public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][ARM] Add logical DImode expanders
@ 2019-08-29 18:09 Wilco Dijkstra
  2019-09-09 17:06 ` Wilco Dijkstra
  0 siblings, 1 reply; 8+ messages in thread
From: Wilco Dijkstra @ 2019-08-29 18:09 UTC (permalink / raw)
  To: GCC Patches, Kyrylo Tkachov; +Cc: nd

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.

Bootstrap OK on armhf, regress passes.

ChangeLog:
2019-08-29  Wilco Dijkstra  <wdijkstr@arm.com>

	* config/arm/arm.md (anddi3): Expand explicitly.
	(iordi3): Likewise.
	(xordi3): Likewise.
	(one_cmpldi2): Likewise.
	* config/arm/arm.c (const_ok_for_dimode_op): Return true if one
	of the constant parts is simple.
	* config/arm/predicates.md (arm_anddi_operand): Add predicate.
	(arm_iordi_operand): Add predicate.
	(arm_xordi_operand): Add predicate.

--

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index fb57880fe0568be96a04aee1b7d230e77121e3f5..1fec00baa2a5e510ef2c02d9766432cc7cd0a17b 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -4273,8 +4273,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 ed49c4beda138633a84b58fe345cf5ba99103ab7..738d42fd164f117f1dec1108a824d984ccd70d09 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -2176,6 +2176,89 @@ (define_expand "divdf3"
   "")
 \f
 
+; 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 "anddi3"
+  [(set (match_operand:DI	  0 "s_register_operand")
+	(and:DI (match_operand:DI 1 "s_register_operand")
+		(match_operand:DI 2 "arm_anddi_operand")))]
+  "TARGET_32BIT"
+  {
+      rtx low  = simplify_gen_binary (AND, SImode,
+				      gen_lowpart (SImode, operands[1]),
+				      gen_lowpart (SImode, operands[2]));
+      rtx high = simplify_gen_binary (AND, 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 "iordi3"
+  [(set (match_operand:DI	  0 "s_register_operand")
+	(ior:DI (match_operand:DI 1 "s_register_operand")
+		(match_operand:DI 2 "arm_iordi_operand")))]
+  "TARGET_32BIT"
+  {
+      rtx low  = simplify_gen_binary (IOR, SImode,
+				      gen_lowpart (SImode, operands[1]),
+				      gen_lowpart (SImode, operands[2]));
+      rtx high = simplify_gen_binary (IOR, 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 "xordi3"
+  [(set (match_operand:DI	  0 "s_register_operand")
+	(xor:DI (match_operand:DI 1 "s_register_operand")
+		(match_operand:DI 2 "arm_xordi_operand")))]
+  "TARGET_32BIT"
+  {
+	rtx low  = simplify_gen_binary (XOR, SImode,
+					gen_lowpart (SImode, operands[1]),
+					gen_lowpart (SImode, operands[2]));
+	rtx high = simplify_gen_binary (XOR, 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/predicates.md b/gcc/config/arm/predicates.md
index 59dc2e89534a8b85df1197bd7211af43c56fb18c..82a2c841a51e6da120303bf0037280da0d10b049 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -206,6 +206,21 @@ (define_predicate "arm_adddi_operand"
        (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")))

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-09-19 16:54 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-29 18:09 [PATCH][ARM] Add logical DImode expanders Wilco Dijkstra
2019-09-09 17:06 ` Wilco Dijkstra
2019-09-18 16:17   ` Kyrill Tkachov
2019-09-18 19:55     ` Wilco Dijkstra
2019-09-19 10:26       ` Richard Earnshaw (lists)
2019-09-19 14:26         ` Wilco Dijkstra
2019-09-19 16:16           ` Richard Earnshaw (lists)
2019-09-19 16:54             ` Wilco Dijkstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).