re PR target/85582 (wrong code at -O1 and above on x86_64-linux-gnu in 32-bit mode)
authorJakub Jelinek <jakub@redhat.com>
Wed, 2 May 2018 21:56:17 +0000 (23:56 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 2 May 2018 21:56:17 +0000 (23:56 +0200)
PR target/85582
* config/i386/i386.md (*ashl<dwi>3_doubleword_mask,
*ashl<dwi>3_doubleword_mask_1, *<shift_insn><dwi>3_doubleword_mask,
*<shift_insn><dwi>3_doubleword_mask_1): In condition require that
the highest significant bit of the shift count mask is clear.  In
check whether and[sq]i3 is needed verify that all significant bits
of the shift count other than the highest are set.

* gcc.c-torture/execute/pr85582-3.c: New test.

From-SVN: r259862

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr85582-3.c [new file with mode: 0644]

index 806f74cc3b76887c1f50a632db92f8c775ed5d0d..9074715cf0cc3ac30a0289c544e3fb19e1dfa02d 100644 (file)
@@ -1,3 +1,13 @@
+2018-05-02  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/85582
+       * config/i386/i386.md (*ashl<dwi>3_doubleword_mask,
+       *ashl<dwi>3_doubleword_mask_1, *<shift_insn><dwi>3_doubleword_mask,
+       *<shift_insn><dwi>3_doubleword_mask_1): In condition require that
+       the highest significant bit of the shift count mask is clear.  In
+       check whether and[sq]i3 is needed verify that all significant bits
+       of the shift count other than the highest are set.
+
 2018-05-02  Tom de Vries  <tom@codesourcery.com>
 
        PR libgomp/82428
index 5913424cfc18791ac9644bad1414b41d892d689c..3aa27331187afd65cc2b428b82ddc9a61b7de2d5 100644 (file)
              (match_operand:SI 2 "register_operand" "c")
              (match_operand:SI 3 "const_int_operand")) 0)))
    (clobber (reg:CC FLAGS_REG))]
-  "INTVAL (operands[3]) <= (<MODE_SIZE> * BITS_PER_UNIT) - 1
+  "(INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT)) == 0
    && can_create_pseudo_p ()"
   "#"
   "&& 1"
 
   operands[8] = GEN_INT (<MODE_SIZE> * BITS_PER_UNIT);
 
-  if (INTVAL (operands[3]) < (<MODE_SIZE> * BITS_PER_UNIT) - 1)
+  if ((INTVAL (operands[3]) & ((<MODE_SIZE> * BITS_PER_UNIT) - 1))
+      != ((<MODE_SIZE> * BITS_PER_UNIT) - 1))
     {
       rtx tem = gen_reg_rtx (SImode);
       emit_insn (gen_andsi3 (tem, operands[2], operands[3]));
            (match_operand:QI 2 "register_operand" "c")
            (match_operand:QI 3 "const_int_operand"))))
    (clobber (reg:CC FLAGS_REG))]
-  "INTVAL (operands[3]) <= (<MODE_SIZE> * BITS_PER_UNIT) - 1
+  "(INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT)) == 0
    && can_create_pseudo_p ()"
   "#"
   "&& 1"
 
   operands[8] = GEN_INT (<MODE_SIZE> * BITS_PER_UNIT);
 
-  if (INTVAL (operands[3]) < (<MODE_SIZE> * BITS_PER_UNIT) - 1)
+  if ((INTVAL (operands[3]) & ((<MODE_SIZE> * BITS_PER_UNIT) - 1))
+      != ((<MODE_SIZE> * BITS_PER_UNIT) - 1))
     {
       rtx tem = gen_reg_rtx (QImode);
       emit_insn (gen_andqi3 (tem, operands[2], operands[3]));
              (match_operand:SI 2 "register_operand" "c")
              (match_operand:SI 3 "const_int_operand")) 0)))
    (clobber (reg:CC FLAGS_REG))]
-  "INTVAL (operands[3]) <= (<MODE_SIZE> * BITS_PER_UNIT) - 1
+  "(INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT)) == 0
    && can_create_pseudo_p ()"
   "#"
   "&& 1"
 
   operands[8] = GEN_INT (<MODE_SIZE> * BITS_PER_UNIT);
 
