diff mbox series

i386: Use SWI48DWI mode iterator for abs and maxmin [PR97873]

Message ID CAFULd4Z3UE836OMBxDkn5p9FB50G2=MkpAcVcEUNUhqnpMx9jg@mail.gmail.com
State New
Headers show
Series i386: Use SWI48DWI mode iterator for abs and maxmin [PR97873] | expand

Commit Message

Uros Bizjak Nov. 22, 2020, 9:29 p.m. UTC
Generate special double mode sequence also for TImode on 64bit targets.

2020-11-22  Uroš Bizjak  <ubizjak@gmail.com>

    PR target/97873

gcc/
    * config/i386/i386.md (abs<mode>2): Use SWI48DWI mode iterator.
    (*abs<dwi>2_doubleword): Use DWIH mode iterator.

    (<maxmin:code><mode>3): Use SWI48DWI mode iterator.
    (*<maxmin:code><dwi>3_doubleword): Use DWIH mode iterator.

gcc/testsuite/
    * gcc.target/i386/pr97873-2.c: New test.

Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

Pushed to mainline.

Uros.
diff mbox series

Patch

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 2b2ba2f3a20..2beaee5418d 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -10180,9 +10180,9 @@ 
 
 (define_expand "abs<mode>2"
   [(parallel
-    [(set (match_operand:SWI48x 0 "register_operand")
-	  (abs:SWI48x
-	    (match_operand:SWI48x 1 "general_operand")))
+    [(set (match_operand:SWI48DWI 0 "register_operand")
+	  (abs:SWI48DWI
+	    (match_operand:SWI48DWI 1 "general_operand")))
      (clobber (reg:CC FLAGS_REG))])]
   "TARGET_CMOVE"
 {
@@ -10208,37 +10208,12 @@ 
     }
 })
 
