PR target/57819
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Jul 2013 08:48:40 +0000 (08:48 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Jul 2013 08:48:40 +0000 (08:48 +0000)
* simplify-rtx.c (simplify_unary_operation_1) <case ZERO_EXTEND>:
Simplify (zero_extend:SI (subreg:QI (and:SI (reg:SI)
(const_int 63)) 0)).
* combine.c (make_extraction): Create ZERO_EXTEND or SIGN_EXTEND
using simplify_gen_unary instead of gen_rtx_*_EXTEND.
* config/i386/i386.md (*jcc_bt<mode>_1): New define_insn_and_split.

* gcc.target/i386/pr57819.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@200775 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/combine.c
gcc/config/i386/i386.md
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr57819.c [new file with mode: 0644]

index e4fc901..4fc4e50 100644 (file)
@@ -1,5 +1,13 @@
 2013-07-08  Jakub Jelinek  <jakub@redhat.com>
 
+       PR target/57819
+       * simplify-rtx.c (simplify_unary_operation_1) <case ZERO_EXTEND>:
+       Simplify (zero_extend:SI (subreg:QI (and:SI (reg:SI)
+       (const_int 63)) 0)).
+       * combine.c (make_extraction): Create ZERO_EXTEND or SIGN_EXTEND
+       using simplify_gen_unary instead of gen_rtx_*_EXTEND.
+       * config/i386/i386.md (*jcc_bt<mode>_1): New define_insn_and_split.
+
        PR rtl-optimization/57829
        * simplify-rtx.c (simplify_binary_operation_1) <case IOR>: Ensure that
        mask bits outside of mode are just sign-extension from mode to HWI.
index b737bc5..ca311ff 100644 (file)
@@ -7326,7 +7326,8 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
   if (pos_rtx != 0
       && GET_MODE_SIZE (pos_mode) > GET_MODE_SIZE (GET_MODE (pos_rtx)))
     {
-      rtx temp = gen_rtx_ZERO_EXTEND (pos_mode, pos_rtx);
+      rtx temp = simplify_gen_unary (ZERO_EXTEND, pos_mode, pos_rtx,
+                                    GET_MODE (pos_rtx));
 
       /* If we know that no extraneous bits are set, and that the high
         bit is not set, convert extraction to cheaper one - either
@@ -7340,7 +7341,8 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
                       >> 1))
                  == 0)))
        {
-         rtx temp1 = gen_rtx_SIGN_EXTEND (pos_mode, pos_rtx);
+         rtx temp1 = simplify_gen_unary (SIGN_EXTEND, pos_mode, pos_rtx,
+                                         GET_MODE (pos_rtx));
 
          /* Prefer ZERO_EXTENSION, since it gives more information to
             backends.  */
index a6e2946..2777e9c 100644 (file)
   PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));
 })
 
+;; Like *jcc_bt<mode>, but expect a SImode operand 2 instead of QImode
+;; zero extended to SImode.
+(define_insn_and_split "*jcc_bt<mode>_1"
+  [(set (pc)
+       (if_then_else (match_operator 0 "bt_comparison_operator"
+                       [(zero_extract:SWI48
+                          (match_operand:SWI48 1 "register_operand" "r")
+                          (const_int 1)
+                          (match_operand:SI 2 "register_operand" "r"))
+                        (const_int 0)])
+                     (label_ref (match_operand 3))
+                     (pc)))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_USE_BT || optimize_function_for_size_p (cfun)"
+  "#"
+  "&& 1"
+  [(set (reg:CCC FLAGS_REG)
+       (compare:CCC
+         (zero_extract:SWI48
+           (match_dup 1)
+           (const_int 1)
+           (match_dup 2))
+         (const_int 0)))
+   (set (pc)
+       (if_then_else (match_op_dup 0 [(reg:CCC FLAGS_REG) (const_int 0)])
+                     (label_ref (match_dup 3))
+                     (pc)))]
+{
+  operands[2] = simplify_gen_subreg (<MODE>mode, operands[2], SImode, 0);
+
+  PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));
+})
+
 ;; Avoid useless masking of bit offset operand.  "and" in SImode is correct
 ;; also for DImode, this is what combine produces.
 (define_insn_and_split "*jcc_bt<mode>_mask"
index be54db8..17a3d12 100644 (file)
@@ -1470,6 +1470,29 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
            }
        }
 
+      /* (zero_extend:M (subreg:N <X:O>)) is <X:O> (for M == O) or
+        (zero_extend:M <X:O>), if X doesn't have any non-zero bits outside
+        of mode N.  E.g.
+        (zero_extend:SI (subreg:QI (and:SI (reg:SI) (const_int 63)) 0)) is
+        (and:SI (reg:SI) (const_int 63)).  */
+      if (GET_CODE (op) == SUBREG
+         && GET_MODE_PRECISION (GET_MODE (op))
+            < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))
+         && GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))
+            <= HOST_BITS_PER_WIDE_INT
+         && GET_MODE_PRECISION (mode)
+            >= GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))
+         && subreg_lowpart_p (op)
+         && (nonzero_bits (SUBREG_REG (op), GET_MODE (SUBREG_REG (op)))
+             & ~GET_MODE_MASK (GET_MODE (op))) == 0)
+       {
+         if (GET_MODE_PRECISION (mode)
+             == GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))))
+           return SUBREG_REG (op);
+         return simplify_gen_unary (ZERO_EXTEND, mode, SUBREG_REG (op),
+                                    GET_MODE (SUBREG_REG (op)));
+       }
+
 #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
       /* As we do not know which address space the pointer is referring to,
         we can do this only if the target does not support different pointer
index f4d0b6f..8de216f 100644 (file)
@@ -1,5 +1,8 @@
 2013-07-08  Jakub Jelinek  <jakub@redhat.com>
 
+       PR target/57819
+       * gcc.target/i386/pr57819.c: New test.
+
        PR rtl-optimization/57829
        * gcc.c-torture/execute/pr57829.c: New test.
 
diff --git a/gcc/testsuite/gcc.target/i386/pr57819.c b/gcc/testsuite/gcc.target/i386/pr57819.c
new file mode 100644 (file)
index 0000000..b086a40
--- /dev/null
@@ -0,0 +1,38 @@
+/* PR target/57819 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=core2" } */
+
+void foo (void);
+
+__extension__ typedef __INTPTR_TYPE__ intptr_t;
+
+int
+test1 (intptr_t x, intptr_t n)
+{
+  n &= sizeof (intptr_t) * __CHAR_BIT__ - 1;
+
+  if (x & ((intptr_t) 1 << n))
+    foo ();
+
+  return 0;
+}
+
+int
+test2 (intptr_t x, intptr_t n)
+{
+  if (x & ((intptr_t) 1 << ((int) n & (sizeof (intptr_t) * __CHAR_BIT__ - 1))))
+    foo ();
+
+  return 0;
+}
+
+int
+test3 (intptr_t x, intptr_t n)
+{
+  if (x & ((intptr_t) 1 << ((int) n & ((int) sizeof (intptr_t) * __CHAR_BIT__ - 1))))
+    foo ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-not "and\[lq\]\[ \t\]" } } */