aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilco Dijkstra <wdijkstr@arm.com>2019-09-18 19:52:09 +0000
committerWilco Dijkstra <wilco@gcc.gnu.org>2019-09-18 19:52:09 +0000
commit1ea956609a5a4ac12841ef86353995bd434fa1ef (patch)
tree04a0a7e9b8668596a3050d3f99b2ce21094b21d6
parent7706f2f312a87b0c8509cccc986d6372dcd2fbcf (diff)
downloadgcc-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
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/arm/arm.c4
-rw-r--r--gcc/config/arm/arm.md43
-rw-r--r--gcc/config/arm/iterators.md5
-rw-r--r--gcc/config/arm/predicates.md15
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")))