[ARM] Add logical DImode expanders
We currently use default mid-end expanders for logical DImode operations. These split operations without first splitting off complex immediates or memory operands. The resulting expansions are non-optimal and allow for fewer LDRD/STRD opportunities. So add back explicit expanders which ensure memory operands and immediates are handled more efficiently. gcc/ PR target/91738 * config/arm/arm.md (<logical_op>di3): Expand explicitly. (one_cmpldi2): Likewise. * config/arm/arm.c (const_ok_for_dimode_op): Return true if one of the constant parts is simple. * config/arm/iterators.md (LOGICAL): Add new code iterator. (logical_op): Add new code attribute. (logical_OP): Likewise. * config/arm/predicates.md (arm_anddi_operand): Add predicate. (arm_iordi_operand): Add predicate. (arm_xordi_operand): Add predicate. From-SVN: r275907
This commit is contained in:
parent
7706f2f312
commit
1ea956609a
|
@ -11,6 +11,20 @@
|
|||
pseudo register store cost from 3 to 6 to make it the same as
|
||||
QImode and HImode.
|
||||
|
||||
2019-09-18 Wilco Dijkstra <wdijkstr@arm.com>
|
||||
|
||||
PR target/91738
|
||||
* config/arm/arm.md (<logical_op>di3): Expand explicitly.
|
||||
(one_cmpldi2): Likewise.
|
||||
* config/arm/arm.c (const_ok_for_dimode_op): Return true if one
|
||||
of the constant parts is simple.
|
||||
* config/arm/iterators.md (LOGICAL): Add new code iterator.
|
||||
(logical_op): Add new code attribute.
|
||||
(logical_OP): Likewise.
|
||||
* config/arm/predicates.md (arm_anddi_operand): Add predicate.
|
||||
(arm_iordi_operand): Add predicate.
|
||||
(arm_xordi_operand): Add predicate.
|
||||
|
||||
2019-09-18 Wilco Dijkstra <wdijkstr@arm.com>
|
||||
|
||||
* config/arm/arm.md (maddsidi4): Remove expander.
|
||||
|
|
|
@ -4390,8 +4390,8 @@ const_ok_for_dimode_op (HOST_WIDE_INT i, enum rtx_code code)
|
|||
case AND:
|
||||
case IOR:
|
||||
case XOR:
|
||||
return (const_ok_for_op (hi_val, code) || hi_val == 0xFFFFFFFF)
|
||||
&& (const_ok_for_op (lo_val, code) || lo_val == 0xFFFFFFFF);
|
||||
return const_ok_for_op (hi_val, code) || hi_val == 0xFFFFFFFF
|
||||
|| const_ok_for_op (lo_val, code) || lo_val == 0xFFFFFFFF;
|
||||
case PLUS:
|
||||
return arm_not_operand (hi, SImode) && arm_add_operand (lo, SImode);
|
||||
|
||||
|
|
|
@ -2035,6 +2035,49 @@
|
|||
"")
|
||||
|
||||
|
||||
; Expand logical operations. The mid-end expander does not split off memory
|
||||
; operands or complex immediates, which leads to fewer LDRD/STRD instructions.
|
||||
; So an explicit expander is needed to generate better code.
|
||||
|
||||
(define_expand "<logical_op>di3"
|
||||
[(set (match_operand:DI 0 "s_register_operand")
|
||||
(LOGICAL:DI (match_operand:DI 1 "s_register_operand")
|
||||
(match_operand:DI 2 "arm_<logical_op>di_operand")))]
|
||||
"TARGET_32BIT"
|
||||
{
|
||||
rtx low = simplify_gen_binary (<logical_OP>, SImode,
|
||||
gen_lowpart (SImode, operands[1]),
|
||||
gen_lowpart (SImode, operands[2]));
|
||||
rtx high = simplify_gen_binary (<logical_OP>, SImode,
|
||||
gen_highpart (SImode, operands[1]),
|
||||
gen_highpart_mode (SImode, DImode,
|
||||
operands[2]));
|
||||
|
||||
emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
|
||||
emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
|
||||
DONE;
|
||||
}
|
||||
)
|
||||
|
||||
(define_expand "one_cmpldi2"
|
||||
[(set (match_operand:DI 0 "s_register_operand")
|
||||
(not:DI (match_operand:DI 1 "s_register_operand")))]
|
||||
"TARGET_32BIT"
|
||||
{
|
||||
rtx low = simplify_gen_unary (NOT, SImode,
|
||||
gen_lowpart (SImode, operands[1]),
|
||||
SImode);
|
||||
rtx high = simplify_gen_unary (NOT, SImode,
|
||||
gen_highpart_mode (SImode, DImode,
|
||||
operands[1]),
|
||||
SImode);
|
||||
|
||||
emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
|
||||
emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
|
||||
DONE;
|
||||
}
|
||||
)
|
||||
|
||||
;; Split DImode and, ior, xor operations. Simply perform the logical
|
||||
;; operation on the upper and lower halves of the registers.
|
||||
;; This is needed for atomic operations in arm_split_atomic_op.
|
||||
|
|
|
@ -239,6 +239,8 @@
|
|||
;; A list of ...
|
||||
(define_code_iterator IOR_XOR [ior xor])
|
||||
|
||||
(define_code_iterator LOGICAL [and ior xor])
|
||||
|
||||
;; Operations on two halves of a quadword vector.
|
||||
(define_code_iterator VQH_OPS [plus smin smax umin umax])
|
||||
|
||||
|
@ -285,6 +287,9 @@
|
|||
|
||||
(define_code_attr vfml_op [(plus "a") (minus "s")])
|
||||
|
||||
(define_code_attr logical_op [(ior "ior") (xor "xor") (and "and")])
|
||||
(define_code_attr logical_OP [(ior "IOR") (xor "XOR") (and "AND")])
|
||||
|
||||
;;----------------------------------------------------------------------------
|
||||
;; Int iterators
|
||||
;;----------------------------------------------------------------------------
|
||||
|
|
|
@ -206,6 +206,21 @@
|
|||
(and (match_code "const_int")
|
||||
(match_test "const_ok_for_dimode_op (INTVAL (op), PLUS)"))))
|
||||
|
||||
(define_predicate "arm_anddi_operand"
|
||||
(ior (match_operand 0 "s_register_operand")
|
||||
(and (match_code "const_int")
|
||||
(match_test "const_ok_for_dimode_op (INTVAL (op), AND)"))))
|
||||
|
||||
(define_predicate "arm_iordi_operand"
|
||||
(ior (match_operand 0 "s_register_operand")
|
||||
(and (match_code "const_int")
|
||||
(match_test "const_ok_for_dimode_op (INTVAL (op), IOR)"))))
|
||||
|
||||
(define_predicate "arm_xordi_operand"
|
||||
(ior (match_operand 0 "s_register_operand")
|
||||
(and (match_code "const_int")
|
||||
(match_test "const_ok_for_dimode_op (INTVAL (op), XOR)"))))
|
||||
|
||||
(define_predicate "arm_addimm_operand"
|
||||
(ior (match_operand 0 "arm_immediate_operand")
|
||||
(match_operand 0 "arm_neg_immediate_operand")))
|
||||
|
|
Loading…
Reference in New Issue