Skip to content

Commit 8414e41

Browse files
author
rearnsha
committed
[arm] Early split addvdi4
This patch adds early splitting for addvdi4; it's very similar to the uaddvdi4 splitter, but the details are just different enough in places, especially for the patterns that match the splitting, where we have to compare against the non-widened version to detect if overflow occurred. I've also added a testcase to the testsuite for a couple of constants that caught me out during the development of this patch. They're probably arm-specific values, but the test is generic enough that I've included it for all targets. [gcc] * config/arm/arm.c (arm_select_cc_mode): Allow either the first or second operand of the PLUS inside a DImode equality test to be sign-extend when selecting CC_Vmode. * config/arm/arm.md (addvdi4): Early-split the operation into SImode instructions. (addsi3_cin_vout_reg, addsi3_cin_vout_imm, addsi3_cin_vout_0): New expand patterns. (addsi3_cin_vout_reg_insn, addsi3_cin_vout_imm_insn): New patterns. (addsi3_cin_vout_0): Likewise. (adddi3_compareV): Delete. [gcc/testsuite] * gcc.dg/builtin-arith-overflow-3.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@277186 138bc75d-0d04-0410-961f-82ee72b054a4
1 parent 8aefed8 commit 8414e41

File tree

5 files changed

+220
-22
lines changed

5 files changed

+220
-22
lines changed

gcc/ChangeLog

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
2019-10-18 Richard Earnshaw <[email protected]>
2+
3+
* config/arm/arm.c (arm_select_cc_mode): Allow either the first
4+
or second operand of the PLUS inside a DImode equality test to be
5+
sign-extend when selecting CC_Vmode.
6+
* config/arm/arm.md (addvdi4): Early-split the operation into SImode
7+
instructions.
8+
(addsi3_cin_vout_reg, addsi3_cin_vout_imm, addsi3_cin_vout_0): New
9+
expand patterns.
10+
(addsi3_cin_vout_reg_insn, addsi3_cin_vout_imm_insn): New patterns.
11+
(addsi3_cin_vout_0): Likewise.
12+
(adddi3_compareV): Delete.
13+
114
2019-10-18 Richard Earnshaw <[email protected]>
215

316
* config/arm/arm.md (addsi3_compareV_reg_nosum): New insn.

gcc/config/arm/arm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15414,7 +15414,8 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
1541415414
if (GET_MODE (x) == DImode
1541515415
&& (op == EQ || op == NE)
1541615416
&& GET_CODE (x) == PLUS
15417-
&& GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
15417+
&& (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
15418+
|| GET_CODE (XEXP (x, 1)) == SIGN_EXTEND)
1541815419
&& GET_CODE (y) == SIGN_EXTEND
1541915420
&& GET_CODE (XEXP (y, 0)) == PLUS)
1542015421
return CC_Vmode;

gcc/config/arm/arm.md

Lines changed: 160 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -505,18 +505,173 @@
505505
})
506506

