Elide stores of empty structures for correct support of boost::compressed_pair.  Radar 7659636.

llvm-svn: 99313
diff --git a/llvm-gcc-4.2/gcc/cp/cp-objcp-common.c b/llvm-gcc-4.2/gcc/cp/cp-objcp-common.c
index 8e4d91c..0e2b29c 100644
--- a/llvm-gcc-4.2/gcc/cp/cp-objcp-common.c
+++ b/llvm-gcc-4.2/gcc/cp/cp-objcp-common.c
@@ -111,6 +111,30 @@
     return lhd_expr_size (exp);
 }
 
+/* LLVM LOCAL begin 7659636 */
+/* lang_hooks.empty_type_p: Return true if the given type has size
+   zero.  */
+
+int
+cp_empty_type_p (tree exp)
+{
+  gcc_assert(TYPE_P(exp));
+  if (VOID_TYPE_P(exp))
+    return 0;
+
+  /* C++ classes with non-trivial constructors or non-trivial
+     assignment operators are assumed non-empty, thus assignments of
+     these types can't be elided.  */
+  if (CLASS_TYPE_P(exp)
+      && (TYPE_HAS_COMPLEX_INIT_REF(exp)
+          || TYPE_HAS_COMPLEX_ASSIGN_REF(exp)))
+    return 0;
+
+  return is_empty_class(exp);
+}
+
+/* LLVM LOCAL end 7659636 */
+
 /* Langhook for tree_size: determine size of our 'x' and 'c' nodes.  */
 size_t
 cp_tree_size (enum tree_code code)
diff --git a/llvm-gcc-4.2/gcc/cp/cp-objcp-common.h b/llvm-gcc-4.2/gcc/cp/cp-objcp-common.h
index 2c292ba..a774cbd 100644
--- a/llvm-gcc-4.2/gcc/cp/cp-objcp-common.h
+++ b/llvm-gcc-4.2/gcc/cp/cp-objcp-common.h
@@ -33,6 +33,10 @@
 
 #undef LANG_HOOKS_TREE_SIZE
 #define LANG_HOOKS_TREE_SIZE cp_tree_size
+/* LLVM LOCAL begin 7659636 */
+#undef LANG_HOOKS_EMPTY_TYPE_P
+#define LANG_HOOKS_EMPTY_TYPE_P cp_empty_type_p
+/* LLVM LOCAL end 7659636 */
 #undef LANG_HOOKS_FINISH
 #define LANG_HOOKS_FINISH cxx_finish
 #undef LANG_HOOKS_CLEAR_BINDING_STACK
diff --git a/llvm-gcc-4.2/gcc/cp/cp-tree.h b/llvm-gcc-4.2/gcc/cp/cp-tree.h
index 87abc7e..fb3e980 100644
--- a/llvm-gcc-4.2/gcc/cp/cp-tree.h
+++ b/llvm-gcc-4.2/gcc/cp/cp-tree.h
@@ -4639,6 +4639,8 @@
 extern bool cxx_warn_unused_global_decl		(tree);
 extern tree cp_expr_size			(tree);
 extern size_t cp_tree_size			(enum tree_code);
+/* LLVM LOCAL 7659636 */
+extern int cp_empty_type_p                      (tree);
 extern bool cp_var_mod_type_p			(tree, tree);
 extern void cxx_initialize_diagnostics		(struct diagnostic_context *);
 extern int cxx_types_compatible_p		(tree, tree);
diff --git a/llvm-gcc-4.2/gcc/langhooks-def.h b/llvm-gcc-4.2/gcc/langhooks-def.h
index 63efc3a..bc4cab1 100644
--- a/llvm-gcc-4.2/gcc/langhooks-def.h
+++ b/llvm-gcc-4.2/gcc/langhooks-def.h
@@ -70,6 +70,8 @@
 extern bool lhd_decl_ok_for_sibcall (tree);
 extern const char *lhd_comdat_group (tree);
 extern tree lhd_expr_size (tree);
+/* LLVM LOCAL 7659636 */
+extern int lhd_empty_type_p (tree);
 extern size_t lhd_tree_size (enum tree_code);
 extern HOST_WIDE_INT lhd_to_target_charset (HOST_WIDE_INT);
 extern tree lhd_expr_to_decl (tree, bool *, bool *, bool *);
