Commit 1ea95660 by Wilco Dijkstra Committed by Wilco Dijkstra

[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
parent 7706f2f3
...@@ -13,6 +13,20 @@ ...@@ -13,6 +13,20 @@
2019-09-18 Wilco Dijkstra <wdijkstr@arm.com> 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. * config/arm/arm.md (maddsidi4): Remove expander.
(mulsidi3adddi): Remove pattern. (mulsidi3adddi): Remove pattern.
(mulsidi3adddi_v6): Likewise. (mulsidi3adddi_v6): Likewise.
......
...@@ -4390,8 +4390,8 @@ const_ok_for_dimode_op (HOST_WIDE_INT i, enum rtx_code code) ...@@ -4390,8 +4390,8 @@ const_ok_for_dimode_op (HOST_WIDE_INT i, enum rtx_code code)
case AND: case AND:
case IOR: case IOR:
case XOR: case XOR:
return (const_ok_for_op (hi_val, code) || hi_val == 0xFFFFFFFF) return const_ok_for_op (hi_val, code) || hi_val == 0xFFFFFFFF
&& (const_ok_for_op (lo_val, code) || lo_val == 0xFFFFFFFF); || const_ok_for_op (lo_val, code) || lo_val == 0xFFFFFFFF;
case PLUS: case PLUS:
return arm_not_operand (hi, SImode) && arm_add_operand (lo, SImode); return arm_not_operand (hi, SImode) && arm_add_operand (lo, SImode);
......
...@@ -2035,6 +2035,49 @@ ...@@ -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 ;; Split DImode and, ior, xor operations. Simply perform the logical
;; operation on the upper and lower halves of the registers. ;; operation on the upper and lower halves of the registers.
;; This is needed for atomic operations in arm_split_atomic_op. ;; This is needed for atomic operations in arm_split_atomic_op.
......
...@@ -239,6 +239,8 @@ ...@@ -239,6 +239,8 @@
;; A list of ... ;; A list of ...
(define_code_iterator IOR_XOR [ior xor]) (define_code_iterator IOR_XOR [ior xor])
(define_code_iterator LOGICAL [and ior xor])
;; Operations on two halves of a quadword vector. ;; Operations on two halves of a quadword vector.
(define_code_iterator VQH_OPS [plus smin smax umin umax]) (define_code_iterator VQH_OPS [plus smin smax umin umax])
...@@ -285,6 +287,9 @@ ...@@ -285,6 +287,9 @@
(define_code_attr vfml_op [(plus "a") (minus "s")]) (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 ;; Int iterators
;;---------------------------------------------------------------------------- ;;----------------------------------------------------------------------------
......
...@@ -206,6 +206,21 @@ ...@@ -206,6 +206,21 @@
(and (match_code "const_int") (and (match_code "const_int")
(match_test "const_ok_for_dimode_op (INTVAL (op), PLUS)")))) (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" (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")))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment