[PATCH, i386]: Split several double-word patterns before reload

Uros Bizjak ubizjak@gmail.com
Sat Jun 15 07:47:00 GMT 2019


Attached patch moves splitting of double-word patterns that do not
result in a special instructions when split (e.g. anddi ->
andsi/andsi, ...) before reload. Before STV pass was introduced, 32bit
targets didn't define double-mode patterns, so middle-end expanded
double-mode operations to narrow-mode instructions by itself.
The split pass is performed after STV pass does its magic, so these
double-mode instructions are the remains that STV pass didn't convert.
There is no need to split them after reload, so we can use way simpler
pre-reload splitter patterns, while also leaving register allocator
more freedom to allocate non-paired narrow-mode registers.

2019-06-15  Uroš Bizjak  <ubizjak@gmail.com>

    * config/i386/i386.md (and<mode>3): Generate zero-extends for
    TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun))
    only.
    (*anddi3_doubleword): Split before reload. Merge with
    anddi->zext pre-reload splitter.
    (*andndi3_doubleword): Split before reload.
    (*<code>di3_doubleword): Ditto.
    (*one_cmpldi2_doubleword): Ditto.

Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

Committed to mainline SVN.

Uros.
-------------- next part --------------
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index b484caebc453..253fcfb2f3c8 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -8365,7 +8365,10 @@
 
   if (<MODE>mode == DImode && !TARGET_64BIT)
     ;
-  else if (CONST_INT_P (operands[2]) && REG_P (operands[0]))
+  else if (const_int_operand (operands[2], <MODE>mode)
+	   && register_operand (operands[0], <MODE>mode)
+	   && !(TARGET_ZERO_EXTEND_WITH_AND
+		&& optimize_function_for_speed_p (cfun)))
     {
       unsigned HOST_WIDE_INT ival = UINTVAL (operands[2]);
 
@@ -8388,68 +8391,34 @@
 })
 
 (define_insn_and_split "*anddi3_doubleword"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
-	(and:DI
-	 (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
-	 (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm")))
-   (clobber (reg:CC FLAGS_REG))]
-  "!TARGET_64BIT && TARGET_STV && TARGET_SSE2
-   && ix86_binary_operator_ok (AND, DImode, operands)"
-  "#"
-  "&& reload_completed"
-  [(const_int 0)]
-{
-  split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);
-  if (operands[2] == const0_rtx)
-    {
-      operands[1] = const0_rtx;
-      ix86_expand_move (SImode, &operands[0]);
-    }
-  else if (operands[2] != constm1_rtx)
-    ix86_expand_binary_operator (AND, SImode, &operands[0]);
-  else if (operands[5] == constm1_rtx)
-    emit_note (NOTE_INSN_DELETED);
-  if (operands[5] == const0_rtx)
-    {
-      operands[4] = const0_rtx;
-      ix86_expand_move (SImode, &operands[3]);
-    }
-  else if (operands[5] != constm1_rtx)
-    ix86_expand_binary_operator (AND, SImode, &operands[3]);
-  DONE;
-})
-
-(define_split
-  [(set (match_operand:DI 0 "register_operand")
+  [(set (match_operand:DI 0 "nonimmediate_operand")
 	(and:DI
 	 (match_operand:DI 1 "nonimmediate_operand")
-	 (match_operand:DI 2 "const_int_operand")))
+	 (match_operand:DI 2 "x86_64_szext_general_operand")))
    (clobber (reg:CC FLAGS_REG))]
   "!TARGET_64BIT && TARGET_STV && TARGET_SSE2
+   && ix86_binary_operator_ok (AND, DImode, operands)
    && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
   [(const_int 0)]
 {
-  unsigned HOST_WIDE_INT ival = UINTVAL (operands[2]);
-  machine_mode mode;
-
-  if (ival == GET_MODE_MASK (SImode))
-    mode = SImode;
-  else if (ival == GET_MODE_MASK (HImode))
-    mode = HImode;
-  else if (ival == GET_MODE_MASK (QImode))
-    mode = QImode;
-  else
-    FAIL;
-
   split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);
 
-  if (mode == SImode)
+  if (operands[2] == const0_rtx)
+    emit_move_insn (operands[0], const0_rtx);
+  else if (operands[2] == constm1_rtx)
     emit_move_insn (operands[0], operands[1]);
   else
-    emit_insn (gen_extend_insn
-	       (operands[0], gen_lowpart (mode, operands[1]),
-		SImode, mode, 1));
-  emit_move_insn (operands[3], const0_rtx);
+    emit_insn (gen_andsi3 (operands[0], operands[1], operands[2]));
+
+  if (operands[5] == const0_rtx)
+    emit_move_insn (operands[3], const0_rtx);
+  else if (operands[5] == constm1_rtx)
+    emit_move_insn (operands[3], operands[4]);
+  else
+    emit_insn (gen_andsi3 (operands[3], operands[4], operands[5]));
+
   DONE;
 })
 
