From 5c561248378ab07fb2abd6766b16572d8b903545 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 25 Feb 2019 11:32:38 +0100 Subject: [PATCH] re PR target/89434 (wrong code with -Og and __builtin_mul_overflow()) PR target/89434 * config/arm/arm.md (*subsi3_carryin_const): Use arm_neg_immediate_operand predicate instead of arm_not_immediate_operand, "L" constraint instead of "K" and print it using %n2 instead of %B2. (*subsi3_carryin_const0): New define_insn. (*subsi3_carryin_compare_const): Use const_int_I_operand predicate instead of arm_not_operand and "I" constraint instead of "K" and print it using %n3 instead of %B2. Instead of using match_dup 2 add another match_operand and in the condition check that it is negation of operands[2]. (*subsi3_carryin_compare_const0): New define_ins. (*subdi_di_zesidi): Adjust to use *subsi3_carryin_const0 instead of *subsi3_carryin_const. (*arm_cmpdi_insn): Fix splitting into *subsi3_carryin_compare_const, split into *subsi3_carryin_compare_const0 if the highpart is zero. * gcc.c-torture/execute/pr89434.c: New test. From-SVN: r269186 --- gcc/ChangeLog | 17 +++++++ gcc/config/arm/arm.md | 49 ++++++++++++++----- gcc/testsuite/ChangeLog | 3 ++ gcc/testsuite/gcc.c-torture/execute/pr89434.c | 29 +++++++++++ gcc/testsuite/gcc.dg/pr89434.c | 5 ++ 5 files changed, 91 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr89434.c create mode 100644 gcc/testsuite/gcc.dg/pr89434.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 932861814ad..cce2741a809 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,22 @@ 2019-02-25 Jakub Jelinek + PR target/89434 + * config/arm/arm.md (*subsi3_carryin_const): Use + arm_neg_immediate_operand predicate instead of + arm_not_immediate_operand, "L" constraint instead of "K" and + print it using %n2 instead of %B2. + (*subsi3_carryin_const0): New define_insn. + (*subsi3_carryin_compare_const): Use const_int_I_operand predicate + instead of arm_not_operand and "I" constraint instead of "K" and + print it using %n3 instead of %B2. Instead of using match_dup 2 add + another match_operand and in the condition check that it is negation + of operands[2]. + (*subsi3_carryin_compare_const0): New define_ins. + (*subdi_di_zesidi): Adjust to use *subsi3_carryin_const0 instead of + *subsi3_carryin_const. + (*arm_cmpdi_insn): Fix splitting into *subsi3_carryin_compare_const, + split into *subsi3_carryin_compare_const0 if the highpart is zero. + PR target/89438 * config/arm.vfp.md (*negdf2_vfp): Use gen_int_mode (0x80000000, SImode) instead of GEN_INT (0x80000000). diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 0e35d03afd1..349b0a5d07d 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1145,10 +1145,20 @@ (define_insn "*subsi3_carryin_const" [(set (match_operand:SI 0 "s_register_operand" "=r") (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_not_immediate_operand" "K")) + (match_operand:SI 2 "arm_neg_immediate_operand" "L")) (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] "TARGET_32BIT" - "sbc\\t%0, %1, #%B2" + "sbc\\t%0, %1, #%n2" + [(set_attr "conds" "use") + (set_attr "type" "adc_imm")] +) + +(define_insn "*subsi3_carryin_const0" + [(set (match_operand:SI 0 "s_register_operand" "=r") + (minus:SI (match_operand:SI 1 "s_register_operand" "r") + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + "TARGET_32BIT" + "sbc\\t%0, %1, #0" [(set_attr "conds" "use") (set_attr "type" "adc_imm")] ) @@ -1170,13 +1180,26 @@ (define_insn "*subsi3_carryin_compare_const" [(set (reg:CC CC_REGNUM) (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r") - (match_operand:SI 2 "arm_not_operand" "K"))) + (match_operand:SI 2 "const_int_I_operand" "I"))) (set (match_operand:SI 0 "s_register_operand" "=r") (minus:SI (plus:SI (match_dup 1) - (match_dup 2)) + (match_operand:SI 3 "arm_neg_immediate_operand" "L")) + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + "TARGET_32BIT && UINTVAL (operands[2]) == -UINTVAL (operands[3])" + "sbcs\\t%0, %1, #%n3" + [(set_attr "conds" "set") + (set_attr "type" "adcs_imm")] +) + +(define_insn "*subsi3_carryin_compare_const0" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r") + (const_int 0))) + (set (match_operand:SI 0 "s_register_operand" "=r") + (minus:SI (match_dup 1) (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] "TARGET_32BIT" - "sbcs\\t%0, %1, #%B2" + "sbcs\\t%0, %1, #0" [(set_attr "conds" "set") (set_attr "type" "adcs_imm")] ) @@ -1301,14 +1324,13 @@ [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (match_dup 2))) (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) - (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5)) + (set (match_dup 3) (minus:SI (match_dup 4) (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); operands[4] = gen_highpart (SImode, operands[1]); operands[1] = gen_lowpart (SImode, operands[1]); - operands[5] = GEN_INT (~0); } [(set_attr "conds" "clob") (set_attr "length" "8") @@ -7423,16 +7445,19 @@ (compare:CC (match_dup 3) (match_dup 4))) (set (match_dup 2) (minus:SI (match_dup 5) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])] + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); if (CONST_INT_P (operands[1])) { - operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode, - DImode, - operands[1]))); - operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]); + operands[4] = gen_highpart_mode (SImode, DImode, operands[1]); + if (operands[4] == const0_rtx) + operands[5] = operands[3]; + else + operands[5] = gen_rtx_PLUS (SImode, operands[3], + gen_int_mode (-UINTVAL (operands[4]), + SImode)); } else { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f872fc4c8f8..70e692bcec7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2019-02-25 Jakub Jelinek + PR target/89434 + * gcc.c-torture/execute/pr89434.c: New test. + PR target/89438 * gcc.dg/pr89438.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr89434.c b/gcc/testsuite/gcc.c-torture/execute/pr89434.c new file mode 100644 index 00000000000..5c26266e522 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr89434.c @@ -0,0 +1,29 @@ +/* PR target/89434 */ + +#if __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 && __CHAR_BIT__ == 8 +long g = 0; + +static inline unsigned long long +foo (unsigned long long u) +{ + unsigned x; + __builtin_mul_overflow (-1, g, &x); + u |= (unsigned) u < (unsigned short) x; + return x - u; +} + +int +main () +{ + unsigned long long x = foo (0x222222222ULL); + if (x != 0xfffffffddddddddeULL) + __builtin_abort (); + return 0; +} +#else +int +main () +{ + return 0; +} +#endif diff --git a/gcc/testsuite/gcc.dg/pr89434.c b/gcc/testsuite/gcc.dg/pr89434.c new file mode 100644 index 00000000000..477adb50c25 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr89434.c @@ -0,0 +1,5 @@ +/* PR target/89434 */ +/* { dg-do run } */ +/* { dg-options "-Og" } */ + +#include "../gcc.c-torture/execute/pr89434.c" -- 2.30.2