Hi,
The bitposition calculation for the bitfield lowering in loop if
conversion was not
taking DECL_FIELD_OFFSET into account, which meant that it would result in
wrong bitpositions for bitfields that did not end up having representations
starting at the beginning of the struct.
Bootstrappend and regression tested on aarch64-none-linux-gnu and
x86_64-pc-linux-gnu.
gcc/ChangeLog:
PR tree-optimization/107229
* gcc/tree-if-conv.cc (get_bitfield_rep): Fix bitposition calculation.
gcc/testsuite/ChangeLog:
* gcc.dg/vect/pr107229-1.c: New test.
* gcc.dg/vect/pr107229-2.c: New test.
* gcc.dg/vect/pr107229-3.c: New test.
diff --git a/gcc/testsuite/gcc.dg/vect/pr107229-1.c
b/gcc/testsuite/gcc.dg/vect/pr107229-1.c
new file mode 100644
index
0000000000000000000000000000000000000000..67b432383d057a630746aa00af50c25fcb527d8e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr107229-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* PR tree-optimization/107229. */
+
+int a, c;
+struct {
+ long d;
+ int : 8;
+ int : 27;
+ int e : 21;
+} f;
+void g(int b) { a = a & 1; }
+int main() {
+ while (c)
+ g(f.e);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr107229-2.c
b/gcc/testsuite/gcc.dg/vect/pr107229-2.c
new file mode 100644
index
0000000000000000000000000000000000000000..88bffb63d5e8b2d7bcdeae223f4ec6ea4f611bc9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr107229-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* PR tree-optimization/107229. */
+
+int a, c;
+struct {
+ long f;
+ long g;
+ long d;
+ int : 8;
+ int : 27;
+ int e : 21;
+} f;
+void g(int b) { a = a & 1; }
+int main() {
+ while (c)
+ g(f.e);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr107229-3.c
b/gcc/testsuite/gcc.dg/vect/pr107229-3.c
new file mode 100644
index
0000000000000000000000000000000000000000..4abd8c14531b40e9dbe9802a8f9a0eabba673c9f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr107229-3.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* PR tree-optimization/107229. */
+
+int a, c;
+struct {
+ long f;
+ long g;
+ long d;
+ int : 8;
+ int : 32;
+ int : 2;
+ int e : 21;
+} f;
+void g(int b) { a = a & 1; }
+int main() {
+ while (c)
+ g(f.e);
+ return 0;
+}
diff --git a/gcc/tree-if-conv.cc b/gcc/tree-if-conv.cc
index
e468a4659fa28a3a31c3390cf19bee65f4590b80..33160ddef80cbd75c2a927fb50bddd792bbf5dd4
100644
--- a/gcc/tree-if-conv.cc
+++ b/gcc/tree-if-conv.cc
@@ -3298,10 +3298,20 @@ get_bitfield_rep (gassign *stmt, bool write, tree
*bitpos,
*struct_expr = TREE_OPERAND (comp_ref, 0);
if (bitpos)
- *bitpos
- = fold_build2 (MINUS_EXPR, bitsizetype,
- DECL_FIELD_BIT_OFFSET (field_decl),
- DECL_FIELD_BIT_OFFSET (rep_decl));
+ {
+ tree bf_pos = fold_build2 (MULT_EXPR, bitsizetype,
+ DECL_FIELD_OFFSET (field_decl),
+ build_int_cst (bitsizetype, 8));
+ bf_pos = fold_build2 (PLUS_EXPR, bitsizetype, bf_pos,
+ DECL_FIELD_BIT_OFFSET (field_decl));
+ tree rep_pos = fold_build2 (MULT_EXPR, bitsizetype,
+ DECL_FIELD_OFFSET (rep_decl),
+ build_int_cst (bitsizetype, 8));
+ rep_pos = fold_build2 (PLUS_EXPR, bitsizetype, rep_pos,
+ DECL_FIELD_BIT_OFFSET (rep_decl));
+
+ *bitpos = fold_build2 (MINUS_EXPR, bitsizetype, bf_pos, rep_pos);
+ }
return rep_decl;