507507
(define_expand "addvdi4"
508-
[(match_operand:DI 0 "register_operand")
509-
(match_operand:DI 1 "register_operand")
510-
(match_operand:DI 2 "register_operand")
508+
[(match_operand:DI 0 "s_register_operand")
509+
(match_operand:DI 1 "s_register_operand")
510+
(match_operand:DI 2 "reg_or_int_operand")
511511
(match_operand 3 "")]
512512
"TARGET_32BIT"
513513
{
514-
emit_insn (gen_adddi3_compareV (operands[0], operands[1], operands[2]));
515-
arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
514+
rtx lo_result, hi_result;
515+
rtx lo_op1, hi_op1, lo_op2, hi_op2;
516+
arm_decompose_di_binop (operands[1], operands[2], &lo_op1, &hi_op1,
517+
&lo_op2, &hi_op2);
518+
lo_result = gen_lowpart (SImode, operands[0]);
519+
hi_result = gen_highpart (SImode, operands[0]);
520+
521+
if (lo_op2 == const0_rtx)
522+
{
523+
emit_move_insn (lo_result, lo_op1);
524+
if (!arm_add_operand (hi_op2, SImode))
525+
hi_op2 = force_reg (SImode, hi_op2);
526+
527+
emit_insn (gen_addvsi4 (hi_result, hi_op1, hi_op2, operands[3]));
528+
}
529+
else
530+
{
531+
if (!arm_add_operand (lo_op2, SImode))
532+
lo_op2 = force_reg (SImode, lo_op2);
533+
if (!arm_not_operand (hi_op2, SImode))
534+
hi_op2 = force_reg (SImode, hi_op2);
535+
536+
emit_insn (gen_addsi3_compare_op1 (lo_result, lo_op1, lo_op2));
537+
538+
if (hi_op2 == const0_rtx)
539+
emit_insn (gen_addsi3_cin_vout_0 (hi_result, hi_op1));
540+
else if (CONST_INT_P (hi_op2))
541+
emit_insn (gen_addsi3_cin_vout_imm (hi_result, hi_op1, hi_op2));
542+
else
543+
emit_insn (gen_addsi3_cin_vout_reg (hi_result, hi_op1, hi_op2));
544+
545+
arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
546+
}
516547

517548
DONE;
518549
})
519550

551+
(define_expand "addsi3_cin_vout_reg"
552+
[(parallel
553+
[(set (match_dup 3)
554+
(compare:CC_V
555+
(plus:DI
556+
(plus:DI (match_dup 4)
557+
(sign_extend:DI (match_operand:SI 1 "s_register_operand")))
558+
(sign_extend:DI (match_operand:SI 2 "s_register_operand")))
559+
(sign_extend:DI (plus:SI (plus:SI (match_dup 5) (match_dup 1))
560+
(match_dup 2)))))
561+
(set (match_operand:SI 0 "s_register_operand")
562+
(plus:SI (plus:SI (match_dup 5) (match_dup 1))
563+
(match_dup 2)))])]
564+
"TARGET_32BIT"
565+
{
566+
operands[3] = gen_rtx_REG (CC_Vmode, CC_REGNUM);
567+
rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
568+
operands[4] = gen_rtx_LTU (DImode, ccin, const0_rtx);
569+
operands[5] = gen_rtx_LTU (SImode, ccin, const0_rtx);
570+
}
571+
)
572+
573+
(define_insn "*addsi3_cin_vout_reg_insn"
574+
[(set (reg:CC_V CC_REGNUM)
575+
(compare:CC_V
576+
(plus:DI
577+
(plus:DI
578+
(match_operand:DI 3 "arm_carry_operation" "")
579+
(sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r")))
580+
(sign_extend:DI (match_operand:SI 2 "s_register_operand" "l,r")))
581+
(sign_extend:DI
582+
(plus:SI (plus:SI (match_operand:SI 4 "arm_carry_operation" "")
583+
(match_dup 1))
584+
(match_dup 2)))))
585+
(set (match_operand:SI 0 "s_register_operand" "=l,r")
586+
(plus:SI (plus:SI (match_dup 4) (match_dup 1))
587+
(match_dup 2)))]
588+
"TARGET_32BIT"
589+
"@
590+
adcs%?\\t%0, %0, %2
591+
adcs%?\\t%0, %1, %2"
592+
[(set_attr "type" "alus_sreg")
593+
(set_attr "arch" "t2,*")
594+
(set_attr "length" "2,4")]
595+
)
596+
597+
(define_expand "addsi3_cin_vout_imm"
598+
[(parallel
599+
[(set (match_dup 3)
600+
(compare:CC_V
601+
(plus:DI
602+
(plus:DI (match_dup 4)
603+
(sign_extend:DI (match_operand:SI 1 "s_register_operand")))
604+
(match_dup 2))
605+
(sign_extend:DI (plus:SI (plus:SI (match_dup 5) (match_dup 1))
606+
(match_dup 2)))))
607+
(set (match_operand:SI 0 "s_register_operand")
608+
(plus:SI (plus:SI (match_dup 5) (match_dup 1))
609+
(match_operand 2 "arm_adcimm_operand")))])]
610+
"TARGET_32BIT"
611+
{
612+
operands[3] = gen_rtx_REG (CC_Vmode, CC_REGNUM);
613+
rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
614+
operands[4] = gen_rtx_LTU (DImode, ccin, const0_rtx);
615+
operands[5] = gen_rtx_LTU (SImode, ccin, const0_rtx);
616+
}
617+
)
618+
619+
(define_insn "*addsi3_cin_vout_imm_insn"
620+
[(set (reg:CC_V CC_REGNUM)
621+
(compare:CC_V
622+
(plus:DI
623+
(plus:DI
624+
(match_operand:DI 3 "arm_carry_operation" "")
625+
(sign_extend:DI (match_operand:SI 1 "s_register_operand" "r,r")))
626+
(match_operand 2 "arm_adcimm_operand" "I,K"))
627+
(sign_extend:DI
628+
(plus:SI (plus:SI (match_operand:SI 4 "arm_carry_operation" "")
629+
(match_dup 1))
630+
(match_dup 2)))))
631+
(set (match_operand:SI 0 "s_register_operand" "=r,r")
632+
(plus:SI (plus:SI (match_dup 4) (match_dup 1))
633+
(match_dup 2)))]
634+
"TARGET_32BIT"
635+
"@
636+
adcs%?\\t%0, %1, %2
637+
sbcs%?\\t%0, %1, #%B2"
638+
[(set_attr "type" "alus_imm")]
639+
)
640+
641+
(define_expand "addsi3_cin_vout_0"
642+
[(parallel
643+
[(set (match_dup 2)
644+
(compare:CC_V
645+
(plus:DI (match_dup 3)
646+
(sign_extend:DI (match_operand:SI 1 "s_register_operand")))
647+
(sign_extend:DI (plus:SI (match_dup 4) (match_dup 1)))))
648+
(set (match_operand:SI 0 "s_register_operand")
649+
(plus:SI (match_dup 4) (match_dup 1)))])]
650+
"TARGET_32BIT"
651+
{
652+
operands[2] = gen_rtx_REG (CC_Vmode, CC_REGNUM);
653+
rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
654+
operands[3] = gen_rtx_LTU (DImode, ccin, const0_rtx);
655+
operands[4] = gen_rtx_LTU (SImode, ccin, const0_rtx);
656+
}
657+
)
658+
659+
(define_insn "*addsi3_cin_vout_0_insn"
660+
[(set (reg:CC_V CC_REGNUM)
661+
(compare:CC_V
662+
(plus:DI
663+
(match_operand:DI 2 "arm_carry_operation" "")
664+
(sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))
665+
(sign_extend:DI (plus:SI
666+
(match_operand:SI 3 "arm_carry_operation" "")
667+
(match_dup 1)))))
668+
(set (match_operand:SI 0 "s_register_operand" "=r")
669+
(plus:SI (match_dup 3) (match_dup 1)))]
670+
"TARGET_32BIT"
671+
"adcs%?\\t%0, %1, #0"
672+
[(set_attr "type" "alus_imm")]
673+
)
674+
520675
(define_expand "uaddvsi4"
521676
[(match_operand:SI 0 "s_register_operand")
522677
(match_operand:SI 1 "s_register_operand")
@@ -770,22 +925,6 @@
770925
]
771926
)
772927

773-
(define_insn "adddi3_compareV"
774-
[(set (reg:CC_V CC_REGNUM)
775-
(ne:CC_V
776-
(plus:TI
777-
(sign_extend:TI (match_operand:DI 1 "s_register_operand" "r"))
778-
(sign_extend:TI (match_operand:DI 2 "s_register_operand" "r")))
779-
(sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
780-
(set (match_operand:DI 0 "s_register_operand" "=&r")
781-
(plus:DI (match_dup 1) (match_dup 2)))]
782-
"TARGET_32BIT"
783-
"adds\\t%Q0, %Q1, %Q2;adcs\\t%R0, %R1, %R2"
784-
[(set_attr "conds" "set")
785-
(set_attr "length" "8")
786-
(set_attr "type" "multiple")]
787-
)
788-
789928
(define_insn "addsi3_compareV_reg"
790929
[(set (reg:CC_V CC_REGNUM)
791930
(compare:CC_V

gcc/testsuite/ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
2019-10-18 Richard Earnshaw <[email protected]>
2+
3+
* gcc.dg/builtin-arith-overflow-3.c: New test.
4+
15
2019-10-18 Richard Earnshaw <[email protected]>
26

37
* gcc.target/arm/negdi-3.c: Remove XFAIL markers.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* { dg-do run } */
2+
/* { dg-options "-O2" } */
3+
4+
static int cnt = 0;
5+
6+
#define LL_MIN ((long long)(-__LONG_LONG_MAX__ - 1))
7+
8+
#define SC1 (LL_MIN + 5)
9+
#define UC1 ((1ULL << (__LONG_LONG_WIDTH__ - 1)) | 5ULL)
10+
#define UC2 (~UC1)
11+
12+
long long __attribute__ ((noinline, noclone))
13+
f1 (long long a)
14+
{
15+
long long x;
16+
if (__builtin_add_overflow (a, SC1, &x)) cnt++;
17+
return x;
18+
}
19+
20+
unsigned long long __attribute__ ((noinline, noclone))
21+
f2 (unsigned long long a)
22+
{
23+
unsigned long long x;
24+
if (__builtin_add_overflow (a, UC1, &x))
25+
cnt++;
26+
return x;
27+
}
28+
29+
int main ()
30+
{
31+
if (f1 (-5) != LL_MIN) __builtin_abort ();
32+
if (cnt != 0) __builtin_abort ();
33+
f1 (-6);
34+
if (cnt != 1) __builtin_abort ();
35+
cnt = 0;
36+
if (f2 (UC2) != ~0ULL) __builtin_abort ();
37+
if (cnt != 0) __builtin_abort ();
38+
if (f2 (UC2 + 1) != 0) __builtin_abort ();
39+
if (cnt != 1) __builtin_abort ();
40+
return 0;
41+
}

0 commit comments

Comments
 (0)