The following fixes the failure to adjust for sub-byte padding of
the partial definition before the object when pruning the size
to sub-byte padding after the object.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.
PR tree-optimization/127377
* tree-ssa-sccvn.cc (vn_walk_cb_data::push_partial_def):
Properly consider the padding before the object when
pruning the size.
* gcc.dg/torture/pr127377.c: New testcase.
---
gcc/testsuite/gcc.dg/torture/pr127377.c | 40 +++++++++++++++++++++++++
gcc/tree-ssa-sccvn.cc | 5 ++--
2 files changed, 43 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/torture/pr127377.c
diff --git a/gcc/testsuite/gcc.dg/torture/pr127377.c
b/gcc/testsuite/gcc.dg/torture/pr127377.c
new file mode 100644
index 00000000000..13fb8f25ca7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr127377.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+__attribute__((noipa))
+int q(void) {
+ struct h {
+ unsigned i : 1;
+ int : 1;
+ unsigned j : 3;
+ int k : 7;
+ int : 3;
+ int aa : 6;
+ unsigned l : 7;
+ };
+ union {
+ int m;
+ signed char b[4];
+ struct h ab;
+ } n = {};
+ int o;
+ n.m = 0x550f;
+ for (int i = 0; i < 1; i++)
+ {
+ n.b[2] = n.ab.i + n.ab.aa;
+ n.m = n.m & ~28u | ((0x7 ^ n.ab.aa) & 7) << 2;
+ }
+ n.b[3] = 0;
+ n.m = n.m | 0x08000000;
+ n.b[2] = 0x7;
+ o = n.ab.l;
+ return o;
+}
+
+int main()
+{
+ int t1 = q();
+ if (t1 != 64)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index bfc227f7ca0..997a37a6647 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -2080,8 +2080,9 @@ vn_walk_cb_data::push_partial_def (pd_data pd,
pd.size -= o;
pd.offset += o;
}
- if (pd.size > maxsizei)
- pd.size = maxsizei + ((pd.size - maxsizei) % BITS_PER_UNIT);
+ if (pd.size + pd.offset > offseti + maxsizei)
+ pd.size = maxsizei + ((pd.size + pd.offset - offseti - maxsizei)
+ % BITS_PER_UNIT);
}
pd.offset -= offseti;
--
2.51.0