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));