aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-02-25 11:32:38 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2019-02-25 11:32:38 +0100
commit5c561248378ab07fb2abd6766b16572d8b903545 (patch)
treeed628bf6873ea15d090cf86a3a1800d38d42502e
parent4199c859ac95ee15433902b5d2a3a537b36e4752 (diff)
downloadgcc-5c561248378ab07fb2abd6766b16572d8b903545.zip
gcc-5c561248378ab07fb2abd6766b16572d8b903545.tar.gz
gcc-5c561248378ab07fb2abd6766b16572d8b903545.tar.bz2
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
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/config/arm/arm.md49
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr89434.c29
-rw-r--r--gcc/testsuite/gcc.dg/pr89434.c5
5 files changed, 91 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9328618..cce2741 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,22 @@
2019-02-25 Jakub Jelinek <jakub@redhat.com>
+ 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 0e35d03..349b0a5 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 f872fc4..70e692b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2019-02-25 Jakub Jelinek <jakub@redhat.com>
+ 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 0000000..5c26266
--- /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 0000000..477adb5
--- /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"