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
This commit is contained in:
parent
2366bf60c6
commit
15643a0dfc
6 changed files with 369 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
83
gcc/testsuite/gcc.c-torture/execute/pr92140.c
Normal file
83
gcc/testsuite/gcc.c-torture/execute/pr92140.c
Normal file
|
@ -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;
|
||||
}
|
38
gcc/testsuite/gcc.target/i386/pr92140.c
Normal file
38
gcc/testsuite/gcc.target/i386/pr92140.c
Normal file
|
@ -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; }
|
Loading…
Add table
Reference in a new issue