120 lines
3.5 KiB
Diff
120 lines
3.5 KiB
Diff
|
|
From 13dfb01e5c30c3bd09333ac79d6ff96a617fea67 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Richard Biener <rguenther@suse.de>
|
||
|
|
Date: Thu, 3 Aug 2023 13:11:12 +0200
|
||
|
|
Subject: [PATCH] tree-optimization/110702 - avoid zero-based memory references
|
||
|
|
in IVOPTs
|
||
|
|
|
||
|
|
Sometimes IVOPTs chooses a weird induction variable which downstream
|
||
|
|
leads to issues. Most of the times we can fend those off during costing
|
||
|
|
by rejecting the candidate but it looks like the address description
|
||
|
|
costing synthesizes is different from what we end up generating so
|
||
|
|
the following fixes things up at code generation time. Specifically
|
||
|
|
we avoid the create_mem_ref_raw fallback which uses a literal zero
|
||
|
|
address base with the actual base in index2. For the case in question
|
||
|
|
we have the address
|
||
|
|
|
||
|
|
type = unsigned long
|
||
|
|
offset = 0
|
||
|
|
elements = {
|
||
|
|
[0] = &e * -3,
|
||
|
|
[1] = (sizetype) a.9_30 * 232,
|
||
|
|
[2] = ivtmp.28_44 * 4
|
||
|
|
}
|
||
|
|
|
||
|
|
from which we code generate the problematical
|
||
|
|
|
||
|
|
_3 = MEM[(long int *)0B + ivtmp.36_9 + ivtmp.28_44 * 4];
|
||
|
|
|
||
|
|
which references the object at address zero. The patch below
|
||
|
|
recognizes the fallback after the fact and transforms the
|
||
|
|
TARGET_MEM_REF memory reference into a LEA for which this form
|
||
|
|
isn't problematic:
|
||
|
|
|
||
|
|
_24 = &MEM[(long int *)0B + ivtmp.36_34 + ivtmp.28_44 * 4];
|
||
|
|
_3 = *_24;
|
||
|
|
|
||
|
|
hereby avoiding the correctness issue. We'd later conclude the
|
||
|
|
program terminates at the null pointer dereference and make the
|
||
|
|
function pure, miscompling the main function of the testcase.
|
||
|
|
|
||
|
|
PR tree-optimization/110702
|
||
|
|
* tree-ssa-loop-ivopts.cc (rewrite_use_address): When
|
||
|
|
we created a NULL pointer based access rewrite that to
|
||
|
|
a LEA.
|
||
|
|
|
||
|
|
* gcc.dg/torture/pr110702.c: New testcase.
|
||
|
|
---
|
||
|
|
gcc/testsuite/gcc.dg/torture/pr110702.c | 31 +++++++++++++++++++++++++
|
||
|
|
gcc/tree-ssa-loop-ivopts.cc | 17 +++++++++++++-
|
||
|
|
2 files changed, 47 insertions(+), 1 deletion(-)
|
||
|
|
create mode 100644 gcc/testsuite/gcc.dg/torture/pr110702.c
|
||
|
|
|
||
|
|
diff --git a/gcc/testsuite/gcc.dg/torture/pr110702.c b/gcc/testsuite/gcc.dg/torture/pr110702.c
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..aab9c7d923e
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/gcc.dg/torture/pr110702.c
|
||
|
|
@@ -0,0 +1,31 @@
|
||
|
|
+/* { dg-do run } */
|
||
|
|
+
|
||
|
|
+void abort (void);
|
||
|
|
+
|
||
|
|
+int a, b, c, d;
|
||
|
|
+long e[9][7][4];
|
||
|
|
+
|
||
|
|
+void f()
|
||
|
|
+{
|
||
|
|
+ for (; a >= 0; a--)
|
||
|
|
+ {
|
||
|
|
+ b = 0;
|
||
|
|
+ for (; b <= 3; b++)
|
||
|
|
+ {
|
||
|
|
+ c = 0;
|
||
|
|
+ for (; c <= 3; c++)
|
||
|
|
+ {
|
||
|
|
+ int *g = &d;
|
||
|
|
+ *g = e[0][0][b] | e[a][b][a];
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+int main()
|
||
|
|
+{
|
||
|
|
+ f();
|
||
|
|
+ if (a != -1)
|
||
|
|
+ abort ();
|
||
|
|
+ return 0;
|
||
|
|
+}
|
||
|
|
diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc
|
||
|
|
index 92fc1c7d734..934897af691 100644
|
||
|
|
--- a/gcc/tree-ssa-loop-ivopts.cc
|
||
|
|
+++ b/gcc/tree-ssa-loop-ivopts.cc
|
||
|
|
@@ -7630,7 +7630,22 @@ rewrite_use_address (struct ivopts_data *data,
|
||
|
|
true, GSI_SAME_STMT);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
- copy_ref_info (ref, *use->op_p);
|
||
|
|
+ {
|
||
|
|
+ /* When we end up confused enough and have no suitable base but
|
||
|
|
+ stuffed everything to index2 use a LEA for the address and
|
||
|
|
+ create a plain MEM_REF to avoid basing a memory reference
|
||
|
|
+ on address zero which create_mem_ref_raw does as fallback. */
|
||
|
|
+ if (TREE_CODE (ref) == TARGET_MEM_REF
|
||
|
|
+ && TMR_INDEX2 (ref) != NULL_TREE
|
||
|
|
+ && integer_zerop (TREE_OPERAND (ref, 0)))
|
||
|
|
+ {
|
||
|
|
+ ref = fold_build1 (ADDR_EXPR, TREE_TYPE (TREE_OPERAND (ref, 0)), ref);
|
||
|
|
+ ref = force_gimple_operand_gsi (&bsi, ref, true, NULL_TREE,
|
||
|
|
+ true, GSI_SAME_STMT);
|
||
|
|
+ ref = build2 (MEM_REF, type, ref, build_zero_cst (alias_ptr_type));
|
||
|
|
+ }
|
||
|
|
+ copy_ref_info (ref, *use->op_p);
|
||
|
|
+ }
|
||
|
|
|
||
|
|
*use->op_p = ref;
|
||
|
|
}
|
||
|
|
--
|
||
|
|
2.45.2
|
||
|
|
|