From ec9b602c167fb7dfba717f04852a3810ecf9a9a8 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 9 Jan 2020 09:18:51 +0100 Subject: [PATCH] re PR target/93141 (Missed optimization : Use of adc when checking overflow) PR target/93141 * config/i386/i386.md (subv4): Use SWIDWI iterator instead of SWI. Use instead of . Use CONST_SCALAR_INT_P instead of CONST_INT_P. (*subv4_1): Rename to ... (subv4_1): ... this. (*subv4_doubleword, *addv4_doubleword_1): New define_insn_and_split patterns. (*subv4_overflow_1, *addv4_overflow_2): New define_insn patterns. * gcc.target/i386/pr93141-1.c: Add tests with constants that have MSB of the low half of the constant set. * gcc.target/i386/pr93141-2.c: New test. From-SVN: r280029 --- gcc/ChangeLog | 13 ++ gcc/config/i386/i386.md | 181 ++++++++++++++++++++-- gcc/testsuite/ChangeLog | 7 + gcc/testsuite/gcc.target/i386/pr93141-1.c | 44 +++++- gcc/testsuite/gcc.target/i386/pr93141-2.c | 78 ++++++++++ 5 files changed, 308 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr93141-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dae2741ef20..2756a97c476 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2020-01-09 Jakub Jelinek + + PR target/93141 + * config/i386/i386.md (subv4): Use SWIDWI iterator instead of + SWI. Use instead of . Use + CONST_SCALAR_INT_P instead of CONST_INT_P. + (*subv4_1): Rename to ... + (subv4_1): ... this. + (*subv4_doubleword, *addv4_doubleword_1): New + define_insn_and_split patterns. + (*subv4_overflow_1, *addv4_overflow_2): New define_insn + patterns. + 2020-01-08 David Malcolm * vec.c (class selftest::count_dtor): New class. diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 1fead5cd8bb..03441109f48 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -6569,16 +6569,17 @@ ;; Subtract with jump on overflow. (define_expand "subv4" [(parallel [(set (reg:CCO FLAGS_REG) - (eq:CCO (minus: - (sign_extend: - (match_operand:SWI 1 "nonimmediate_operand")) - (match_dup 4)) - (sign_extend: - (minus:SWI (match_dup 1) - (match_operand:SWI 2 - ""))))) - (set (match_operand:SWI 0 "register_operand") - (minus:SWI (match_dup 1) (match_dup 2)))]) + (eq:CCO + (minus: + (sign_extend: + (match_operand:SWIDWI 1 "nonimmediate_operand")) + (match_dup 4)) + (sign_extend: + (minus:SWIDWI (match_dup 1) + (match_operand:SWIDWI 2 + ""))))) + (set (match_operand:SWIDWI 0 "register_operand") + (minus:SWIDWI (match_dup 1) (match_dup 2)))]) (set (pc) (if_then_else (eq (reg:CCO FLAGS_REG) (const_int 0)) (label_ref (match_operand 3)) @@ -6586,7 +6587,7 @@ "" { ix86_fixup_binary_operands_no_copy (MINUS, mode, operands); - if (CONST_INT_P (operands[2])) + if (CONST_SCALAR_INT_P (operands[2])) operands[4] = operands[2]; else operands[4] = gen_rtx_SIGN_EXTEND (mode, operands[2]); @@ -6608,7 +6609,7 @@ [(set_attr "type" "alu") (set_attr "mode" "")]) -(define_insn "*subv4_1" +(define_insn "subv4_1" [(set (reg:CCO FLAGS_REG) (eq:CCO (minus: (sign_extend: @@ -6633,6 +6634,162 @@ (const_string "4")] (const_string "")))]) +(define_insn_and_split "*subv4_doubleword" + [(set (reg:CCO FLAGS_REG) + (eq:CCO + (minus: + (sign_extend: + (match_operand: 1 "nonimmediate_operand" "0,0")) + (sign_extend: + (match_operand: 2 "x86_64_hilo_general_operand" "r,o"))) + (sign_extend: + (minus: (match_dup 1) (match_dup 2))))) + (set (match_operand: 0 "nonimmediate_operand" "=ro,r") + (minus: (match_dup 1) (match_dup 2)))] + "ix86_binary_operator_ok (MINUS, mode, operands)" + "#" + "reload_completed" + [(parallel [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (minus:DWIH (match_dup 1) (match_dup 2)))]) + (parallel [(set (reg:CCO FLAGS_REG) + (eq:CCO + (minus: + (minus: + (sign_extend: (match_dup 4)) + (ltu: (reg:CC FLAGS_REG) (const_int 0))) + (sign_extend: (match_dup 5))) + (sign_extend: + (minus:DWIH + (minus:DWIH + (match_dup 4) + (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))) + (match_dup 5))))) + (set (match_dup 3) + (minus:DWIH + (minus:DWIH + (match_dup 4) + (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))) + (match_dup 5)))])] +{ + split_double_mode (mode, &operands[0], 3, &operands[0], &operands[3]); +}) + +(define_insn_and_split "*subv4_doubleword_1" + [(set (reg:CCO FLAGS_REG) + (eq:CCO + (minus: + (sign_extend: + (match_operand: 1 "nonimmediate_operand" "0")) + (match_operand: 3 "const_scalar_int_operand" "")) + (sign_extend: + (minus: + (match_dup 1) + (match_operand: 2 "x86_64_hilo_general_operand" ""))))) + (set (match_operand: 0 "nonimmediate_operand" "=ro") + (minus: (match_dup 1) (match_dup 2)))] + "ix86_binary_operator_ok (MINUS, mode, operands) + && CONST_SCALAR_INT_P (operands[2]) + && rtx_equal_p (operands[2], operands[3])" + "#" + "reload_completed" + [(parallel [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (minus:DWIH (match_dup 1) (match_dup 2)))]) + (parallel [(set (reg:CCO FLAGS_REG) + (eq:CCO + (minus: + (minus: + (sign_extend: (match_dup 4)) + (ltu: (reg:CC FLAGS_REG) (const_int 0))) + (match_dup 5)) + (sign_extend: + (minus:DWIH + (minus:DWIH + (match_dup 4) + (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))) + (match_dup 5))))) + (set (match_dup 3) + (minus:DWIH + (minus:DWIH + (match_dup 4) + (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))) + (match_dup 5)))])] +{ + split_double_mode (mode, &operands[0], 3, &operands[0], &operands[3]); + if (operands[2] == const0_rtx) + { + emit_insn (gen_subv4_1 (operands[3], operands[4], operands[5], + operands[5])); + DONE; + } +}) + +(define_insn "*subv4_overflow_1" + [(set (reg:CCO FLAGS_REG) + (eq:CCO + (minus: + (minus: + (sign_extend: + (match_operand:SWI 1 "nonimmediate_operand" "%0,0")) + (match_operator: 4 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)])) + (sign_extend: + (match_operand:SWI 2 "" "rWe,m"))) + (sign_extend: + (minus:SWI + (minus:SWI + (match_dup 1) + (match_operator:SWI 5 "ix86_carry_flag_operator" + [(match_dup 3) (const_int 0)])) + (match_dup 2))))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=rm,r") + (minus:SWI + (minus:SWI + (match_dup 1) + (match_op_dup 5 [(match_dup 3) (const_int 0)])) + (match_dup 2)))] + "ix86_binary_operator_ok (MINUS, mode, operands)" + "sbb{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "")]) + +(define_insn "*subv4_overflow_2" + [(set (reg:CCO FLAGS_REG) + (eq:CCO + (minus: + (minus: + (sign_extend: + (match_operand:SWI 1 "nonimmediate_operand" "%0")) + (match_operator: 4 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)])) + (match_operand: 6 "const_int_operand" "")) + (sign_extend: + (minus:SWI + (minus:SWI + (match_dup 1) + (match_operator:SWI 5 "ix86_carry_flag_operator" + [(match_dup 3) (const_int 0)])) + (match_operand:SWI 2 "x86_64_immediate_operand" "e"))))) + (set (match_operand:SWI 0 "nonimmediate_operand" "=rm") + (minus:SWI + (minus:SWI + (match_dup 1) + (match_op_dup 5 [(match_dup 3) (const_int 0)])) + (match_dup 2)))] + "ix86_binary_operator_ok (MINUS, mode, operands) + && CONST_INT_P (operands[2]) + && INTVAL (operands[2]) == INTVAL (operands[6])" + "sbb{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "") + (set (attr "length_immediate") + (if_then_else (match_test "IN_RANGE (INTVAL (operands[2]), -128, 127)") + (const_string "1") + (const_string "4")))]) + (define_expand "usubv4" [(parallel [(set (reg:CC FLAGS_REG) (compare:CC diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 622589e3db6..53766afc0c6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2020-01-09 Jakub Jelinek + + PR target/93141 + * gcc.target/i386/pr93141-1.c: Add tests with constants that have MSB + of the low half of the constant set. + * gcc.target/i386/pr93141-2.c: New test. + 2020-01-08 Jeff Law * gcc.dg/Wstringop-overflow-27.c: Make testnames unique. diff --git a/gcc/testsuite/gcc.target/i386/pr93141-1.c b/gcc/testsuite/gcc.target/i386/pr93141-1.c index 64e4a10740a..3a2adf347d2 100644 --- a/gcc/testsuite/gcc.target/i386/pr93141-1.c +++ b/gcc/testsuite/gcc.target/i386/pr93141-1.c @@ -2,15 +2,17 @@ /* { dg-do compile } */ /* { dg-options "-O2 -masm=att" } */ /* { dg-final { scan-assembler-not "cmp\[lq]\t" } } */ -/* { dg-final { scan-assembler-times "setc\t%" 3 } } */ -/* { dg-final { scan-assembler-times "seto\t%" 5 } } */ -/* { dg-final { scan-assembler-times "adc\[lq]\t" 5 } } */ +/* { dg-final { scan-assembler-times "setc\t%" 5 } } */ +/* { dg-final { scan-assembler-times "seto\t%" 7 } } */ +/* { dg-final { scan-assembler-times "adc\[lq]\t" 9 } } */ #ifdef __x86_64__ typedef unsigned __int128 U; +typedef unsigned long long HU; typedef signed __int128 S; #else typedef unsigned long long U; +typedef unsigned int HU; typedef signed long long S; #endif int o; @@ -81,3 +83,39 @@ garply (S x) | (S) 0xbeedead, &z); return z; } + +S +waldo (S x) +{ + S z; + o = __builtin_add_overflow (x, (S) ((((S) 0xdeadbee) << (sizeof (S) * __CHAR_BIT__ / 2)) + | -(HU) 0xbeedead), &z); + return z; +} + +S +fred (S x) +{ + S z; + o = __builtin_add_overflow (x, (S) ((-(((S) 0xdeadbee) << (sizeof (S) * __CHAR_BIT__ / 2))) + | -(HU) 0xbeedead), &z); + return z; +} + +U +plugh (U x) +{ + U z; + o = __builtin_add_overflow (x, (U) ((((U) 0xdeadbee) << (sizeof (U) * __CHAR_BIT__ / 2)) + | -(HU) 0xbeedead), &z); + return z; +} + +U +xyzzy (U x) +{ + U z; + o = __builtin_add_overflow (x, (U) ((-(((U) 0xdeadbee) << (sizeof (U) * __CHAR_BIT__ / 2))) + | -(HU) 0xbeedead), &z); + return z; +} diff --git a/gcc/testsuite/gcc.target/i386/pr93141-2.c b/gcc/testsuite/gcc.target/i386/pr93141-2.c new file mode 100644 index 00000000000..83ae7edb963 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr93141-2.c @@ -0,0 +1,78 @@ +/* PR target/93141 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-final { scan-assembler-not "cmp\[lq]\t" } } */ +/* { dg-final { scan-assembler-not "adc\[lq]\t" } } */ +/* { dg-final { scan-assembler-times "seto\t%" 7 } } */ +/* { dg-final { scan-assembler-times "sbb\[lq]\t" 5 } } */ + +#ifdef __x86_64__ +typedef unsigned __int128 U; +typedef unsigned long long HU; +typedef signed __int128 S; +#else +typedef unsigned long long U; +typedef signed int HU; +typedef signed long long S; +#endif +int o; + +S +qux (S x, S y) +{ + S z; + o = __builtin_sub_overflow (x, y, &z); + return z; +} + +S +quux (S x) +{ + S z; + o = __builtin_sub_overflow (x, ((S) 0xdeadbee) << (sizeof (S) * __CHAR_BIT__ / 2), &z); + return z; +} + +S +corge (S x) +{ + S z; + o = __builtin_sub_overflow (x, (((S) 0xdeadbee) << (sizeof (S) * __CHAR_BIT__ / 2)) + | (S) 0xbeedead, &z); + return z; +} + +S +grault (S x) +{ + S z; + o = __builtin_sub_overflow (x, -((S) 0xdeadbee) << (sizeof (S) * __CHAR_BIT__ / 2), &z); + return z; +} + +S +garply (S x) +{ + S z; + o = __builtin_sub_overflow (x, (-(((S) 0xdeadbee) << (sizeof (S) * __CHAR_BIT__ / 2))) + | (S) 0xbeedead, &z); + return z; +} + +S +waldo (S x) +{ + S z; + o = __builtin_sub_overflow (x, (S) ((((S) 0xdeadbee) << (sizeof (S) * __CHAR_BIT__ / 2)) + | -(HU) 0xbeedead), &z); + return z; +} + +S +fred (S x) +{ + S z; + o = __builtin_sub_overflow (x, (S) ((-(((S) 0xdeadbee) << (sizeof (S) * __CHAR_BIT__ / 2))) + | -(HU) 0xbeedead), &z); + return z; +} -- 2.30.2