aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386.md94
-rw-r--r--gcc/testsuite/gcc.target/i386/bt-5.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/bt-6.c69
-rw-r--r--gcc/testsuite/gcc.target/i386/bt-7.c69
4 files changed, 276 insertions, 0 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 6e4abf3..48532eb 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -12794,6 +12794,100 @@
operands[0] = shallow_copy_rtx (operands[0]);
PUT_CODE (operands[0], reverse_condition (GET_CODE (operands[0])));
})
+
+;; Help combine recognize bt followed by cmov
+(define_split
+ [(set (match_operand:SWI248 0 "register_operand")
+ (if_then_else:SWI248
+ (ne
+ (zero_extract:SWI48
+ (match_operand:SWI48 1 "register_operand")
+ (const_int 1)
+ (zero_extend:SI (match_operand:QI 2 "register_operand")))
+ (const_int 0))
+ (match_operand:SWI248 3 "nonimmediate_operand")
+ (match_operand:SWI248 4 "nonimmediate_operand")))]
+ "TARGET_USE_BT && TARGET_CMOVE
+ && !(MEM_P (operands[3]) && MEM_P (operands[4]))
+ && ix86_pre_reload_split ()"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extract:SWI48 (match_dup 1) (const_int 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0)
+ (if_then_else:SWI248 (eq (reg:CCC FLAGS_REG) (const_int 0))
+ (match_dup 3)
+ (match_dup 4)))]
+{
+ operands[2] = lowpart_subreg (SImode, operands[2], QImode);
+})
+
+;; Help combine recognize bt followed by setc
+(define_insn_and_split "*bt<mode>_setcqi"
+ [(set (subreg:SWI48 (match_operand:QI 0 "register_operand") 0)
+ (zero_extract:SWI48
+ (match_operand:SWI48 1 "register_operand")
+ (const_int 1)
+ (zero_extend:SI (match_operand:QI 2 "register_operand"))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_BT && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extract:SWI48 (match_dup 1) (const_int 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0)
+ (eq:QI (reg:CCC FLAGS_REG) (const_int 0)))]
+{
+ operands[2] = lowpart_subreg (SImode, operands[2], QImode);
+})
+
+;; Help combine recognize bt followed by setnc
+(define_insn_and_split "*bt<mode>_setncqi"
+ [(set (match_operand:QI 0 "register_operand")
+ (and:QI
+ (not:QI
+ (subreg:QI
+ (lshiftrt:SWI48 (match_operand:SWI48 1 "register_operand")
+ (match_operand:QI 2 "register_operand")) 0))
+ (const_int 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_BT && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extract:SWI48 (match_dup 1) (const_int 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0)
+ (ne:QI (reg:CCC FLAGS_REG) (const_int 0)))]
+{
+ operands[2] = lowpart_subreg (SImode, operands[2], QImode);
+})
+
+(define_insn_and_split "*bt<mode>_setnc<mode>"
+ [(set (match_operand:SWI48 0 "register_operand")
+ (and:SWI48
+ (not:SWI48
+ (lshiftrt:SWI48 (match_operand:SWI48 1 "register_operand")
+ (match_operand:QI 2 "register_operand")))
+ (const_int 1)))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_USE_BT && ix86_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(set (reg:CCC FLAGS_REG)
+ (compare:CCC
+ (zero_extract:SWI48 (match_dup 1) (const_int 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 3)
+ (ne:QI (reg:CCC FLAGS_REG) (const_int 0)))
+ (set (match_dup 0) (zero_extend:SWI48 (match_dup 3)))]
+{
+ operands[2] = lowpart_subreg (SImode, operands[2], QImode);
+ operands[3] = gen_reg_rtx (QImode);
+})
;; Store-flag instructions.
diff --git a/gcc/testsuite/gcc.target/i386/bt-5.c b/gcc/testsuite/gcc.target/i386/bt-5.c
new file mode 100644
index 0000000..73e7ed2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/bt-5.c
@@ -0,0 +1,44 @@
+/* PR rtl-optimization/46235 */
+/* { dg-do compile { target lp64 } } */
+/* { dg-options "-O2 -mtune=core2" } */
+
+int foo (int a, int x, int y)
+{
+ if (a & (1<<x))
+ return a;
+ return 1;
+}
+
+int bar_ww (int a, int x, int y, int z)
+{
+ return (a & (1<<x)) ? y : z;
+}
+
+int bar_lw (long long a, int x, int y, int z)
+{
+ return (a & (1LL<<x)) ? y : z;
+}
+
+long long bar_wl (int a, int x, long long y, long long z)
+{
+ return (a & (1<<x)) ? y : z;
+}
+
+long long bar_ll (long long a, int x, long long y, long long z)
+{
+ return (a & (1LL<<x)) ? y : z;
+}
+
+short bar_ws (int a, int x, short y, short z)
+{
+ return (a & (1<<x)) ? y : z;
+}
+
+short bar_ls (long long a, int x, short y, short z)
+{
+ return (a & (1LL<<x)) ? y : z;
+}
+
+/* { dg-final { scan-assembler-times "bt\[lq\]\[ \t\]" 7 } } */
+/* { dg-final { scan-assembler-not "sar\[lq\]\[ \t\]" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/bt-6.c b/gcc/testsuite/gcc.target/i386/bt-6.c
new file mode 100644
index 0000000..d4ef805
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/bt-6.c
@@ -0,0 +1,69 @@
+/* PR rtl-optimization/46235 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=core2" } */
+
+unsigned char set1_bb (unsigned char x, int y)
+{
+ return (x & (1<<y)) != 0;
+}
+
+unsigned char set2_bb (unsigned char x, int y)
+{
+ return (x >> y) & 1;
+}
+
+unsigned char set1_wb (int x, int y)
+{
+ return (x & (1<<y)) != 0;
+}
+
+unsigned char set2_wb (int x, int y)
+{
+ return (x >> y) & 1;
+}
+
+unsigned char clr1_bb (unsigned char x, int y)
+{
+ return (x & (1<<y)) == 0;
+}
+
+unsigned char clr2_bb (unsigned char x, int y)
+{
+ return !((x >> y) & 1);
+}
+
+unsigned char clr1_wb (int x, int y)
+{
+ return (x & (1<<y)) == 0;
+}
+
+unsigned char clr2_wb (int x, int y)
+{
+ return !((x >> y) & 1);
+}
+
+int clr1_bw (unsigned char x, int y)
+{
+ return (x & (1<<y)) == 0;
+}
+
+int clr2_bw (unsigned char x, int y)
+{
+ return !((x >> y) & 1);
+}
+
+int clr1_ww (int x, int y)
+{
+ return (x & (1<<y)) == 0;
+}
+
+int clr2_ww (int x, int y)
+{
+ return !((x >> y) & 1);
+}
+
+/* { dg-final { scan-assembler-times "bt\[lq\]\[ \t\]" 12 } } */
+/* { dg-final { scan-assembler-not "sar\[lq\]\[ \t\]" } } */
+/* { dg-final { scan-assembler-not "and\[lq\]\[ \t\]" } } */
+/* { dg-final { scan-assembler-not "not\[lq\]\[ \t\]" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/bt-7.c b/gcc/testsuite/gcc.target/i386/bt-7.c
new file mode 100644
index 0000000..292d741
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/bt-7.c
@@ -0,0 +1,69 @@
+/* PR rtl-optimization/46235 */
+/* { dg-do compile { target lp64 } } */
+/* { dg-options "-O2 -mtune=core2" } */
+
+unsigned char set1_lb (long long x, int y)
+{
+ return (x & (1LL<<y)) != 0;
+}
+
+unsigned char set2_lb (long long x, int y)
+{
+ return (x >> y) & 1;
+}
+
+unsigned char clr1_lb (long long x, int y)
+{
+ return (x & (1LL<<y)) == 0;
+}
+
+unsigned char clr2_lb (long long x, int y)
+{
+ return !((x >> y) & 1);
+}
+
+int clr1_lw (long long x, int y)
+{
+ return (x & (1LL<<y)) == 0;
+}
+
+int clr2_lw (long long x, int y)
+{
+ return !((x >> y) & 1);
+}
+
+long long clr1_bl (unsigned char x, int y)
+{
+ return (x & (1<<y)) == 0;
+}
+
+long long clr2_bl (unsigned char x, int y)
+{
+ return !((x >> y) & 1);
+}
+
+long long clr1_wl (int x, int y)
+{
+ return (x & (1<<y)) == 0;
+}
+
+long long clr2_wl (int x, int y)
+{
+ return !((x >> y) & 1);
+}
+
+long long clr1_ll (long long x, int y)
+{
+ return (x & (1LL<<y)) == 0;
+}
+
+long long clr2_ll (long long x, int y)
+{
+ return !((x >> y) & 1);
+}
+
+/* { dg-final { scan-assembler-times "bt\[lq\]\[ \t\]" 12 } } */
+/* { dg-final { scan-assembler-not "sar\[lq\]\[ \t\]" } } */
+/* { dg-final { scan-assembler-not "and\[lq\]\[ \t\]" } } */
+/* { dg-final { scan-assembler-not "not\[lq\]\[ \t\]" } } */
+