@@ -139,6 +141,8 @@
 #define LANG_HOOKS_DWARF_NAME		lhd_dwarf_name
 #define LANG_HOOKS_GET_CALLEE_FNDECL	lhd_return_null_tree
 #define LANG_HOOKS_EXPR_SIZE		lhd_expr_size
+/* LLVM LOCAL 7659636 */
+#define LANG_HOOKS_EMPTY_TYPE_P		lhd_empty_type_p
 #define LANG_HOOKS_TREE_SIZE		lhd_tree_size
 #define LANG_HOOKS_TYPES_COMPATIBLE_P	lhd_types_compatible_p
 #define LANG_HOOKS_BUILTIN_FUNCTION	builtin_function
@@ -336,6 +340,8 @@
   LANG_HOOKS_GET_CALLEE_FNDECL, \
   LANG_HOOKS_PRINT_ERROR_FUNCTION, \
   LANG_HOOKS_EXPR_SIZE, \
+/* LLVM LOCAL 7659636 */ \
+  LANG_HOOKS_EMPTY_TYPE_P, \
   LANG_HOOKS_TO_TARGET_CHARSET, \
   LANG_HOOKS_ATTRIBUTE_TABLE, \
   LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, \
diff --git a/llvm-gcc-4.2/gcc/langhooks.c b/llvm-gcc-4.2/gcc/langhooks.c
index 74a332e..7f275bd 100644
--- a/llvm-gcc-4.2/gcc/langhooks.c
+++ b/llvm-gcc-4.2/gcc/langhooks.c
@@ -439,6 +439,21 @@
     return size_in_bytes (TREE_TYPE (exp));
 }
 
+/* LLVM LOCAL begin 7659636 */
+/* lang_hooks.empty_type_p: Return true if the given type has size
+   zero.  */
+
+int
+lhd_empty_type_p (tree exp)
+{
+  gcc_assert(TYPE_P(exp));
+  if (VOID_TYPE_P(exp))
+    return 0;
+  return size_in_bytes(exp) == 0;
+}
+
+/* LLVM LOCAL end 7659636 */
+
 /* lang_hooks.gimplify_expr re-writes *EXPR_P into GIMPLE form.  */
 
 int
diff --git a/llvm-gcc-4.2/gcc/langhooks.h b/llvm-gcc-4.2/gcc/langhooks.h
index 6b17e62..a8f0e82 100644
--- a/llvm-gcc-4.2/gcc/langhooks.h
+++ b/llvm-gcc-4.2/gcc/langhooks.h
@@ -410,6 +410,11 @@
      semantics in cases that it doesn't want to handle specially.  */
   tree (*expr_size) (tree);
 
+/* LLVM LOCAL begin 7659636 */
+  /* Return true (non-zero) if the given RECORD_TYPE has size zero.  */
+  int (*empty_type_p) (tree);
+/* LLVM LOCAL end 7659636 */
+
   /* Convert a character from the host's to the target's character
      set.  The character should be in what C calls the "basic source
      character set" (roughly, the set of characters defined by plain
diff --git a/llvm-gcc-4.2/gcc/llvm-convert.cpp b/llvm-gcc-4.2/gcc/llvm-convert.cpp
index 2c21ac0..9d111ec 100644
--- a/llvm-gcc-4.2/gcc/llvm-convert.cpp
+++ b/llvm-gcc-4.2/gcc/llvm-convert.cpp
@@ -3046,6 +3046,20 @@
   tree lhs = TREE_OPERAND (exp, 0);
   tree rhs = TREE_OPERAND (exp, 1);
 
+  // Avoid generating stores of empty types.  This is rare, but necessary
+  // to support the compressed_pair template.
+  if (lang_hooks.empty_type_p(TREE_TYPE(exp))) {
+    if (TREE_SIDE_EFFECTS(rhs)) {
+      // There's a side-effect; alloc a temporary to receive the
+      // value, if any.  Do not store into lhs; we must not
+      // reference it.
+      const Type *RHSTy = ConvertType(TREE_TYPE(rhs));
+      MemRef dest = CreateTempLoc(RHSTy);
+      return Emit(rhs, &dest);
+    } else
+      return (Value *)0;
+  }
+
   // If this is the definition of a gimple temporary, set its DECL_LLVM to the
   // RHS.
   bool LHSSigned = !TYPE_UNSIGNED(TREE_TYPE(lhs));