re PR target/53568 (SH Target: Add support for bswap built-ins)
authorOleg Endo <olegendo@gcc.gnu.org>
Thu, 14 Jun 2012 19:33:10 +0000 (19:33 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Thu, 14 Jun 2012 19:33:10 +0000 (19:33 +0000)
PR target/53568
* config/sh/sh.md: Add peephole for swapbsi2.
(*swapbisi2_and_shl8, *swapbhisi2): New insns and splits.

From-SVN: r188632

gcc/ChangeLog
gcc/config/sh/sh.md

index 1e6d89f9beff3e23f87d2f4e1d1eb85d4ed51b2f..e9b0007e96ed14f57e91d8c3b5e584fd8519b3ec 100644 (file)
@@ -1,3 +1,9 @@
+2012-06-14  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/53568
+       * config/sh/sh.md: Add peephole for swapbsi2.
+       (*swapbisi2_and_shl8, *swapbhisi2): New insns and splits.
+
 2012-06-14  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (*zero_extendsidi2): Mark movd alternatives
index 05a4f38c1dcbaf8e4e0cc359654451a21507936f..852f9fd36ea0543ee6397d5d6be636c868639188 100644 (file)
@@ -4561,6 +4561,81 @@ label:
   "swap.b      %1,%0"
   [(set_attr "type" "arith")])
 
+;; The *swapbisi2_and_shl8 pattern helps the combine pass simplifying
+;; partial byte swap expressions such as...
+;;   ((x & 0xFF) << 8) | ((x >> 8) & 0xFF).
+;; ...which are currently not handled by the tree optimizers.
+;; The combine pass will not initially try to combine the full expression,
+;; but only some sub-expressions.  In such a case the *swapbisi2_and_shl8
+;; pattern acts as an intermediate pattern that will eventually lead combine
+;; to the swapbsi2 pattern above.
+;; As a side effect this also improves code that does (x & 0xFF) << 8
+;; or (x << 8) & 0xFF00.
+(define_insn_and_split "*swapbisi2_and_shl8"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+       (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
+                                  (const_int 8))
+                       (const_int 65280))
+               (match_operand:SI 2 "arith_reg_operand" "r")))]
+  "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
+  "#"
+  "&& can_create_pseudo_p ()"
+  [(const_int 0)]
+{
+  rtx tmp0 = gen_reg_rtx (SImode);
+  rtx tmp1 = gen_reg_rtx (SImode);
+
+  emit_insn (gen_zero_extendqisi2 (tmp0, gen_lowpart (QImode, operands[1])));
+  emit_insn (gen_swapbsi2 (tmp1, tmp0));
+  emit_insn (gen_iorsi3 (operands[0], tmp1, operands[2]));
+  DONE;
+})
+
+;; The *swapbhisi2 pattern is, like the *swapbisi2_and_shl8 pattern, another
+;; intermediate pattern that will help the combine pass arriving at swapbsi2.
+(define_insn_and_split "*swapbhisi2"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+       (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
+                                  (const_int 8))
+                       (const_int 65280))
+               (zero_extract:SI (match_dup 1) (const_int 8) (const_int 8))))]
+  "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
+  "#"
+  "&& can_create_pseudo_p ()"
+  [(const_int 0)]
+{
+  rtx tmp = gen_reg_rtx (SImode);
+
+  emit_insn (gen_zero_extendhisi2 (tmp, gen_lowpart (HImode, operands[1])));
+  emit_insn (gen_swapbsi2 (operands[0], tmp));
+  DONE;
+})
+
+;; In some cases the swapbsi2 pattern might leave a sequence such as...
+;;   swap.b  r4,r4
+;;   mov     r4,r0
+;;
+;; which can be simplified to...
+;;   swap.b  r4,r0
+(define_peephole2
+  [(set (match_operand:SI 0 "arith_reg_dest" "")
+       (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
+                       (const_int 4294901760))
+               (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
+                               (const_int 65280))
+                       (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
+                               (const_int 255)))))
+   (set (match_operand:SI 2 "arith_reg_dest" "")
+       (match_dup 0))]
+  "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 2)
+       (ior:SI (and:SI (match_operand:SI 1 "arith_reg_operand" "")
+                       (const_int 4294901760))
+               (ior:SI (and:SI (ashift:SI (match_dup 1) (const_int 8))
+                               (const_int 65280))
+                       (and:SI (ashiftrt:SI (match_dup 1) (const_int 8))
+                               (const_int 255)))))])
+
 \f
 ;; -------------------------------------------------------------------------
 ;; Zero extension instructions