diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b9b8f78dc89..602dfa799bf 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -9716,6 +9716,27 @@ operands[2] = gen_rtx_AND (mode, val, immed_wide_int_const (mask, mode)); }) +;; Split and;cmp (as optimized by combine) into not;test +;; Except when TARGET_BMI provides andn (*andn__ccno). +(define_insn_and_split "*test_not" + [(set (reg:CCZ FLAGS_REG) + (compare:CCZ + (and:SWI + (not:SWI (match_operand:SWI 0 "register_operand")) + (match_operand:SWI 1 "")) + (const_int 0)))] + "ix86_pre_reload_split () + && (!TARGET_BMI || !REG_P (operands[1]))" + "#" + "&& 1" + [(set (match_dup 2) (not:SWI (match_dup 0))) + (set (reg:CCZ FLAGS_REG) + (compare:CCZ (and:SWI (match_dup 2) (match_dup 1)) + (const_int 0)))] +{ + operands[2] = gen_reg_rtx (mode); +}) + ;; Convert HImode/SImode test instructions with immediate to QImode ones. ;; i386 does not allow to encode test with 8bit sign extended immediate, so ;; this is relatively important trick. diff --git a/gcc/testsuite/gcc.target/i386/pr91400-1.c b/gcc/testsuite/gcc.target/i386/pr91400-1.c index 6124058dc1e..751dc6c824e 100644 --- a/gcc/testsuite/gcc.target/i386/pr91400-1.c +++ b/gcc/testsuite/gcc.target/i386/pr91400-1.c @@ -1,8 +1,8 @@ /* PR target/91400 */ /* { dg-do compile } */ /* { dg-options "-O2" } */ -/* { dg-final { scan-assembler-times "andl" 1 } } */ -/* { dg-final { scan-assembler-times "cmpl" 1 } } */ +/* { dg-final { scan-assembler-times "notl" 1 } } */ +/* { dg-final { scan-assembler-times "testb" 1 } } */ /* { dg-final { scan-assembler-times "sete" 1 } } */ /* { dg-final { scan-assembler-not "cmove" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr91400-2.c b/gcc/testsuite/gcc.target/i386/pr91400-2.c index 1af5a2f41cd..914acd7812f 100644 --- a/gcc/testsuite/gcc.target/i386/pr91400-2.c +++ b/gcc/testsuite/gcc.target/i386/pr91400-2.c @@ -1,8 +1,8 @@ /* PR target/91400 */ /* { dg-do compile } */ /* { dg-options "-O2" } */ -/* { dg-final { scan-assembler-times "andl" 1 } } */ -/* { dg-final { scan-assembler-times "cmpl" 1 } } */ +/* { dg-final { scan-assembler-times "notl" 1 } } */ +/* { dg-final { scan-assembler-times "testb" 1 } } */ /* { dg-final { scan-assembler-times "sete" 1 } } */ /* { dg-final { scan-assembler-not "cmove" } } */ diff --git a/gcc/testsuite/gcc.target/i386/testnot-1.c b/gcc/testsuite/gcc.target/i386/testnot-1.c new file mode 100644 index 00000000000..9ebcb5c7e99 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/testnot-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int foo(int x) +{ + return (x & 1234) == 1234; +} + +int foos(short x) +{ + return (x & 1234) == 1234; +} + +int fooc(char x) +{ + return (x & 123) == 123; +} + +int fool(long long x) +{ + return (x & 1234) == 1234; +} + +/* { dg-final { scan-assembler-not "cmp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/testnot-2.c b/gcc/testsuite/gcc.target/i386/testnot-2.c new file mode 100644 index 00000000000..52fdaf361df --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/testnot-2.c @@ -0,0 +1,24 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2" } */ + +int foo(int x, int y) +{ + return (x & y) == y; +} + +int foos(short x, short y) +{ + return (x & y) == y; +} + +int fooc(char x, char y) +{ + return (x & y) == y; +} + +int fool(long long x, long long y) +{ + return (x & y) == y; +} + +/* { dg-final { scan-assembler-not "cmp" } } */