summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2014-08-18 14:30:30 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2014-08-18 14:30:30 +0000
commit1bd2e4a08001b07ffaff2347a65c2d4f10682731 (patch)
tree0cc63ddc60f5c1363dc3604fb6bc2a51989dfef4
parent39c98dee75836f564a5efd5df7ca25cd5b6dcdbf (diff)
downloadgcc-1bd2e4a08001b07ffaff2347a65c2d4f10682731.tar.gz
2014-08-18 Richard Biener <rguenther@suse.de>
* gimple-fold.c (maybe_fold_reference): Move re-gimplification code to ... (maybe_canonicalize_mem_ref_addr): ... this function. (fold_stmt_1): Apply it here before all simplification. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@214103 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/gimple-fold.c215
2 files changed, 161 insertions, 61 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 95f5de9a682..f471e2cc48d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2014-08-18 Richard Biener <rguenther@suse.de>
+
+ * gimple-fold.c (maybe_fold_reference): Move re-gimplification
+ code to ...
+ (maybe_canonicalize_mem_ref_addr): ... this function.
+ (fold_stmt_1): Apply it here before all simplification.
+
2014-08-18 Ilya Enkovich <ilya.enkovich@intel.com>
PR ipa/61800
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 4fa1a3579c3..d34be0a2906 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -256,7 +256,6 @@ get_symbol_constant_value (tree sym)
static tree
maybe_fold_reference (tree expr, bool is_lhs)
{
- tree *t = &expr;
tree result;
if ((TREE_CODE (expr) == VIEW_CONVERT_EXPR
@@ -276,71 +275,11 @@ maybe_fold_reference (tree expr, bool is_lhs)
TREE_OPERAND (expr, 1),
TREE_OPERAND (expr, 2));
- while (handled_component_p (*t))
- t = &TREE_OPERAND (*t, 0);
-
- /* Canonicalize MEM_REFs invariant address operand. Do this first
- to avoid feeding non-canonical MEM_REFs elsewhere. */
- if (TREE_CODE (*t) == MEM_REF
- && !is_gimple_mem_ref_addr (TREE_OPERAND (*t, 0)))
- {
- bool volatile_p = TREE_THIS_VOLATILE (*t);
- tree tem = fold_binary (MEM_REF, TREE_TYPE (*t),
- TREE_OPERAND (*t, 0),
- TREE_OPERAND (*t, 1));
- if (tem)
- {
- TREE_THIS_VOLATILE (tem) = volatile_p;
- *t = tem;
- tem = maybe_fold_reference (expr, is_lhs);
- if (tem)
- return tem;
- return expr;
- }
- }
-
if (!is_lhs
&& (result = fold_const_aggregate_ref (expr))
&& is_gimple_min_invariant (result))
return result;
- /* Fold back MEM_REFs to reference trees. */
- if (TREE_CODE (*t) == MEM_REF
- && TREE_CODE (TREE_OPERAND (*t, 0)) == ADDR_EXPR
- && integer_zerop (TREE_OPERAND (*t, 1))
- && (TREE_THIS_VOLATILE (*t)
- == TREE_THIS_VOLATILE (TREE_OPERAND (TREE_OPERAND (*t, 0), 0)))
- && !TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (*t, 1)))
- && (TYPE_MAIN_VARIANT (TREE_TYPE (*t))
- == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (TREE_OPERAND (*t, 1)))))
- /* We have to look out here to not drop a required conversion
- from the rhs to the lhs if is_lhs, but we don't have the
- rhs here to verify that. Thus require strict type
- compatibility. */
- && types_compatible_p (TREE_TYPE (*t),
- TREE_TYPE (TREE_OPERAND
- (TREE_OPERAND (*t, 0), 0))))
- {
- tree tem;
- *t = TREE_OPERAND (TREE_OPERAND (*t, 0), 0);
- tem = maybe_fold_reference (expr, is_lhs);
- if (tem)
- return tem;
- return expr;
- }
- else if (TREE_CODE (*t) == TARGET_MEM_REF)
- {
- tree tem = maybe_fold_tmr (*t);
- if (tem)
- {
- *t = tem;
- tem = maybe_fold_reference (expr, is_lhs);
- if (tem)
- return tem;
- return expr;
- }
- }
-
return NULL_TREE;
}
@@ -2678,6 +2617,88 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
return changed;
}
+/* Canonicalize MEM_REFs invariant address operand after propagation. */
+
+static bool
+maybe_canonicalize_mem_ref_addr (tree *t)
+{
+ bool res = false;
+
+ if (TREE_CODE (*t) == ADDR_EXPR)
+ t = &TREE_OPERAND (*t, 0);
+
+ while (handled_component_p (*t))
+ t = &TREE_OPERAND (*t, 0);
+
+ /* Canonicalize MEM [&foo.bar, 0] which appears after propagating
+ of invariant addresses into a SSA name MEM_REF address. */
+ if (TREE_CODE (*t) == MEM_REF
+ || TREE_CODE (*t) == TARGET_MEM_REF)
+ {
+ tree addr = TREE_OPERAND (*t, 0);
+ if (TREE_CODE (addr) == ADDR_EXPR
+ && (TREE_CODE (TREE_OPERAND (addr, 0)) == MEM_REF
+ || handled_component_p (TREE_OPERAND (addr, 0))))
+ {
+ tree base;
+ HOST_WIDE_INT coffset;
+ base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
+ &coffset);
+ if (!base)
+ gcc_unreachable ();
+
+ TREE_OPERAND (*t, 0) = build_fold_addr_expr (base);
+ TREE_OPERAND (*t, 1) = int_const_binop (PLUS_EXPR,
+ TREE_OPERAND (*t, 1),
+ size_int (coffset));
+ res = true;
+ }
+ gcc_checking_assert (TREE_CODE (TREE_OPERAND (*t, 0)) == DEBUG_EXPR_DECL
+ || is_gimple_mem_ref_addr (TREE_OPERAND (*t, 0)));
+ }
+
+ /* Canonicalize back MEM_REFs to plain reference trees if the object
+ accessed is a decl that has the same access semantics as the MEM_REF. */
+ if (TREE_CODE (*t) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (*t, 0)) == ADDR_EXPR
+ && integer_zerop (TREE_OPERAND (*t, 1)))
+ {
+ tree decl = TREE_OPERAND (TREE_OPERAND (*t, 0), 0);
+ tree alias_type = TREE_TYPE (TREE_OPERAND (*t, 1));
+ if (/* Same volatile qualification. */
+ TREE_THIS_VOLATILE (*t) == TREE_THIS_VOLATILE (decl)
+ /* Same TBAA behavior with -fstrict-aliasing. */
+ && !TYPE_REF_CAN_ALIAS_ALL (alias_type)
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (decl))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (alias_type)))
+ /* Same alignment. */
+ && TYPE_ALIGN (TREE_TYPE (decl)) == TYPE_ALIGN (TREE_TYPE (*t))
+ /* We have to look out here to not drop a required conversion
+ from the rhs to the lhs if *t appears on the lhs or vice-versa
+ if it appears on the rhs. Thus require strict type
+ compatibility. */
+ && types_compatible_p (TREE_TYPE (*t), TREE_TYPE (decl)))
+ {
+ *t = TREE_OPERAND (TREE_OPERAND (*t, 0), 0);
+ res = true;
+ }
+ }
+
+ /* Canonicalize TARGET_MEM_REF in particular with respect to
+ the indexes becoming constant. */
+ else if (TREE_CODE (*t) == TARGET_MEM_REF)
+ {
+ tree tem = maybe_fold_tmr (*t);
+ if (tem)
+ {
+ *t = tem;
+ res = true;
+ }
+ }
+
+ return res;
+}
+
/* Worker for both fold_stmt and fold_stmt_inplace. The INPLACE argument
distinguishes both cases. */
@@ -2688,6 +2709,78 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
gimple stmt = gsi_stmt (*gsi);
unsigned i;
+ /* First do required canonicalization of [TARGET_]MEM_REF addresses
+ after propagation.
+ ??? This shouldn't be done in generic folding but in the
+ propagation helpers which also know whether an address was
+ propagated. */
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_ASSIGN:
+ if (gimple_assign_rhs_class (stmt) == GIMPLE_SINGLE_RHS)
+ {
+ tree *rhs = gimple_assign_rhs1_ptr (stmt);
+ if ((REFERENCE_CLASS_P (*rhs)
+ || TREE_CODE (*rhs) == ADDR_EXPR)
+ && maybe_canonicalize_mem_ref_addr (rhs))
+ changed = true;
+ tree *lhs = gimple_assign_lhs_ptr (stmt);
+ if (REFERENCE_CLASS_P (*lhs)
+ && maybe_canonicalize_mem_ref_addr (lhs))
+ changed = true;
+ }
+ break;
+ case GIMPLE_CALL:
+ {
+ for (i = 0; i < gimple_call_num_args (stmt); ++i)
+ {
+ tree *arg = gimple_call_arg_ptr (stmt, i);
+ if (REFERENCE_CLASS_P (*arg)
+ && maybe_canonicalize_mem_ref_addr (arg))
+ changed = true;
+ }
+ tree *lhs = gimple_call_lhs_ptr (stmt);
+ if (*lhs
+ && REFERENCE_CLASS_P (*lhs)
+ && maybe_canonicalize_mem_ref_addr (lhs))
+ changed = true;
+ break;
+ }
+ case GIMPLE_ASM:
+ {
+ for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
+ {
+ tree link = gimple_asm_output_op (stmt, i);
+ tree op = TREE_VALUE (link);
+ if (REFERENCE_CLASS_P (op)
+ && maybe_canonicalize_mem_ref_addr (&TREE_VALUE (link)))
+ changed = true;
+ }
+ for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
+ {
+ tree link = gimple_asm_input_op (stmt, i);
+ tree op = TREE_VALUE (link);
+ if ((REFERENCE_CLASS_P (op)
+ || TREE_CODE (op) == ADDR_EXPR)
+ && maybe_canonicalize_mem_ref_addr (&TREE_VALUE (link)))
+ changed = true;
+ }
+ }
+ break;
+ case GIMPLE_DEBUG:
+ if (gimple_debug_bind_p (stmt))
+ {
+ tree *val = gimple_debug_bind_get_value_ptr (stmt);
+ if (*val
+ && (REFERENCE_CLASS_P (*val)
+ || TREE_CODE (*val) == ADDR_EXPR)
+ && maybe_canonicalize_mem_ref_addr (val))
+ changed = true;
+ }
+ break;
+ default:;
+ }
+
/* Fold the main computation performed by the statement. */
switch (gimple_code (stmt))
{