re PR rtl-optimization/84071 (wrong elimination of zero-extension after sign-extended...
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 31 Jan 2018 10:03:06 +0000 (10:03 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Wed, 31 Jan 2018 10:03:06 +0000 (10:03 +0000)
PR rtl-optimization/84071
* combine.c (record_dead_and_set_regs_1): Record the source unmodified
for a paradoxical SUBREG on a WORD_REGISTER_OPERATIONS target.

From-SVN: r257224

gcc/ChangeLog
gcc/combine.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20180131-1.c [new file with mode: 0644]

index db2c33536cee5e42d5e2b16bf0d31da9ed1f3eaf..5c1977907f1aedc5546336276172e39893a29ddc 100644 (file)
@@ -1,3 +1,9 @@
+2018-01-31  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR rtl-optimization/84071
+       * combine.c (record_dead_and_set_regs_1): Record the source unmodified
+       for a paradoxical SUBREG on a WORD_REGISTER_OPERATIONS target.
+
 2018-01-31  Claudiu Zissulescu  <claziss@synopsys.com>
 
        * config/arc/arc.c (arc_handle_aux_attribute): New function.
index 6adc0a7d6f8510ff501a949def3560b3115830eb..b14b248800e25e6f418d885f873a5e05b54b3502 100644 (file)
@@ -13245,18 +13245,25 @@ record_dead_and_set_regs_1 (rtx dest, const_rtx setter, void *data)
   if (REG_P (dest))
     {
       /* If we are setting the whole register, we know its value.  Otherwise
-        show that we don't know the value.  We can handle SUBREG in
-        some cases.  */
+        show that we don't know the value.  We can handle a SUBREG if it's
+        the low part, but we must be careful with paradoxical SUBREGs on
+        RISC architectures because we cannot strip e.g. an extension around
+        a load and record the naked load since the RTL middle-end considers
+        that the upper bits are defined according to LOAD_EXTEND_OP.  */
       if (GET_CODE (setter) == SET && dest == SET_DEST (setter))
        record_value_for_reg (dest, record_dead_insn, SET_SRC (setter));
       else if (GET_CODE (setter) == SET
               && GET_CODE (SET_DEST (setter)) == SUBREG
               && SUBREG_REG (SET_DEST (setter)) == dest
-              && known_le (GET_MODE_PRECISION (GET_MODE (dest)), BITS_PER_WORD)
+              && known_le (GET_MODE_PRECISION (GET_MODE (dest)),
+                           BITS_PER_WORD)
               && subreg_lowpart_p (SET_DEST (setter)))
        record_value_for_reg (dest, record_dead_insn,
-                             gen_lowpart (GET_MODE (dest),
-                                                      SET_SRC (setter)));
+                             WORD_REGISTER_OPERATIONS
+                             && paradoxical_subreg_p (SET_DEST (setter))
+                             ? SET_SRC (setter)
+                             : gen_lowpart (GET_MODE (dest),
+                                            SET_SRC (setter)));
       else
        record_value_for_reg (dest, record_dead_insn, NULL_RTX);
     }
index d6bca32809648a7528795167c5ff7b232e90ca2d..13d8e643c57f22511539788ccdc3a623fb24ce24 100644 (file)
@@ -1,3 +1,7 @@
+2018-01-31  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.c-torture/execute/20180131-1.c: New test.
+
 2018-01-31  Claudiu Zissulescu  <claziss@synopsys.com>
 
        * gcc.target/arc/taux-1.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20180131-1.c b/gcc/testsuite/gcc.c-torture/execute/20180131-1.c
new file mode 100644 (file)
index 0000000..76e264b
--- /dev/null
@@ -0,0 +1,28 @@
+/* PR rtl-optimization/84071 */
+/* Reported by Wilco <wilco@gcc.gnu.org> */
+
+extern void abort (void);
+
+typedef union 
+{
+  signed short ss;
+  unsigned short us;
+  int x;
+} U;
+
+int f(int x, int y, int z, int a, U u) __attribute__((noclone, noinline));
+
+int f(int x, int y, int z, int a, U u)
+{
+  return (u.ss <= 0) + u.us;
+}
+
+int main (void)
+{
+  U u = { .ss = -1 };
+
+  if (f (0, 0, 0, 0, u) != (1 << sizeof (short) * 8))
+    abort ();
+
+  return 0;
+}