Check optab before transforming equivalent, but slighly different cases to their canonical forms in optimize_atomic_bit_test_and and require TARGET_HIMODE_MATH in HImode atomic bit expanders.
gcc/ PR target/103205 * tree-ssa-ccp.c (optimize_atomic_bit_test_and): Check optab before transforming equivalent, but slighly different cases to their canonical forms. * config/i386/sync.md (atomic_bit_test_and_set<mode>): Require TARGET_HIMODE_MATH for HImode. (atomic_bit_test_and_complement<mode>): Likewise. (atomic_bit_test_and_reset<mode>): Likewise. gcc/testsuite/ PR target/103205 * gcc.target/i386/pr103205-1a.c: New test. * gcc.target/i386/pr103205-1b.c: Likewise. * gcc.target/i386/pr103205-2a.c: Likewise. * gcc.target/i386/pr103205-2b.c: Likewise. * gcc.target/i386/pr103205-3.c: Likewise. * gcc.target/i386/pr103205-4.c: Likewise. --- gcc/config/i386/sync.md | 6 ++-- gcc/testsuite/gcc.target/i386/pr103205-1a.c | 27 ++++++++++++++++ gcc/testsuite/gcc.target/i386/pr103205-1b.c | 9 ++++++ gcc/testsuite/gcc.target/i386/pr103205-2a.c | 26 ++++++++++++++++ gcc/testsuite/gcc.target/i386/pr103205-2b.c | 9 ++++++ gcc/testsuite/gcc.target/i386/pr103205-3.c | 11 +++++++ gcc/testsuite/gcc.target/i386/pr103205-4.c | 11 +++++++ gcc/tree-ssa-ccp.c | 34 ++++++++++++--------- 8 files changed, 115 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr103205-1a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr103205-1b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr103205-2a.c create mode 100644 gcc/testsuite/gcc.target/i386/pr103205-2b.c create mode 100644 gcc/testsuite/gcc.target/i386/pr103205-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr103205-4.c diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md index 05a835256bb..68c4314c21c 100644 --- a/gcc/config/i386/sync.md +++ b/gcc/config/i386/sync.md @@ -717,7 +717,7 @@ (define_expand "atomic_bit_test_and_set<mode>" (match_operand:SWI248 2 "nonmemory_operand") (match_operand:SI 3 "const_int_operand") ;; model (match_operand:SI 4 "const_int_operand")] - "" + "<MODE>mode != HImode || TARGET_HIMODE_MATH" { emit_insn (gen_atomic_bit_test_and_set<mode>_1 (operands[1], operands[2], operands[3])); @@ -753,7 +753,7 @@ (define_expand "atomic_bit_test_and_complement<mode>" (match_operand:SWI248 2 "nonmemory_operand") (match_operand:SI 3 "const_int_operand") ;; model (match_operand:SI 4 "const_int_operand")] - "" + "<MODE>mode != HImode || TARGET_HIMODE_MATH" { emit_insn (gen_atomic_bit_test_and_complement<mode>_1 (operands[1], operands[2], @@ -792,7 +792,7 @@ (define_expand "atomic_bit_test_and_reset<mode>" (match_operand:SWI248 2 "nonmemory_operand") (match_operand:SI 3 "const_int_operand") ;; model (match_operand:SI 4 "const_int_operand")] - "" + "<MODE>mode != HImode || TARGET_HIMODE_MATH" { emit_insn (gen_atomic_bit_test_and_reset<mode>_1 (operands[1], operands[2], operands[3])); diff --git a/gcc/testsuite/gcc.target/i386/pr103205-1a.c b/gcc/testsuite/gcc.target/i386/pr103205-1a.c new file mode 100644 index 00000000000..3ea74b68059 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103205-1a.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mtune-ctrl=himode_math" } */ + +extern short foo; + +int +foo1 (void) +{ + return __sync_fetch_and_and(&foo, ~1) & 1; +} + +int +foo2 (void) +{ + return __sync_fetch_and_or (&foo, 1) & 1; +} + +int +foo3 (void) +{ + return __sync_fetch_and_xor (&foo, 1) & 1; +} + +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrw" 1 } } */ +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btsw" 1 } } */ +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btcw" 1 } } */ +/* { dg-final { scan-assembler-not "cmpxchgw" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr103205-1b.c b/gcc/testsuite/gcc.target/i386/pr103205-1b.c new file mode 100644 index 00000000000..4ce24b5011e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103205-1b.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mtune-ctrl=^himode_math" } */ + +#include "pr103205-1a.c" + +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*cmpxchgw" 3 } } */ +/* { dg-final { scan-assembler-not "btrw" } } */ +/* { dg-final { scan-assembler-not "btsw" } } */ +/* { dg-final { scan-assembler-not "btcw" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr103205-2a.c b/gcc/testsuite/gcc.target/i386/pr103205-2a.c new file mode 100644 index 00000000000..7eb7122aaaf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103205-2a.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mtune-ctrl=himode_math" } */ + +extern unsigned short foo; +unsigned short +foo1 (void) +{ + return __sync_fetch_and_and(&foo, ~1) & 1; +} + +unsigned short +foo2 (void) +{ + return __sync_fetch_and_or (&foo, 1) & 1; +} + +unsigned short +foo3 (void) +{ + return __sync_fetch_and_xor (&foo, 1) & 1; +} + +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btrw" 1 } } */ +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btsw" 1 } } */ +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*btcw" 1 } } */ +/* { dg-final { scan-assembler-not "cmpxchgw" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr103205-2b.c b/gcc/testsuite/gcc.target/i386/pr103205-2b.c new file mode 100644 index 00000000000..49be2e2f39d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103205-2b.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mtune-ctrl=^himode_math" } */ + +#include "pr103205-2a.c" + +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*cmpxchgw" 3 } } */ +/* { dg-final { scan-assembler-not "btrw" } } */ +/* { dg-final { scan-assembler-not "btsw" } } */ +/* { dg-final { scan-assembler-not "btcw" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr103205-3.c b/gcc/testsuite/gcc.target/i386/pr103205-3.c new file mode 100644 index 00000000000..609a674242c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103205-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +char sync_fetch_and_and_short_15_a; +int +__attribute__sync_fetch_and_and_short_15 (void) +{ + return __sync_fetch_and_and(&sync_fetch_and_and_short_15_a, ~1) & 1; +} + +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*cmpxchgb" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr103205-4.c b/gcc/testsuite/gcc.target/i386/pr103205-4.c new file mode 100644 index 00000000000..825867cd705 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr103205-4.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +unsigned char sync_fetch_and_and_short_15_a; +unsigned char +__attribute__sync_fetch_and_and_short_15 (void) +{ + return __sync_fetch_and_and(&sync_fetch_and_and_short_15_a, ~1) & 1; +} + +/* { dg-final { scan-assembler-times "lock;?\[ \t\]*cmpxchgb" 1 } } */ diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 0f79e9f05bd..fec68b5fc73 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -3366,6 +3366,21 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip, || !gimple_vdef (call)) return; + switch (fn) + { + case IFN_ATOMIC_BIT_TEST_AND_SET: + optab = atomic_bit_test_and_set_optab; + break; + case IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT: + optab = atomic_bit_test_and_complement_optab; + break; + case IFN_ATOMIC_BIT_TEST_AND_RESET: + optab = atomic_bit_test_and_reset_optab; + break; + default: + return; + } + tree bit = nullptr; mask = gimple_call_arg (call, 1); @@ -3384,6 +3399,10 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip, if (lhs != use_rhs) return; + if (optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs))) + == CODE_FOR_nothing) + return; + gimple *g; gimple_stmt_iterator gsi; tree var; @@ -3628,21 +3647,6 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip, } } - switch (fn) - { - case IFN_ATOMIC_BIT_TEST_AND_SET: - optab = atomic_bit_test_and_set_optab; - break; - case IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT: - optab = atomic_bit_test_and_complement_optab; - break; - case IFN_ATOMIC_BIT_TEST_AND_RESET: - optab = atomic_bit_test_and_reset_optab; - break; - default: - return; - } - if (optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs))) == CODE_FOR_nothing) return; -- 2.33.1