re PR target/53447 (missed optimization of 64bit ALU operation with small constant)

PR target/53447
	* config/arm/arm-protos.h (const_ok_for_dimode_op): New prototype.
	* config/arm/arm.c (const_ok_for_dimode_op): New function.
	* config/arm/constraints.md (Dd): New constraint.
	* config/arm/predicates.md (arm_adddi_operand): New predicate.
	* config/arm/arm.md (adddi3): Extend it to handle constants.
	(arm_adddi3): Likewise.
	(addsi3_carryin_<optab>): Extend it to handle sbc case.
	(addsi3_carryin_alt2_<optab>): Likewise.
	* config/arm/neon.md (adddi3_neon): Extend it to handle constants.

	* gcc.target/arm/pr53447-1.c: New testcase.
	* gcc.target/arm/pr53447-2.c: New testcase.
	* gcc.target/arm/pr53447-3.c: New testcase.
	* gcc.target/arm/pr53447-4.c: New testcase.

From-SVN: r189102
This commit is contained in:
Wei Guozhi 2012-07-01 15:14:52 +00:00 committed by Wei Guozhi
parent 9faeb49326
commit 44cd681003
12 changed files with 117 additions and 21 deletions

View File

@ -1,3 +1,16 @@
2012-07-01 Wei Guozhi <carrot@google.com>
PR target/53447
* config/arm/arm-protos.h (const_ok_for_dimode_op): New prototype.
* config/arm/arm.c (const_ok_for_dimode_op): New function.
* config/arm/constraints.md (Dd): New constraint.
* config/arm/predicates.md (arm_adddi_operand): New predicate.
* config/arm/arm.md (adddi3): Extend it to handle constants.
(arm_adddi3): Likewise.
(addsi3_carryin_<optab>): Extend it to handle sbc case.
(addsi3_carryin_alt2_<optab>): Likewise.
* config/arm/neon.md (adddi3_neon): Extend it to handle constants.
2012-06-30 Nathan Sidwell <nathan@acm.org> 2012-06-30 Nathan Sidwell <nathan@acm.org>
* coverage.c (bbg_file_stamp): New. * coverage.c (bbg_file_stamp): New.

View File

@ -50,6 +50,7 @@ extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode);
extern bool arm_modes_tieable_p (enum machine_mode, enum machine_mode); extern bool arm_modes_tieable_p (enum machine_mode, enum machine_mode);
extern int const_ok_for_arm (HOST_WIDE_INT); extern int const_ok_for_arm (HOST_WIDE_INT);
extern int const_ok_for_op (HOST_WIDE_INT, enum rtx_code); extern int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
extern int const_ok_for_dimode_op (HOST_WIDE_INT, enum rtx_code);
extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx, extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
HOST_WIDE_INT, rtx, rtx, int); HOST_WIDE_INT, rtx, rtx, int);
extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *); extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);

View File

