i386: Use SWI48DWI mode iterator for abs and maxmin [PR97873]
authorUros Bizjak <ubizjak@gmail.com>
Sun, 22 Nov 2020 21:26:48 +0000 (22:26 +0100)
committerUros Bizjak <ubizjak@gmail.com>
Sun, 22 Nov 2020 21:27:35 +0000 (22:27 +0100)
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.

gcc/config/i386/i386.md
gcc/testsuite/gcc.target/i386/pr97873-2.c [new file with mode: 0644]

index 2b2ba2f3a2070cd002b30e1bbf17df41228a6d4f..2beaee5418dafe860e9e88602f78639673b9feb5 100644 (file)
 
 (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"
 {
     }
 })
 
-(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"
    (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"
 
 (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
   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 (file)
index 0000000..22519ab
--- /dev/null
@@ -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" } } */