diff options
author | Wilco Dijkstra <wdijkstr@arm.com> | 2019-09-18 19:52:09 +0000 |
---|---|---|
committer | Wilco Dijkstra <wilco@gcc.gnu.org> | 2019-09-18 19:52:09 +0000 |
commit | 1ea956609a5a4ac12841ef86353995bd434fa1ef (patch) | |
tree | 04a0a7e9b8668596a3050d3f99b2ce21094b21d6 /gcc | |
parent | 7706f2f312a87b0c8509cccc986d6372dcd2fbcf (diff) | |
download | gcc-1ea956609a5a4ac12841ef86353995bd434fa1ef.zip gcc-1ea956609a5a4ac12841ef86353995bd434fa1ef.tar.gz gcc-1ea956609a5a4ac12841ef86353995bd434fa1ef.tar.bz2 |
[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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 4 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 43 | ||||
-rw-r--r-- | gcc/config/arm/iterators.md | 5 | ||||
-rw-r--r-- | gcc/config/arm/predicates.md | 15 |
5 files changed, 79 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0a20e86..04715c1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -13,6 +13,20 @@ 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. (mulsidi3adddi): Remove pattern. (mulsidi3adddi_v6): Likewise. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index c9ab71e..9f0975d 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -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); diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 0054ed4..d54082b 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -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. diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index c29897a..5e3299e 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -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 ;;---------------------------------------------------------------------------- diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index 983faac..8b36e7ee 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -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"))) |