-(define_insn_and_split "*abs<mode>2_1"
-  [(set (match_operand:SWI48 0 "register_operand")
-	(abs:SWI48
-	  (match_operand:SWI48 1 "general_operand")))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_CMOVE && ix86_pre_reload_split ()"
-   "#"
-   "&& 1"
-  [(parallel
-     [(set (reg:CCGOC FLAGS_REG)
-	   (compare:CCGOC
-	     (neg:SWI48 (match_dup 1))
-	     (const_int 0)))
-      (set (match_dup 2)
-	   (neg:SWI48 (match_dup 1)))])
-   (set (match_dup 0)
-        (if_then_else:SWI48
-	  (ge (reg:CCGOC FLAGS_REG) (const_int 0))
-	  (match_dup 2)
-	  (match_dup 1)))]
-{
-  operands[1] = force_reg (<MODE>mode, operands[1]);
-  operands[2] = gen_reg_rtx (<MODE>mode);
-})
-
-(define_insn_and_split "*absdi2_doubleword"
-  [(set (match_operand:DI 0 "register_operand")
-	(abs:DI
-	  (match_operand:DI 1 "general_operand")))
+(define_insn_and_split "*abs<dwi>2_doubleword"
+  [(set (match_operand:<DWI> 0 "register_operand")
+	(abs:<DWI>
+	  (match_operand:<DWI> 1 "general_operand")))
    (clobber (reg:CC FLAGS_REG))]
-  "!TARGET_64BIT && TARGET_CMOVE
+  "TARGET_CMOVE
    && ix86_pre_reload_split ()"
    "#"
    "&& 1"
@@ -10255,25 +10230,51 @@ 
    (parallel
      [(set (reg:CCGOC FLAGS_REG)
 	   (compare:CCGOC
-	     (neg:SI (match_dup 5))
+	     (neg:DWIH (match_dup 5))
 	     (const_int 0)))
       (set (match_dup 5)
-	   (neg:SI (match_dup 5)))])
+	   (neg:DWIH (match_dup 5)))])
    (set (match_dup 0)
-        (if_then_else:SI
+        (if_then_else:DWIH
 	  (ge (reg:CCGOC FLAGS_REG) (const_int 0))
 	  (match_dup 2)
 	  (match_dup 1)))
    (set (match_dup 3)
-        (if_then_else:SI
+        (if_then_else:DWIH
 	  (ge (reg:CCGOC FLAGS_REG) (const_int 0))
 	  (match_dup 5)
 	  (match_dup 4)))]
 {
-  operands[1] = force_reg (DImode, operands[1]);
-  operands[2] = gen_reg_rtx (DImode);
+  operands[1] = force_reg (<DWI>mode, operands[1]);
+  operands[2] = gen_reg_rtx (<DWI>mode);
 
-  split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);
+  split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);
+})
+
+(define_insn_and_split "*abs<mode>2_1"
+  [(set (match_operand:SWI48 0 "register_operand")
+	(abs:SWI48
+	  (match_operand:SWI48 1 "general_operand")))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_CMOVE
+   && ix86_pre_reload_split ()"
+   "#"
+   "&& 1"
+  [(parallel
+     [(set (reg:CCGOC FLAGS_REG)
+	   (compare:CCGOC
+	     (neg:SWI48 (match_dup 1))
+	     (const_int 0)))
+      (set (match_dup 2)
+	   (neg:SWI48 (match_dup 1)))])
+   (set (match_dup 0)
+        (if_then_else:SWI48
+	  (ge (reg:CCGOC FLAGS_REG) (const_int 0))
+	  (match_dup 2)
+	  (match_dup 1)))]
+{
+  operands[1] = force_reg (<MODE>mode, operands[1]);
+  operands[2] = gen_reg_rtx (<MODE>mode);
 })
 
 (define_expand "<code>tf2"
@@ -18966,13 +18967,71 @@ 
 
 (define_expand "<code><mode>3"
   [(parallel
-    [(set (match_operand:SWI48x 0 "register_operand")
-	  (maxmin:SWI48x
-	    (match_operand:SWI48x 1 "register_operand")
-	    (match_operand:SWI48x 2 "general_operand")))
+    [(set (match_operand:SWI48DWI 0 "register_operand")
+	  (maxmin:SWI48DWI
+	    (match_operand:SWI48DWI 1 "register_operand")
+	    (match_operand:SWI48DWI 2 "general_operand")))
      (clobber (reg:CC FLAGS_REG))])]
   "TARGET_CMOVE")
 
+(define_insn_and_split "*<code><dwi>3_doubleword"
+  [(set (match_operand:<DWI> 0 "register_operand")
+	(maxmin:<DWI>
+	  (match_operand:<DWI> 1 "register_operand")
+	  (match_operand:<DWI> 2 "general_operand")))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_CMOVE
+   && ix86_pre_reload_split ()"
+  "#"
+  "&& 1"
+  [(set (match_dup 0)
+	(if_then_else:DWIH (match_dup 6)
+	  (match_dup 1)
+	  (match_dup 2)))
+   (set (match_dup 3)
+	(if_then_else:DWIH (match_dup 6)
+	  (match_dup 4)
+	  (match_dup 5)))]
+{
+  operands[2] = force_reg (<DWI>mode, operands[2]);
+
+  split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);
+
+  rtx cmplo[2] = { operands[1], operands[2] };
+  rtx cmphi[2] = { operands[4], operands[5] };
+
+  enum rtx_code code = <maxmin_rel>;
+
+  switch (code)
+    {
+    case LE: case LEU:
+      std::swap (cmplo[0], cmplo[1]);
+      std::swap (cmphi[0], cmphi[1]);
+      code = swap_condition (code);
+      /* FALLTHRU */
+
+    case GE: case GEU:
+      {
+	bool uns = (code == GEU);
+	rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx)
+	  = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz;
+
+	emit_insn (gen_cmp_1 (<MODE>mode, cmplo[0], cmplo[1]));
+
+	rtx tmp = gen_rtx_SCRATCH (<MODE>mode);
+	emit_insn (sbb_insn (<MODE>mode, tmp, cmphi[0], cmphi[1]));
+
+	rtx flags = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
+	operands[6] = gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
+
+	break;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+})
+
 (define_insn_and_split "*<code><mode>3_1"
   [(set (match_operand:SWI48 0 "register_operand")
 	(maxmin:SWI48
@@ -19027,63 +19086,6 @@ 
   operands[3] = gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
 })
 
-(define_insn_and_split "*<code>di3_doubleword"
-  [(set (match_operand:DI 0 "register_operand")
-	(maxmin:DI (match_operand:DI 1 "register_operand")
-		   (match_operand:DI 2 "general_operand")))
-   (clobber (reg:CC FLAGS_REG))]
-  "!TARGET_64BIT && TARGET_CMOVE
-   && ix86_pre_reload_split ()"
-  "#"
-  "&& 1"
-  [(set (match_dup 0)
-	(if_then_else:SI (match_dup 6)
-	  (match_dup 1)
-	  (match_dup 2)))
-   (set (match_dup 3)
-	(if_then_else:SI (match_dup 6)
-	  (match_dup 4)
-	  (match_dup 5)))]
-{
-  operands[2] = force_reg (DImode, operands[2]);
-
-  split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);
-
-  rtx cmplo[2] = { operands[1], operands[2] };
-  rtx cmphi[2] = { operands[4], operands[5] };
-
-  enum rtx_code code = <maxmin_rel>;
-
-  switch (code)
-    {
-    case LE: case LEU:
-      std::swap (cmplo[0], cmplo[1]);
-      std::swap (cmphi[0], cmphi[1]);
-      code = swap_condition (code);
-      /* FALLTHRU */
-
-    case GE: case GEU:
-      {
-	bool uns = (code == GEU);
-	rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx)
-	  = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz;
-
-	emit_insn (gen_cmp_1 (SImode, cmplo[0], cmplo[1]));
-
-	rtx tmp = gen_rtx_SCRATCH (SImode);
-	emit_insn (sbb_insn (SImode, tmp, cmphi[0], cmphi[1]));
-
-	rtx flags = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
-	operands[6] = gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
-
-	break;
-      }
-
-    default:
-      gcc_unreachable ();
-    }
-})
-
 ;; Avoid clearing a register between a flags setting comparison and its use,
 ;; i.e. prefer "xorl %eax,%eax; test/cmp" over "test/cmp; movl $0, %eax".
 (define_peephole2
diff --git a/gcc/testsuite/gcc.target/i386/pr97873-2.c b/gcc/testsuite/gcc.target/i386/pr97873-2.c
new file mode 100644
index 00000000000..22519ab5af6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97873-2.c
@@ -0,0 +1,23 @@ 
+/* PR target/97873 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-sse3 -mtune=generic" } */
+
+#ifdef __SIZEOF_INT128__
+typedef __int128_t T;
+#else
+typedef long long T;
+#endif
+
+T test_abs (T x)
+{
+  return (x < 0) ? -x : x;
+}
+
+/* { dg-final { scan-assembler "adc" } } */
+
+T test_smin (T x, T y)
+{
+  return (x < y) ? x : y;
+}
+
+/* { dg-final { scan-assembler "sbb" } } */