Hello,
Please find the updated version of the patch in the attachment. It has
addressed the previous comments and also included some changes in order
to pass the bootstrapping on x86_64.
It's also passed the regtest on arm-none-eabi and aarch64-none-elf.
It will also fix the test failure as reported here:
http://gcc.gnu.org/ml/gcc-patches/2013-09/msg01317.html
OK for the trunk?
Thanks,
Yufeng
gcc/
* gimple-ssa-strength-reduction.c (safe_to_multiply_p): New
function.
(backtrace_base_for_ref): Call get_unwidened, check 'base_in'
again and set unwidend_p with true; call safe_to_multiply_p to
avoid
unsafe unwidened cases.
gcc/testsuite/
* gcc.dg/tree-ssa/slsr-40.c: New test.
On 09/11/13 13:39, Bill Schmidt wrote:
On Wed, 2013-09-11 at 10:32 +0200, Richard Biener wrote:
On Tue, Sep 10, 2013 at 5:53 PM, Yufeng Zhang<yufeng.zh...@arm.com> wrote:
Hi,
Following Bin's patch in
http://gcc.gnu.org/ml/gcc-patches/2013-09/msg00695.html, this patch tweaks
backtrace_base_for_ref () to strip of any widening conversion after the
first TREE_CODE check fails. Without this patch, the test
(gcc.dg/tree-ssa/slsr-39.c) in Bin's patch will fail on AArch64, as
backtrace_base_for_ref () will stop if not seeing an ssa_name since the tree
code can be nop_expr instead.
Regtested on arm and aarch64; still bootstrapping x86_64.
OK for the trunk if the x86_64 bootstrap succeeds?
Please add a testcase.
Also, the comment "Strip of" should read "Strip off". Otherwise I have
no comments.
Thanks,
Bill
Richard.
diff --git a/gcc/gimple-ssa-strength-reduction.c
b/gcc/gimple-ssa-strength-reduction.c
index 8d48add..1c04382 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -750,6 +750,40 @@ slsr_process_phi (gimple phi, bool speed)
add_cand_for_stmt (phi, c);
}
+/* Utility function for backtrace_base_for_ref.
+
+ Given
+
+ T2 = T2' + CST
+ RES = (wider_type) T2 * C3
+
+ where TYPE is TREE_TYPE (T2), this function returns false when it is
+ _not_ safe to carry out the following transformation.
+
+ RES = (wider_type) T2' * C3 + (wider_type) CST * C3
+
+ One example unsafe case is:
+
+ int array[40];
+ array[n - 1]
+
+ where n is a 32-bit unsigned int and pointer are 64-bit long. In this
+ case, the gimple for (n - 1) is:
+
+ _2 = n_1(D) + 4294967295; // 0xFFFFFFFF
+
+ and it is wrong to multiply the large constant by 4 in the 64-bit space. */
+
+static bool
+safe_to_multiply_p (tree type, double_int cst)
+{
+ if (TYPE_UNSIGNED (type)
+ && ! double_int_fits_to_tree_p (signed_type_for (type), cst))
+ return false;
+
+ return true;
+}
+
/* Given PBASE which is a pointer to tree, look up the defining
statement for it and check whether the candidate is in the
form of:
@@ -766,10 +800,19 @@ backtrace_base_for_ref (tree *pbase)
{
tree base_in = *pbase;
slsr_cand_t base_cand;
+ bool unwidened_p = false;
STRIP_NOPS (base_in);
if (TREE_CODE (base_in) != SSA_NAME)
- return tree_to_double_int (integer_zero_node);
+ {
+ /* Strip off widening conversion(s) to handle cases where
+ e.g. 'B' is widened from an 'int' in order to calculate
+ a 64-bit address. */
+ base_in = get_unwidened (base_in, NULL_TREE);
+ if (TREE_CODE (base_in) != SSA_NAME)
+ return tree_to_double_int (integer_zero_node);
+ unwidened_p = true;
+ }
base_cand = base_cand_from_table (base_in);
@@ -777,7 +820,10 @@ backtrace_base_for_ref (tree *pbase)
{
if (base_cand->kind == CAND_ADD
&& base_cand->index.is_one ()
- && TREE_CODE (base_cand->stride) == INTEGER_CST)
+ && TREE_CODE (base_cand->stride) == INTEGER_CST
+ && (! unwidened_p
+ || safe_to_multiply_p (TREE_TYPE (base_cand->stride),
+ tree_to_double_int (base_cand->stride))))
{
/* X = B + (1 * S), S is integer constant. */
*pbase = base_cand->base_expr;
@@ -785,8 +831,11 @@ backtrace_base_for_ref (tree *pbase)
}
else if (base_cand->kind == CAND_ADD
&& TREE_CODE (base_cand->stride) == INTEGER_CST
- && integer_onep (base_cand->stride))
- {
+ && integer_onep (base_cand->stride)
+ && (! unwidened_p
+ || safe_to_multiply_p (TREE_TYPE (base_cand->base_expr),
+ base_cand->index)))
+ {
/* X = B + (i * S), S is integer one. */
*pbase = base_cand->base_expr;
return base_cand->index;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-40.c
b/gcc/testsuite/gcc.dg/tree-ssa/slsr-40.c
new file mode 100644
index 0000000..72726a3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-40.c
@@ -0,0 +1,27 @@
+/* Verify straight-line strength reduction for array
+ subscripting.
+
+ elems[n-1] is reduced to elems + n * 4 + 0xffffffff * 4, only when
+ pointers are of the same size as that of int (assuming 4 bytes). */
+
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+struct data
+{
+ unsigned long elms[1];
+} gData;
+
+void __attribute__((noinline))
+foo (struct data *dst, unsigned int n)
+{
+ dst->elms[n - 1] &= 1;
+}
+
+int
+main ()
+{
+ foo (&gData, 1);
+ return 0;
+}
+