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

login
register
mail settings
Submitter Uros Bizjak
Date May 6, 2012, 8:45 p.m.
Message ID <CAFULd4by+T9kSdTBtbd_EuE7EMd-a4ZGLBgPUjqxzaESdaTdzQ@mail.gmail.com>
Download mbox | patch
Permalink /patch/157194/
State New
Headers show

Comments

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

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"