diff mbox

[i386] : Fix PR 53227, FAIL: gcc.target/i386/movbe-2.c scan-assembler-times movbe[ \t] 4

Message ID CAFULd4by+T9kSdTBtbd_EuE7EMd-a4ZGLBgPUjqxzaESdaTdzQ@mail.gmail.com
State New
Headers show

Commit Message

Uros Bizjak May 6, 2012, 8:45 p.m. UTC
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  <ubizjak@gmail.com>

	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.
diff mbox

Patch

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"