]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[ARM] Add logical DImode expanders
authorWilco Dijkstra <wdijkstr@arm.com>
Wed, 18 Sep 2019 19:52:09 +0000 (19:52 +0000)
committerWilco Dijkstra <wilco@gcc.gnu.org>
Wed, 18 Sep 2019 19:52:09 +0000 (19:52 +0000)
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

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.md
gcc/config/arm/iterators.md
gcc/config/arm/predicates.md

index 0a20e8644dba130168b5aa63d2a429f73f48def1..04715c146c80f19a7f2e26d796d1a5324b06a9f6 100644 (file)
        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.
index c9ab71e57ef434e7128e71711ffb91f306738f27..9f0975dc0710626ef46abecaa3a205e993821118 100644 (file)
@@ -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);
 
index 0054ed45de830a2512932d2178ad8b7f4e820c51..d54082b13dd702aa55a1465c0fbfa87baa89149a 100644 (file)
   "")
 \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 "<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.
index c29897a3b70d342b025c72b8c032bb3bb831040f..5e3299e850813db2f3c0a25a6cde779d1d0d1d55 100644 (file)
 ;; 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])
 
 
 (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
 ;;----------------------------------------------------------------------------
index 983faac8a72ef75e80cc34031c07c6435902c36f..8b36e7ee462235ad26e132f1ccf98d28c2487d67 100644 (file)
        (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")))