@@ -8886,14 +8855,14 @@
 })
 
 (define_insn "*andndi3_doubleword"
-  [(set (match_operand:DI 0 "register_operand" "=&r,r,r,&r")
+  [(set (match_operand:DI 0 "register_operand")
 	(and:DI
-	  (not:DI (match_operand:DI 1 "register_operand" "r,0,r,0"))
-	  (match_operand:DI 2 "nonimmediate_operand" "rm,rm,0,rm")))
+	  (not:DI (match_operand:DI 1 "register_operand"))
+	  (match_operand:DI 2 "nonimmediate_operand")))
    (clobber (reg:CC FLAGS_REG))]
-  "!TARGET_64BIT && TARGET_STV && TARGET_SSE2"
-  "#"
-  [(set_attr "isa" "bmi,bmi,bmi,*")])
+  "!TARGET_64BIT && TARGET_STV && TARGET_SSE2
+   && can_create_pseudo_p ()"
+  "#")
 
 (define_split
   [(set (match_operand:DI 0 "register_operand")
@@ -8902,7 +8871,7 @@
 	  (match_operand:DI 2 "nonimmediate_operand")))
    (clobber (reg:CC FLAGS_REG))]
   "!TARGET_64BIT && TARGET_BMI && TARGET_STV && TARGET_SSE2
-   && reload_completed"
+   && can_create_pseudo_p ()"
   [(parallel [(set (match_dup 0)
 		   (and:SI (not:SI (match_dup 1)) (match_dup 2)))
 	      (clobber (reg:CC FLAGS_REG))])
@@ -8914,20 +8883,25 @@
 (define_split
   [(set (match_operand:DI 0 "register_operand")
 	(and:DI
-	  (not:DI (match_dup 0))
-	  (match_operand:DI 1 "nonimmediate_operand")))
+	  (not:DI (match_operand:DI 1 "register_operand"))
+	  (match_operand:DI 2 "nonimmediate_operand")))
    (clobber (reg:CC FLAGS_REG))]
   "!TARGET_64BIT && !TARGET_BMI && TARGET_STV && TARGET_SSE2