@ -2507,6 +2507,28 @@ const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code)
} }
} }
/* Return true if I is a valid di mode constant for the operation CODE. */
int
const_ok_for_dimode_op (HOST_WIDE_INT i, enum rtx_code code)
{
HOST_WIDE_INT hi_val = (i >> 32) & 0xFFFFFFFF;
HOST_WIDE_INT lo_val = i & 0xFFFFFFFF;
rtx hi = GEN_INT (hi_val);
rtx lo = GEN_INT (lo_val);
if (TARGET_THUMB1)
return 0;
switch (code)
{
case PLUS:
return arm_not_operand (hi, SImode) && arm_add_operand (lo, SImode);
default:
return 0;
}
}
/* Emit a sequence of insns to handle a large constant. /* Emit a sequence of insns to handle a large constant.
CODE is the code of the operation required, it can be any of SET, PLUS, CODE is the code of the operation required, it can be any of SET, PLUS,
IOR, AND, XOR, MINUS; IOR, AND, XOR, MINUS;

View File

@ -604,7 +604,7 @@
[(parallel [(parallel
[(set (match_operand:DI 0 "s_register_operand" "") [(set (match_operand:DI 0 "s_register_operand" "")
(plus:DI (match_operand:DI 1 "s_register_operand" "") (plus:DI (match_operand:DI 1 "s_register_operand" "")
(match_operand:DI 2 "s_register_operand" ""))) (match_operand:DI 2 "arm_adddi_operand" "")))
(clobber (reg:CC CC_REGNUM))])] (clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER" "TARGET_EITHER"
" "
@ -630,9 +630,9 @@
) )
(define_insn_and_split "*arm_adddi3" (define_insn_and_split "*arm_adddi3"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r") [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0") (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
(match_operand:DI 2 "s_register_operand" "r, 0"))) (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
(clobber (reg:CC CC_REGNUM))] (clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT && !TARGET_NEON" "TARGET_32BIT && !TARGET_NEON"
"#" "#"
@ -650,7 +650,7 @@
operands[0] = gen_lowpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]);
operands[4] = gen_highpart (SImode, operands[1]); operands[4] = gen_highpart (SImode, operands[1]);
operands[1] = gen_lowpart (SImode, operands[1]); operands[1] = gen_lowpart (SImode, operands[1]);
operands[5] = gen_highpart (SImode, operands[2]); operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
operands[2] = gen_lowpart (SImode, operands[2]); operands[2] = gen_lowpart (SImode, operands[2]);
}" }"
[(set_attr "conds" "clob") [(set_attr "conds" "clob")
@ -1001,22 +1001,26 @@
) )
(define_insn "*addsi3_carryin_<optab>" (define_insn "*addsi3_carryin_<optab>"
[(set (match_operand:SI 0 "s_register_operand" "=r") [(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r") (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r")
(match_operand:SI 2 "arm_rhs_operand" "rI")) (match_operand:SI 2 "arm_not_operand" "rI,K"))
(LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))] (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
"TARGET_32BIT" "TARGET_32BIT"
"adc%?\\t%0, %1, %2" "@
adc%?\\t%0, %1, %2
sbc%?\\t%0, %1, #%B2"
[(set_attr "conds" "use")] [(set_attr "conds" "use")]
) )
(define_insn "*addsi3_carryin_alt2_<optab>" (define_insn "*addsi3_carryin_alt2_<optab>"
[(set (match_operand:SI 0 "s_register_operand" "=r") [(set (match_operand:SI 0 "s_register_operand" "=r,r")
(plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0)) (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
(match_operand:SI 1 "s_register_operand" "%r")) (match_operand:SI 1 "s_register_operand" "%r,r"))
(match_operand:SI 2 "arm_rhs_operand" "rI")))] (match_operand:SI 2 "arm_rhs_operand" "rI,K")))]
"TARGET_32BIT" "TARGET_32BIT"
"adc%?\\t%0, %1, %2" "@
adc%?\\t%0, %1, %2
sbc%?\\t%0, %1, #%B2"
[(set_attr "conds" "use")] [(set_attr "conds" "use")]
) )

View File

@ -31,7 +31,7 @@
;; 'H' was previously used for FPA. ;; 'H' was previously used for FPA.
;; The following multi-letter normal constraints have been used: ;; The following multi-letter normal constraints have been used:
;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di, Dt, Dz ;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, Dl, DL, Dv, Dy, Di, Dt, Dz
;; in Thumb-1 state: Pa, Pb, Pc, Pd, Pe ;; in Thumb-1 state: Pa, Pb, Pc, Pd, Pe
;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py ;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py
@ -242,6 +242,12 @@
(match_test "TARGET_32BIT && arm_const_double_inline_cost (op) == 4 (match_test "TARGET_32BIT && arm_const_double_inline_cost (op) == 4
&& !(optimize_size || arm_ld_sched)"))) && !(optimize_size || arm_ld_sched)")))
(define_constraint "Dd"
"@internal
In ARM/Thumb-2 state a const_int that can be used by insn adddi."
(and (match_code "const_int")
(match_test "TARGET_32BIT && const_ok_for_dimode_op (ival, PLUS)")))
(define_constraint "Di" (define_constraint "Di"
"@internal "@internal
In ARM/Thumb-2 state a const_int or const_double where both the high In ARM/Thumb-2 state a const_int or const_double where both the high

View File

@ -587,9 +587,9 @@
) )
(define_insn "adddi3_neon" (define_insn "adddi3_neon"
[(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w") [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?w,?&r,?&r,?&r")
(plus:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,w") (plus:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,w,r,0,r")
(match_operand:DI 2 "s_register_operand" "w,r,0,w"))) (match_operand:DI 2 "arm_adddi_operand" "w,r,0,w,r,Dd,Dd")))
(clobber (reg:CC CC_REGNUM))] (clobber (reg:CC CC_REGNUM))]
"TARGET_NEON" "TARGET_NEON"
{ {
@ -599,13 +599,16 @@
case 3: return "vadd.i64\t%P0, %P1, %P2"; case 3: return "vadd.i64\t%P0, %P1, %P2";
case 1: return "#"; case 1: return "#";
case 2: return "#"; case 2: return "#";
case 4: return "#";
case 5: return "#";
case 6: return "#";
default: gcc_unreachable (); default: gcc_unreachable ();
} }
} }
[(set_attr "neon_type" "neon_int_1,*,*,neon_int_1") [(set_attr "neon_type" "neon_int_1,*,*,neon_int_1,*,*,*")
(set_attr "conds" "*,clob,clob,*") (set_attr "conds" "*,clob,clob,*,clob,clob,clob")
(set_attr "length" "*,8,8,*") (set_attr "length" "*,8,8,*,8,8,8")
(set_attr "arch" "nota8,*,*,onlya8")] (set_attr "arch" "nota8,*,*,onlya8,*,*,*")]
) )
(define_insn "*sub<mode>3_neon" (define_insn "*sub<mode>3_neon"

View File

@ -141,6 +141,11 @@
(ior (match_operand 0 "arm_rhs_operand") (ior (match_operand 0 "arm_rhs_operand")
(match_operand 0 "arm_neg_immediate_operand"))) (match_operand 0 "arm_neg_immediate_operand")))
(define_predicate "arm_adddi_operand"
(ior (match_operand 0 "s_register_operand")
(and (match_code "const_int")
(match_test "const_ok_for_dimode_op (INTVAL (op), PLUS)"))))
(define_predicate "arm_addimm_operand" (define_predicate "arm_addimm_operand"
(ior (match_operand 0 "arm_immediate_operand") (ior (match_operand 0 "arm_immediate_operand")
(match_operand 0 "arm_neg_immediate_operand"))) (match_operand 0 "arm_neg_immediate_operand")))

View File

@ -1,3 +1,11 @@
2012-07-01 Wei Guozhi <carrot@google.com>
PR target/53447
* gcc.target/arm/pr53447-1.c: New testcase.
* gcc.target/arm/pr53447-2.c: New testcase.
* gcc.target/arm/pr53447-3.c: New testcase.
* gcc.target/arm/pr53447-4.c: New testcase.
2012-06-29 Richard Guenther <rguenther@suse.de> 2012-06-29 Richard Guenther <rguenther@suse.de>
PR tree-optimization/47061 PR tree-optimization/47061

View File

@ -0,0 +1,8 @@
/* { dg-options "-O2" } */
/* { dg-require-effective-target arm32 } */
/* { dg-final { scan-assembler-not "mov" } } */
void t0p(long long * p)
{
*p += 0x100000001;
}

View File

@ -0,0 +1,8 @@
/* { dg-options "-O2" } */
/* { dg-require-effective-target arm32 } */
/* { dg-final { scan-assembler-not "mov" } } */
void t0p(long long * p)
{
*p -= 0x100000008;
}

View File

@ -0,0 +1,9 @@
/* { dg-options "-O2" } */
/* { dg-require-effective-target arm32 } */
/* { dg-final { scan-assembler-not "mov" } } */
void t0p(long long * p)
{
*p +=0x1fffffff8;
}

View File

@ -0,0 +1,9 @@
/* { dg-options "-O2" } */
/* { dg-require-effective-target arm32 } */
/* { dg-final { scan-assembler-not "mov" } } */
void t0p(long long * p)
{
*p -=0x1fffffff8;
}