]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
expr.c (expand_expr_real_1): For a bit-field destination type...
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 19 Feb 2014 14:45:16 +0000 (14:45 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Wed, 19 Feb 2014 14:45:16 +0000 (14:45 +0000)
* expr.c (expand_expr_real_1) <case VIEW_CONVERT_EXPR>: For a bit-field
destination type, extract only the valid bits if the source type is not
integral and has a different mode.

From-SVN: r207902

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/opt31.adb [new file with mode: 0644]

index a71885409b37888cb92b67ae886c565da426c6ce..eca2f7a780bf8cd53ce88b7505080cc2f58843c1 100644 (file)
@@ -1,3 +1,9 @@
+2014-02-19  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * expr.c (expand_expr_real_1) <case VIEW_CONVERT_EXPR>: For a bit-field
+       destination type, extract only the valid bits if the source type is not
+       integral and has a different mode.
+
 2014-02-19  Richard Biener  <rguenther@suse.de>
 
        PR ipa/60243
index 29ce694704c0d177cae60c562faa51b0c129513a..be62c539e25d62eba0f708b0f3a5f48a6731ae64 100644 (file)
@@ -10436,6 +10436,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       else if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (treeop0)))
        op0 = convert_modes (mode, GET_MODE (op0), op0,
                             TYPE_UNSIGNED (TREE_TYPE (treeop0)));
+      /* If the output type is a bit-field type, do an extraction.  */
+      else if (reduce_bit_field)
+       return extract_bit_field (op0, TYPE_PRECISION (type), 0,
+                                 TYPE_UNSIGNED (type), NULL_RTX,
+                                 mode, mode);
       /* As a last resort, spill op0 to memory, and reload it in a
         different mode.  */
       else if (!MEM_P (op0))
@@ -10458,10 +10463,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          op0 = target;
        }
 
-      /* At this point, OP0 is in the correct mode.  If the output type is
-        such that the operand is known to be aligned, indicate that it is.
-        Otherwise, we need only be concerned about alignment for non-BLKmode
-        results.  */
+      /* If OP0 is (now) a MEM, we need to deal with alignment issues.  If the
+        output type is such that the operand is known to be aligned, indicate
+        that it is.  Otherwise, we need only be concerned about alignment for
+        non-BLKmode results.  */
       if (MEM_P (op0))
        {
          enum insn_code icode;
index a7aa8c2f9d10ee53a434f953e0613c9713a63a2f..c34f640710b7d4ec7412f91b6537d3d803bda278 100644 (file)
@@ -1,3 +1,7 @@
+2014-02-19  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/opt31.adb: New test.
+
 2014-02-19  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * gcc.dg/torture/pr60092.c: xfail execution on *-*-solaris2.11* at -O0.
diff --git a/gcc/testsuite/gnat.dg/opt31.adb b/gcc/testsuite/gnat.dg/opt31.adb
new file mode 100644 (file)
index 0000000..51aa355
--- /dev/null
@@ -0,0 +1,43 @@
+-- { dg-do run }
+-- { dg-options "-O" }
+
+with Interfaces; use Interfaces;
+with Unchecked_Conversion;
+
+procedure Opt31 is
+
+  type Unsigned_24 is new Unsigned_32 range 0 .. 2**24 - 1;
+  subtype Time_T is Unsigned_24 range 0 .. 24 * 60 * 60 * 128 - 1;
+
+  type Messages_T is array (Positive range <>) of Unsigned_8;
+  subtype T_3Bytes is Messages_T (1 .. 3);
+
+  type Rec1 is record
+    F : Time_T;
+  end record;
+  for Rec1 use record
+    F at 0 range 0 .. 23;
+  end record;
+  for Rec1'Size use 24;
+
+  type Rec2 is record
+    I1,I2,I3,I4 : Integer;
+    R1 : Rec1;
+  end record;
+
+  function Conv is new Unchecked_Conversion (T_3Bytes, Rec1);
+
+  procedure Decode (M : Messages_T) is
+    My_Rec2 : Rec2;
+  begin
+    My_Rec2.R1 := Conv (M (1 .. 3));
+    if not My_Rec2.R1.F'Valid then
+      raise Program_Error;
+    end if;
+  end;
+
+  Message : Messages_T (1 .. 4) := (16#18#, 16#0C#, 16#0C#, 16#18#);
+
+begin
+  Decode (Message);
+end;