Hello!
Attached patch splits bswap patterns on 32bit targets by hand, as is
the case with all other DImode patterns. The patch takes into account
memory operands, where it swaps high/low word load according to
bswap/movbe insn availability, and generates xcgh %rX, %rY for reg-reg
swaps, avoiding a move to/from temporary register.
2012-05-06 Uros Bizjak <[email protected]>
PR target/53227
* config/i386/i386.md (swap<mode>): Rename from *swap<mode>.
(bswapdi2): Split from bswap<mode>2. Use nonnimediate_operand
predicate for operand 1. Force operand 1 to register for TARGET_BSWAP.
(bswapsi2): Ditto.
(*bswapdi2_doubleword): New insn pattern.
(*bswap<mode>2): Rename from *bswap<mode>2_1.
Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu.
Committed to mainline SVN.
Uros.
Index: i386.md
===================================================================
--- i386.md (revision 187211)
+++ i386.md (working copy)
@@ -2406,7 +2406,7 @@
(set_attr "memory" "load")
(set_attr "mode" "<MODE>")])
-(define_insn "*swap<mode>"
+(define_insn "swap<mode>"
[(set (match_operand:SWI48 0 "register_operand" "+r")
(match_operand:SWI48 1 "register_operand" "+r"))
(set (match_dup 1)
@@ -12487,13 +12487,71 @@
(set_attr "type" "bitmanip")
(set_attr "mode" "SI")])
-(define_expand "bswap<mode>2"
- [(set (match_operand:SWI48 0 "register_operand")
- (bswap:SWI48 (match_operand:SWI48 1 "register_operand")))]
+(define_expand "bswapdi2"
+ [(set (match_operand:DI 0 "register_operand")
+ (bswap:DI (match_operand:DI 1 "nonimmediate_operand")))]
""
{
- if (<MODE>mode == SImode && !(TARGET_BSWAP || TARGET_MOVBE))
+ if (TARGET_64BIT && !TARGET_MOVBE)
+ operands[1] = force_reg (DImode, operands[1]);
+})
+
+(define_insn_and_split "*bswapdi2_doubleword"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m")
+ (bswap:DI
+ (match_operand:DI 1 "nonimmediate_operand" "0,m,r")))]
+ "!TARGET_64BIT
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2)
+ (bswap:SI (match_dup 1)))
+ (set (match_dup 0)
+ (bswap:SI (match_dup 3)))]
+{
+ split_double_mode (DImode, &operands[0], 2, &operands[0], &operands[2]);
+
+ if (REG_P (operands[0]) && REG_P (operands[1]))
{
+ emit_insn (gen_swapsi (operands[0], operands[2]));
+ emit_insn (gen_bswapsi2 (operands[0], operands[0]));
+ emit_insn (gen_bswapsi2 (operands[2], operands[2]));
+ DONE;
+ }
+
+ if (!TARGET_MOVBE)
+ {
+ if (MEM_P (operands[0]))
+ {
+ emit_insn (gen_bswapsi2 (operands[3], operands[3]));
+ emit_insn (gen_bswapsi2 (operands[1], operands[1]));
+
+ emit_move_insn (operands[0], operands[3]);
+ emit_move_insn (operands[2], operands[1]);
+ }
+ if (MEM_P (operands[1]))
+ {
+ emit_move_insn (operands[2], operands[1]);
+ emit_move_insn (operands[0], operands[3]);
+
+ emit_insn (gen_bswapsi2 (operands[2], operands[2]));
+ emit_insn (gen_bswapsi2 (operands[0], operands[0]));
+ }
+ DONE;
+ }
+})
+
+(define_expand "bswapsi2"
+ [(set (match_operand:SI 0 "register_operand")
+ (bswap:SI (match_operand:SI 1 "nonimmediate_operand")))]
+ ""
+{
+ if (TARGET_MOVBE)
+ ;
+ else if (TARGET_BSWAP)
+ operands[1] = force_reg (SImode, operands[1]);
+ else
+ {
rtx x = operands[0];
emit_move_insn (x, operands[1]);
@@ -12519,7 +12577,7 @@
(set_attr "prefix_extra" "*,1,1")
(set_attr "mode" "<MODE>")])
-(define_insn "*bswap<mode>2_1"
+(define_insn "*bswap<mode>2"
[(set (match_operand:SWI48 0 "register_operand" "=r")
(bswap:SWI48 (match_operand:SWI48 1 "register_operand" "0")))]
"TARGET_BSWAP"