summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-07-08 08:48:40 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-07-08 08:48:40 +0000
commit1bf020d9b399127094474cf802aee4026dd7e54b (patch)
tree38579d40ff3a272b2669af830c79e5de77e39b55 /gcc
parentc69585bd3a695c12ca881781e245af69d3007b14 (diff)
downloadgcc-1bf020d9b399127094474cf802aee4026dd7e54b.tar.gz
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. * gcc.target/i386/pr57819.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@200775 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/combine.c6
-rw-r--r--gcc/config/i386/i386.md33
-rw-r--r--gcc/simplify-rtx.c23
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr57819.c38
6 files changed, 109 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e4fc901528c..4fc4e503dc7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/combine.c b/gcc/combine.c
index b737bc5529f..ca311ff7797 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -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. */
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index a6e2946584b..2777e9c8617 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -10474,6 +10474,39 @@
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"
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index be54db8f5d0..17a3d12e076 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f4d0b6faf96..8de216fa48b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..b086a40c4ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr57819.c
@@ -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\]" } } */