* [PATCH] Split "re-gimplification" path somewhat out of fold_stmt
@ 2014-08-18 14:16 Richard Biener
0 siblings, 0 replies; only message in thread
From: Richard Biener @ 2014-08-18 14:16 UTC (permalink / raw)
To: gcc-patches
This is a first step towards re-gimplifying statements with
propagated addresses in the core propagation routines that
already deal (well, some of them...) with computing invariantness.
The patch moves all such re-gimplification before any simplifications
are performed (which means once "fixed" this can turn into
asserts only).
This makes it possible for match-and-simplify to wire in
before all existing manual foldings (well, more easily at least).
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
I couldn't resist fixing a possible wrong-code issue wrt
dropping alignment.
I will explore pushing this re-gimplification into the propagation
places / helpers instead as followups.
Not sure if it is worth retaining other folding for GIMPLE_DEBUGs
or GIMPLE_ASMs (what remains is folding from constant initializers).
Richard.
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.
Index: gcc/gimple-fold.c
===================================================================
--- gcc/gimple-fold.c (revision 214085)
+++ gcc/gimple-fold.c (working copy)
@@ -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
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 +2755,86 @@ gimple_fold_call (gimple_stmt_iterator *
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
+ && 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 (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 +2845,78 @@ fold_stmt_1 (gimple_stmt_iterator *gsi,
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))
{
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2014-08-18 14:16 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-18 14:16 [PATCH] Split "re-gimplification" path somewhat out of fold_stmt Richard Biener
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).