diff options
author | Jakub Jelinek <jakub@redhat.com> | 2019-10-19 14:46:57 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2019-10-19 14:46:57 +0200 |
commit | 15643a0dfc60e8e53d9b66165f4e2f4fcd8d98de (patch) | |
tree | 3f46d62c0e0d813672986e1e5292eaaeb307b3d7 /gcc | |
parent | 2366bf60c667d968c88e7bcec2eb9e2b84d0172d (diff) | |
download | gcc-15643a0dfc60e8e53d9b66165f4e2f4fcd8d98de.zip gcc-15643a0dfc60e8e53d9b66165f4e2f4fcd8d98de.tar.gz gcc-15643a0dfc60e8e53d9b66165f4e2f4fcd8d98de.tar.bz2 |
re PR target/92140 (clang vs gcc optimizing with adc/sbb)
PR target/92140
* config/i386/predicates.md (int_nonimmediate_operand): New special
predicate.
* config/i386/i386.md (*add<mode>3_eq, *add<mode>3_ne,
*add<mode>3_eq_0, *add<mode>3_ne_0, *sub<mode>3_eq, *sub<mode>3_ne,
*sub<mode>3_eq_1, *sub<mode>3_eq_0, *sub<mode>3_ne_0): New
define_insn_and_split patterns.
* gcc.target/i386/pr92140.c: New test.
* gcc.c-torture/execute/pr92140.c: New test.
Co-Authored-By: Uros Bizjak <ubizjak@gmail.com>
From-SVN: r277203
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 222 | ||||
-rw-r--r-- | gcc/config/i386/predicates.md | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr92140.c | 83 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr92140.c | 38 |
6 files changed, 369 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7f77088..4919539 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2019-10-19 Jakub Jelinek <jakub@redhat.com> + Uroš Bizjak <ubizjak@gmail.com> + + PR target/92140 + * config/i386/predicates.md (int_nonimmediate_operand): New special + predicate. + * config/i386/i386.md (*add<mode>3_eq, *add<mode>3_ne, + *add<mode>3_eq_0, *add<mode>3_ne_0, *sub<mode>3_eq, *sub<mode>3_ne, + *sub<mode>3_eq_1, *sub<mode>3_eq_0, *sub<mode>3_ne_0): New + define_insn_and_split patterns. + 2019-10-19 Iain Sandoe <iain@sandoe.co.uk> * config/rs6000/rs6000.md: Delete out--of-date comment about diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b7e7d12..a1b849e 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -6843,6 +6843,228 @@ [(set_attr "type" "alu") (set_attr "mode" "SI")]) +;; x == 0 with zero flag test can be done also as x < 1U with carry flag +;; test, where the latter is preferrable if we have some carry consuming +;; instruction. +;; For x != 0, we need to use x < 1U with negation of carry, i.e. +;; + (1 - CF). +(define_insn_and_split "*add<mode>3_eq" + [(set (match_operand:SWI 0 "nonimmediate_operand") + (plus:SWI + (plus:SWI + (eq:SWI (match_operand 3 "int_nonimmediate_operand") (const_int 0)) + (match_operand:SWI 1 "nonimmediate_operand")) + (match_operand:SWI 2 "<general_operand>"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (PLUS, <MODE>mode, operands) + && can_create_pseudo_p ()" + "#" + "&& 1" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 3) (const_int 1))) + (parallel [(set (match_dup 0) + (plus:SWI + (plus:SWI (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 1)) + (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])]) + +(define_insn_and_split "*add<mode>3_ne" + [(set (match_operand:SWI 0 "nonimmediate_operand") + (plus:SWI + (plus:SWI + (ne:SWI (match_operand 3 "int_nonimmediate_operand") (const_int 0)) + (match_operand:SWI 1 "nonimmediate_operand")) + (match_operand:SWI 2 "<immediate_operand>"))) + (clobber (reg:CC FLAGS_REG))] + "CONST_INT_P (operands[2]) + && (<MODE>mode != DImode + || INTVAL (operands[2]) != HOST_WIDE_INT_C (-0x80000000)) + && ix86_binary_operator_ok (PLUS, <MODE>mode, operands) + && can_create_pseudo_p ()" + "#" + "&& 1" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 3) (const_int 1))) + (parallel [(set (match_dup 0) + (minus:SWI + (minus:SWI (match_dup 1) + (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))) + (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] +{ + operands[2] = gen_int_mode (~INTVAL (operands[2]), + <MODE>mode == DImode ? SImode : <MODE>mode); +}) + +(define_insn_and_split "*add<mode>3_eq_0" + [(set (match_operand:SWI 0 "nonimmediate_operand") + (plus:SWI + (eq:SWI (match_operand 2 "int_nonimmediate_operand") (const_int 0)) + (match_operand:SWI 1 "<general_operand>"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_unary_operator_ok (PLUS, <MODE>mode, operands) + && can_create_pseudo_p ()" + "#" + "&& 1" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 2) (const_int 1))) + (parallel [(set (match_dup 0) + (plus:SWI (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 1))) + (clobber (reg:CC FLAGS_REG))])] +{ + if (!nonimmediate_operand (operands[1], <MODE>mode)) + operands[1] = force_reg (<MODE>mode, operands[1]); +}) + +(define_insn_and_split "*add<mode>3_ne_0" + [(set (match_operand:SWI 0 "nonimmediate_operand") + (plus:SWI + (ne:SWI (match_operand 2 "int_nonimmediate_operand") (const_int 0)) + (match_operand:SWI 1 "<general_operand>"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_unary_operator_ok (PLUS, <MODE>mode, operands) + && can_create_pseudo_p ()" + "#" + "&& 1" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 2) (const_int 1))) + (parallel [(set (match_dup 0) + (minus:SWI (minus:SWI + (match_dup 1) + (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))) + (const_int -1))) + (clobber (reg:CC FLAGS_REG))])] +{ + if (!nonimmediate_operand (operands[1], <MODE>mode)) + operands[1] = force_reg (<MODE>mode, operands[1]); +}) + +(define_insn_and_split "*sub<mode>3_eq" + [(set (match_operand:SWI 0 "nonimmediate_operand") + (minus:SWI + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand") + (eq:SWI (match_operand 3 "int_nonimmediate_operand") + (const_int 0))) + (match_operand:SWI 2 "<general_operand>"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (MINUS, <MODE>mode, operands) + && can_create_pseudo_p ()" + "#" + "&& 1" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 3) (const_int 1))) + (parallel [(set (match_dup 0) + (minus:SWI + (minus:SWI (match_dup 1) + (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))) + (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])]) + +(define_insn_and_split "*sub<mode>3_ne" + [(set (match_operand:SWI 0 "nonimmediate_operand") + (plus:SWI + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand") + (ne:SWI (match_operand 3 "int_nonimmediate_operand") + (const_int 0))) + (match_operand:SWI 2 "<immediate_operand>"))) + (clobber (reg:CC FLAGS_REG))] + "CONST_INT_P (operands[2]) + && (<MODE>mode != DImode + || INTVAL (operands[2]) != HOST_WIDE_INT_C (-0x80000000)) + && ix86_binary_operator_ok (MINUS, <MODE>mode, operands) + && can_create_pseudo_p ()" + "#" + "&& 1" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 3) (const_int 1))) + (parallel [(set (match_dup 0) + (plus:SWI + (plus:SWI (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 1)) + (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] +{ + operands[2] = gen_int_mode (INTVAL (operands[2]) - 1, + <MODE>mode == DImode ? SImode : <MODE>mode); +}) + +(define_insn_and_split "*sub<mode>3_eq_1" + [(set (match_operand:SWI 0 "nonimmediate_operand") + (plus:SWI + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand") + (eq:SWI (match_operand 3 "int_nonimmediate_operand") + (const_int 0))) + (match_operand:SWI 2 "<immediate_operand>"))) + (clobber (reg:CC FLAGS_REG))] + "CONST_INT_P (operands[2]) + && (<MODE>mode != DImode + || INTVAL (operands[2]) != HOST_WIDE_INT_C (-0x80000000)) + && ix86_binary_operator_ok (MINUS, <MODE>mode, operands) + && can_create_pseudo_p ()" + "#" + "&& 1" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 3) (const_int 1))) + (parallel [(set (match_dup 0) + (minus:SWI + (minus:SWI (match_dup 1) + (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))) + (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] +{ + operands[2] = gen_int_mode (-INTVAL (operands[2]), + <MODE>mode == DImode ? SImode : <MODE>mode); +}) + +(define_insn_and_split "*sub<mode>3_eq_0" + [(set (match_operand:SWI 0 "nonimmediate_operand") + (minus:SWI + (match_operand:SWI 1 "<general_operand>") + (eq:SWI (match_operand 2 "int_nonimmediate_operand") (const_int 0)))) + (clobber (reg:CC FLAGS_REG))] + "ix86_unary_operator_ok (MINUS, <MODE>mode, operands) + && can_create_pseudo_p ()" + "#" + "&& 1" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 2) (const_int 1))) + (parallel [(set (match_dup 0) + (minus:SWI (match_dup 1) + (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)))) + (clobber (reg:CC FLAGS_REG))])] +{ + if (!nonimmediate_operand (operands[1], <MODE>mode)) + operands[1] = force_reg (<MODE>mode, operands[1]); +}) + +(define_insn_and_split "*sub<mode>3_ne_0" + [(set (match_operand:SWI 0 "nonimmediate_operand") + (minus:SWI + (match_operand:SWI 1 "<general_operand>") + (ne:SWI (match_operand 2 "int_nonimmediate_operand") (const_int 0)))) + (clobber (reg:CC FLAGS_REG))] + "ix86_unary_operator_ok (MINUS, <MODE>mode, operands) + && can_create_pseudo_p ()" + "#" + "&& 1" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 2) (const_int 1))) + (parallel [(set (match_dup 0) + (plus:SWI (plus:SWI + (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 1)) + (const_int -1))) + (clobber (reg:CC FLAGS_REG))])] +{ + if (!nonimmediate_operand (operands[1], <MODE>mode)) + operands[1] = force_reg (<MODE>mode, operands[1]); +}) + ;; The patterns that match these are at the end of this file. (define_expand "<plusminus_insn>xf3" diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 31f1cea..279827f 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -100,6 +100,15 @@ (match_test "GET_MODE (op) == SImode") (match_test "GET_MODE (op) == HImode")))) +;; Match a DI, SI, HI or QImode nonimmediate_operand. +(define_special_predicate "int_nonimmediate_operand" + (and (match_operand 0 "nonimmediate_operand") + (ior (and (match_test "TARGET_64BIT") + (match_test "GET_MODE (op) == DImode")) + (match_test "GET_MODE (op) == SImode") + (match_test "GET_MODE (op) == HImode") + (match_test "GET_MODE (op) == QImode")))) + ;; Match register operands, but include memory operands for TARGET_SSE_MATH. (define_predicate "register_ssemem_operand" (if_then_else diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6fc0c82..c22b137 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-10-19 Jakub Jelinek <jakub@redhat.com> + + PR target/92140 + * gcc.target/i386/pr92140.c: New test. + * gcc.c-torture/execute/pr92140.c: New test. + 2019-10-19 Iain Sandoe <iain@sandoe.co.uk> * gcc.dg/Wnonnull.c: Add attributed function declarations for diff --git a/gcc/testsuite/gcc.c-torture/execute/pr92140.c b/gcc/testsuite/gcc.c-torture/execute/pr92140.c new file mode 100644 index 0000000..1036fd8 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr92140.c @@ -0,0 +1,83 @@ +/* PR target/92140 */ + +char c; +int v; + +__attribute__((noipa)) void f1 (void) { v += c != 0; } +__attribute__((noipa)) void f2 (void) { v -= c != 0; } +__attribute__((noipa)) void f3 (void) { v += c == 0; } +__attribute__((noipa)) void f4 (void) { v -= c == 0; } +__attribute__((noipa)) void f5 (void) { v += (c != 0) - 26; } +__attribute__((noipa)) void f6 (void) { v -= (c != 0) - 26; } +__attribute__((noipa)) void f7 (void) { v += (c == 0) - 26; } +__attribute__((noipa)) void f8 (void) { v -= (c == 0) - 26; } +__attribute__((noipa)) void f9 (void) { v += (c != 0) + 42; } +__attribute__((noipa)) void f10 (void) { v -= (c != 0) + 42; } +__attribute__((noipa)) void f11 (void) { v += (c == 0) + 42; } +__attribute__((noipa)) void f12 (void) { v -= (c == 0) + 42; } +__attribute__((noipa)) void f13 (int z) { v += (c == 0) + z; } +__attribute__((noipa)) void f14 (int z) { v -= (c == 0) + z; } +__attribute__((noipa)) unsigned int f15 (unsigned int n) { return n ? 2 : 1; } + +int +main () +{ + int i; + for (i = 0; i < 2; i++) + { + v = 15; + if (i == 1) + c = 37; + f1 (); + if (v != 15 + i) + __builtin_abort (); + f2 (); + if (v != 15) + __builtin_abort (); + f3 (); + if (v != 16 - i) + __builtin_abort (); + f4 (); + if (v != 15) + __builtin_abort (); + f5 (); + if (v != 15 + i - 26) + __builtin_abort (); + f6 (); + if (v != 15) + __builtin_abort (); + f7 (); + if (v != 16 - i - 26) + __builtin_abort (); + f8 (); + if (v != 15) + __builtin_abort (); + f9 (); + if (v != 15 + i + 42) + __builtin_abort (); + f10 (); + if (v != 15) + __builtin_abort (); + f11 (); + if (v != 16 - i + 42) + __builtin_abort (); + f12 (); + if (v != 15) + __builtin_abort (); + f13 (173); + if (v != 16 - i + 173) + __builtin_abort (); + f14 (173); + if (v != 15) + __builtin_abort (); + f13 (-35); + if (v != 16 - i - 35) + __builtin_abort (); + f14 (-35); + if (v != 15) + __builtin_abort (); + } + if (f15 (0) != 1 || f15 (1) != 2 || f15 (371) != 2) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr92140.c b/gcc/testsuite/gcc.target/i386/pr92140.c new file mode 100644 index 0000000..f21544e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr92140.c @@ -0,0 +1,38 @@ +/* PR target/92140 */ +/* { dg-do compile { target nonpic } } */ +/* { dg-options "-O2 -mtune=generic -masm=att" } */ +/* { dg-additional-options "-mregparm=1" { target ia32 } } */ +/* { dg-final { scan-assembler-times "\tsbbl\t\\\$-1, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tadcl\t\\\$-1, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tadcl\t\\\$0, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tsbbl\t\\\$0, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tsbbl\t\\\$25, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tadcl\t\\\$25, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tadcl\t\\\$-26, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tsbbl\t\\\$-26, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tsbbl\t\\\$-43, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tadcl\t\\\$-43, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tadcl\t\\\$42, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tsbbl\t\\\$42, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tadcl\t%\[a-z0-9]*, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tsbbl\t%\[a-z0-9]*, v" 1 } } */ +/* { dg-final { scan-assembler-times "\tsbbl\t\\\$-1, %" 1 } } */ + +char c; +int v; + +__attribute__((noipa)) void f1 (void) { v += c != 0; } +__attribute__((noipa)) void f2 (void) { v -= c != 0; } +__attribute__((noipa)) void f3 (void) { v += c == 0; } +__attribute__((noipa)) void f4 (void) { v -= c == 0; } +__attribute__((noipa)) void f5 (void) { v += (c != 0) - 26; } +__attribute__((noipa)) void f6 (void) { v -= (c != 0) - 26; } +__attribute__((noipa)) void f7 (void) { v += (c == 0) - 26; } +__attribute__((noipa)) void f8 (void) { v -= (c == 0) - 26; } +__attribute__((noipa)) void f9 (void) { v += (c != 0) + 42; } +__attribute__((noipa)) void f10 (void) { v -= (c != 0) + 42; } +__attribute__((noipa)) void f11 (void) { v += (c == 0) + 42; } +__attribute__((noipa)) void f12 (void) { v -= (c == 0) + 42; } +__attribute__((noipa)) void f13 (int z) { v += (c == 0) + z; } +__attribute__((noipa)) void f14 (int z) { v -= (c == 0) + z; } +__attribute__((noipa)) unsigned int f15 (unsigned int n) { return n ? 2 : 1; } |