-  if (INTVAL (operands[3]) < (<MODE_SIZE> * BITS_PER_UNIT)-1)
+  if ((INTVAL (operands[3]) & ((<MODE_SIZE> * BITS_PER_UNIT) - 1))
+      != ((<MODE_SIZE> * BITS_PER_UNIT) - 1))
     {
       rtx tem = gen_reg_rtx (SImode);
       emit_insn (gen_andsi3 (tem, operands[2], operands[3]));
            (match_operand:QI 2 "register_operand" "c")
            (match_operand:QI 3 "const_int_operand"))))
    (clobber (reg:CC FLAGS_REG))]
-  "INTVAL (operands[3]) <= (<MODE_SIZE> * BITS_PER_UNIT) - 1
+  "(INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT)) == 0
    && can_create_pseudo_p ()"
   "#"
   "&& 1"
 
   operands[8] = GEN_INT (<MODE_SIZE> * BITS_PER_UNIT);
 
-  if (INTVAL (operands[3]) < (<MODE_SIZE> * BITS_PER_UNIT) - 1)
+  if ((INTVAL (operands[3]) & ((<MODE_SIZE> * BITS_PER_UNIT) - 1))
+      != ((<MODE_SIZE> * BITS_PER_UNIT) - 1))
     {
       rtx tem = gen_reg_rtx (QImode);
       emit_insn (gen_andqi3 (tem, operands[2], operands[3]));
index 6ddb945c70e60c92eab1bd260d5784547855e20a..670845608fad4aea7fb848f05a8c6e89a303c04f 100644 (file)
@@ -1,3 +1,8 @@
+2018-05-02  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/85582
+       * gcc.c-torture/execute/pr85582-3.c: New test.
+
 2018-05-02  Paolo Carlini  <paolo.carlini@oracle.com>
            Jason Merrill  <jason@redhat.com>
 
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr85582-3.c b/gcc/testsuite/gcc.c-torture/execute/pr85582-3.c
new file mode 100644 (file)
index 0000000..99deb47
--- /dev/null
@@ -0,0 +1,55 @@
+/* PR target/85582 */
+
+#ifdef __SIZEOF_INT128__
+typedef __int128 S;
+typedef unsigned __int128 U;
+#else
+typedef long long S;
+typedef unsigned long long U;
+#endif
+
+__attribute__((noipa)) U
+f1 (U x, int y)
+{
+  return x << (y & -2);
+}
+
+__attribute__((noipa)) S
+f2 (S x, int y)
+{
+  return x >> (y & -2);
+}
+
+__attribute__((noipa)) U
+f3 (U x, int y)
+{
+  return x >> (y & -2);
+}
+
+int
+main ()
+{
+  U a = (U) 1 << (sizeof (U) * __CHAR_BIT__ - 7);
+  if (f1 (a, 5) != ((U) 1 << (sizeof (S) * __CHAR_BIT__ - 3)))
+    __builtin_abort ();
+  S b = (U) 0x101 << (sizeof (S) * __CHAR_BIT__ / 2 - 7);
+  if (f1 (b, sizeof (S) * __CHAR_BIT__ / 2) != (U) 0x101 << (sizeof (S) * __CHAR_BIT__ - 7))
+    __builtin_abort ();
+  if (f1 (b, sizeof (S) * __CHAR_BIT__ / 2 + 2) != (U) 0x101 << (sizeof (S) * __CHAR_BIT__ - 5))
+    __builtin_abort ();
+  S c = (U) 1 << (sizeof (S) * __CHAR_BIT__ - 1);
+  if ((U) f2 (c, 5) != ((U) 0x1f << (sizeof (S) * __CHAR_BIT__ - 5)))
+    __builtin_abort ();
+  if ((U) f2 (c, sizeof (S) * __CHAR_BIT__ / 2) != ((U) -1 << (sizeof (S) * __CHAR_BIT__ / 2 - 1)))
+    __builtin_abort ();
+  if ((U) f2 (c, sizeof (S) * __CHAR_BIT__ / 2 + 2) != ((U) -1 << (sizeof (S) * __CHAR_BIT__ / 2 - 3)))
+    __builtin_abort ();
+  U d = (U) 1 << (sizeof (S) * __CHAR_BIT__ - 1);
+  if (f3 (c, 5) != ((U) 0x1 << (sizeof (S) * __CHAR_BIT__ - 5)))
+    __builtin_abort ();
+  if (f3 (c, sizeof (S) * __CHAR_BIT__ / 2) != ((U) 1 << (sizeof (S) * __CHAR_BIT__ / 2 - 1)))
+    __builtin_abort ();
+  if (f3 (c, sizeof (S) * __CHAR_BIT__ / 2 + 2) != ((U) 1 << (sizeof (S) * __CHAR_BIT__ / 2 - 3)))
+    __builtin_abort ();
+  return 0;
+}