-   && reload_completed"
-  [(set (match_dup 0) (not:SI (match_dup 0)))
+   && can_create_pseudo_p ()"
+  [(set (match_dup 6) (not:SI (match_dup 1)))
    (parallel [(set (match_dup 0)
-		   (and:SI (match_dup 0) (match_dup 1)))
+		   (and:SI (match_dup 6) (match_dup 2)))
 	      (clobber (reg:CC FLAGS_REG))])
-   (set (match_dup 2) (not:SI (match_dup 2)))
-   (parallel [(set (match_dup 2)
-		   (and:SI (match_dup 2) (match_dup 3)))
+   (set (match_dup 7) (not:SI (match_dup 4)))
+   (parallel [(set (match_dup 3)
+		   (and:SI (match_dup 7) (match_dup 5)))
 	      (clobber (reg:CC FLAGS_REG))])]
-  "split_double_mode (DImode, &operands[0], 2, &operands[0], &operands[2]);")
+{
+  operands[6] = gen_reg_rtx (SImode);
+  operands[7] = gen_reg_rtx (SImode);
+
+  split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);
+})
 
 (define_insn "*andn<mode>_1"
   [(set (match_operand:SWI48 0 "register_operand" "=r,r")
@@ -8980,44 +8954,44 @@
   "ix86_expand_binary_operator (<CODE>, <MODE>mode, operands); DONE;")
 
 (define_insn_and_split "*<code>di3_doubleword"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
+  [(set (match_operand:DI 0 "nonimmediate_operand")
 	(any_or:DI
-	 (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
-	 (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm")))
+	 (match_operand:DI 1 "nonimmediate_operand")
+	 (match_operand:DI 2 "x86_64_szext_general_operand")))
    (clobber (reg:CC FLAGS_REG))]
   "!TARGET_64BIT && TARGET_STV && TARGET_SSE2
-   && ix86_binary_operator_ok (<CODE>, DImode, operands)"
+   && ix86_binary_operator_ok (<CODE>, DImode, operands)
+   && can_create_pseudo_p ()"
   "#"
-  "&& reload_completed"
+  "&& 1"
   [(const_int 0)]
 {
   split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);
-  if (operands[2] == constm1_rtx)
+
+  if (operands[2] == const0_rtx)
+    emit_move_insn (operands[0], operands[1]);
+  else if (operands[2] == constm1_rtx)
     {
       if (<CODE> == IOR)
-	{
-	  operands[1] = constm1_rtx;
-	  ix86_expand_move (SImode, &operands[0]);
-	}
+        emit_move_insn (operands[0], constm1_rtx);
       else
-	ix86_expand_unary_operator (NOT, SImode, &operands[0]);
+        ix86_expand_unary_operator (NOT, SImode, &operands[0]);
     }
-  else if (operands[2] != const0_rtx)
+  else
     ix86_expand_binary_operator (<CODE>, SImode, &operands[0]);
-  else if (operands[5] == const0_rtx)
-    emit_note (NOTE_INSN_DELETED);
-  if (operands[5] == constm1_rtx)
+
+  if (operands[5] == const0_rtx)
+    emit_move_insn (operands[3], operands[4]);
+  else if (operands[5] == constm1_rtx)
     {
       if (<CODE> == IOR)
-	{
-	  operands[4] = constm1_rtx;
-	  ix86_expand_move (SImode, &operands[3]);
-	}
+        emit_move_insn (operands[3], constm1_rtx);
       else
-	ix86_expand_unary_operator (NOT, SImode, &operands[3]);
+        ix86_expand_unary_operator (NOT, SImode, &operands[3]);
     }
-  else if (operands[5] != const0_rtx)
+  else
     ix86_expand_binary_operator (<CODE>, SImode, &operands[3]);
+
   DONE;
 })
 
@@ -9673,12 +9647,13 @@
   "ix86_expand_unary_operator (NOT, <MODE>mode, operands); DONE;")
 
 (define_insn_and_split "*one_cmpldi2_doubleword"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
-	(not:DI (match_operand:DI 1 "nonimmediate_operand" "0")))]
+  [(set (match_operand:DI 0 "nonimmediate_operand")
+	(not:DI (match_operand:DI 1 "nonimmediate_operand")))]
   "!TARGET_64BIT && TARGET_STV && TARGET_SSE2
-   && ix86_unary_operator_ok (NOT, DImode, operands)"
+   && ix86_unary_operator_ok (NOT, DImode, operands)
+   && can_create_pseudo_p ()"
   "#"
-  "&& reload_completed"
+  "&& 1"
   [(set (match_dup 0)
 	(not:SI (match_dup 1)))
    (set (match_dup 2)


More information about the Gcc-patches mailing list