]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ifcvt: Fix bitpos calculation in bitfield lowering [PR107229]
authorAndre Vieira <andre.simoesdiasvieira@arm.com>
Thu, 13 Oct 2022 11:09:38 +0000 (12:09 +0100)
committerAndre Vieira <andre.simoesdiasvieira@arm.com>
Thu, 13 Oct 2022 11:11:12 +0000 (12:11 +0100)
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.

gcc/ChangeLog:

PR tree-optimization/107229
* 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.

gcc/testsuite/gcc.dg/vect/pr107229-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/pr107229-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/pr107229-3.c [new file with mode: 0644]
gcc/tree-if-conv.cc

diff --git a/gcc/testsuite/gcc.dg/vect/pr107229-1.c b/gcc/testsuite/gcc.dg/vect/pr107229-1.c
new file mode 100644 (file)
index 0000000..67b4323
--- /dev/null
@@ -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 (file)
index 0000000..88bffb6
--- /dev/null
@@ -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 (file)
index 0000000..4abd8c1
--- /dev/null
@@ -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;
+}
index e468a4659fa28a3a31c3390cf19bee65f4590b80..01637c5da08d5a2a00a495522fc9a6436a804398 100644 (file)
@@ -3298,10 +3298,34 @@ 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));
+    {
+      /* To calculate the bitposition of the BITFIELD_REF we have to determine
+        where our bitfield starts in relation to the container REP_DECL. The
+        DECL_FIELD_OFFSET of the original bitfield's member FIELD_DECL tells
+        us how many bytes from the start of the structure there are until the
+        start of the group of bitfield members the FIELD_DECL belongs to,
+        whereas DECL_FIELD_BIT_OFFSET will tell us how many bits from that
+        position our actual bitfield member starts.  For the container
+        REP_DECL adding DECL_FIELD_OFFSET and DECL_FIELD_BIT_OFFSET will tell
+        us the distance between the start of the structure and the start of
+        the container, though the first is in bytes and the later other in
+        bits.  With this in mind we calculate the bit position of our new
+        BITFIELD_REF by subtracting the number of bits between the start of
+        the structure and the container from the number of bits from the start
+        of the structure and the actual bitfield member. */
+      tree bf_pos = fold_build2 (MULT_EXPR, bitsizetype,
+                                DECL_FIELD_OFFSET (field_decl),
+                                build_int_cst (bitsizetype, BITS_PER_UNIT));
+      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, BITS_PER_UNIT));
+      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;