[llvm] S390x saturated truncation (PR #155377)

Folkert de Vries via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 26 01:58:03 PDT 2025


https://github.com/folkertdev created https://github.com/llvm/llvm-project/pull/155377

fixes https://github.com/llvm/llvm-project/issues/153655 (or well, it should if this gets to a mergeable state)

This does not yet work, but should make it easier to talk about.

After legalizing `smin` and `smax` (I'm still matching the older patterns below, not sure if that is really needed any more?), the DAG is 

```
Optimized legalized selection DAG: %bb.0 'i32_signed:bb2'
SelectionDAG has 17 nodes:
  t0: ch,glue = EntryToken
  t17: v4i32 = BUILD_VECTOR Constant:i32<-32768>, Constant:i32<-32768>, Constant:i32<-32768>, Constant:i32<-32768>
  t16: v4i32 = BUILD_VECTOR Constant:i32<32767>, Constant:i32<32767>, Constant:i32<32767>, Constant:i32<32767>
          t2: v4i32,ch = CopyFromReg t0, Register:v4i32 %0
        t18: v4i32 = smax t2, t17
      t20: v4i32 = smin t18, t16
          t4: v4i32,ch = CopyFromReg t0, Register:v4i32 %1
        t19: v4i32 = smax t4, t17
      t21: v4i32 = smin t19, t16
    t50: v8i16 = SystemZISD::PACK t20, t21
  t14: ch,glue = CopyToReg t0, Register:v8i16 $v24, t50
  t15: ch = SystemZISD::RET_GLUE t14, Register:v8i16 $v24, t14:1
```

However, the pattern still does not match. I'm now suspicious of those `BUILD_VECTOR`s, because the rest just looks like it should work.

I'm also aware that the order of the patterns matters, which is why the `VPKSF` pattern is now before `VPKF`.

cc @uweigand 

>From e75dd4e38de856a3a8d43a13508afa132115184e Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Tue, 26 Aug 2025 10:45:02 +0200
Subject: [PATCH 1/3] s390x: legalize smin/smax/umin/umax

---
 .../Target/SystemZ/SystemZISelLowering.cpp    |  2 +
 llvm/lib/Target/SystemZ/SystemZInstrVector.td | 42 +++++++++++++++----
 2 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index c73dc3021eb42..df9eb9405f3fc 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -492,6 +492,8 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
       // Map SETCCs onto one of VCE, VCH or VCHL, swapping the operands
       // and inverting the result as necessary.
       setOperationAction(ISD::SETCC, VT, Custom);
+
+      setOperationAction({ISD::SMIN, ISD::UMIN, ISD::SMAX, ISD::UMAX}, VT, Legal);
     }
   }
 
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrVector.td b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
index 10de8b05cf45f..80f5f0b4ce445 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrVector.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
@@ -1269,11 +1269,24 @@ multiclass IntegerMinMaxVectorOps<ValueType type, SDPatternOperator cmph,
   }
 }
 
+multiclass SignedIntegerMinMaxVectorOps<ValueType type, SDPatternOperator cmph,
+                                  Instruction min, Instruction max> {
+  defm : IntegerMinMaxVectorOps<type, cmph, min, max>;
+
+  let Predicates = [FeatureVector] in {
+    def : Pat<(type (smax VR128:$x, VR128:$y)),
+              (max VR128:$x, VR128:$y)>;
+
+    def : Pat<(type (smin VR128:$x, VR128:$y)),
+              (min VR128:$x, VR128:$y)>;
+  }
+}
+
 // Signed min/max.
-defm : IntegerMinMaxVectorOps<v16i8, z_vicmph, VMNB, VMXB>;
-defm : IntegerMinMaxVectorOps<v8i16, z_vicmph, VMNH, VMXH>;
-defm : IntegerMinMaxVectorOps<v4i32, z_vicmph, VMNF, VMXF>;
-defm : IntegerMinMaxVectorOps<v2i64, z_vicmph, VMNG, VMXG>;
+defm : SignedIntegerMinMaxVectorOps<v16i8, z_vicmph, VMNB, VMXB>;
+defm : SignedIntegerMinMaxVectorOps<v8i16, z_vicmph, VMNH, VMXH>;
+defm : SignedIntegerMinMaxVectorOps<v4i32, z_vicmph, VMNF, VMXF>;
+defm : SignedIntegerMinMaxVectorOps<v2i64, z_vicmph, VMNG, VMXG>;
 
 let Predicates = [FeatureVectorEnhancements3] in {
   def : Pat<(i128 (or (and VR128:$x, (z_vicmph VR128:$x, VR128:$y)),
@@ -1284,11 +1297,24 @@ let Predicates = [FeatureVectorEnhancements3] in {
             (VMNQ VR128:$x, VR128:$y)>;
 }
 
+multiclass UnsignedIntegerMinMaxVectorOps<ValueType type, SDPatternOperator cmph,
+                                  Instruction min, Instruction max> {
+  defm : IntegerMinMaxVectorOps<type, cmph, min, max>;
+
+  let Predicates = [FeatureVector] in {
+    def : Pat<(type (umax VR128:$x, VR128:$y)),
+              (max VR128:$x, VR128:$y)>;
+
+    def : Pat<(type (umin VR128:$x, VR128:$y)),
+              (min VR128:$x, VR128:$y)>;
+  }
+}
+
 // Unsigned min/max.
-defm : IntegerMinMaxVectorOps<v16i8, z_vicmphl, VMNLB, VMXLB>;
-defm : IntegerMinMaxVectorOps<v8i16, z_vicmphl, VMNLH, VMXLH>;
-defm : IntegerMinMaxVectorOps<v4i32, z_vicmphl, VMNLF, VMXLF>;
-defm : IntegerMinMaxVectorOps<v2i64, z_vicmphl, VMNLG, VMXLG>;
+defm : UnsignedIntegerMinMaxVectorOps<v16i8, z_vicmphl, VMNLB, VMXLB>;
+defm : UnsignedIntegerMinMaxVectorOps<v8i16, z_vicmphl, VMNLH, VMXLH>;
+defm : UnsignedIntegerMinMaxVectorOps<v4i32, z_vicmphl, VMNLF, VMXLF>;
+defm : UnsignedIntegerMinMaxVectorOps<v2i64, z_vicmphl, VMNLG, VMXLG>;
 
 let Predicates = [FeatureVectorEnhancements3] in {
   def : Pat<(i128 (or (and VR128:$x, (z_vicmphl VR128:$x, VR128:$y)),

>From 57e380de75603826736ba3483547fc10e169534f Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Sat, 23 Aug 2025 19:47:19 +0200
Subject: [PATCH 2/3] pull apart the packs cc and non-cc version

---
 llvm/lib/Target/SystemZ/SystemZInstrVector.td | 26 ++++++++++---------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/SystemZ/SystemZInstrVector.td b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
index 80f5f0b4ce445..10584c2e235aa 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrVector.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
@@ -400,20 +400,16 @@ let Predicates = [FeatureVector] in {
 //===----------------------------------------------------------------------===//
 
 let Predicates = [FeatureVector] in {
-  // Pack
-  def VPK  : BinaryVRRcGeneric<"vpk", 0xE794>;
-  def VPKH : BinaryVRRc<"vpkh", 0xE794, z_pack, v128b, v128h, 1>;
-  def VPKF : BinaryVRRc<"vpkf", 0xE794, z_pack, v128h, v128f, 2>;
-  def VPKG : BinaryVRRc<"vpkg", 0xE794, z_pack, v128f, v128g, 3>;
-
   // Pack saturate.
   def  VPKS  : BinaryVRRbSPairGeneric<"vpks", 0xE797>;
-  defm VPKSH : BinaryVRRbSPair<"vpksh", 0xE797, int_s390_vpksh, z_packs_cc,
-                               v128b, v128h, 1>;
-  defm VPKSF : BinaryVRRbSPair<"vpksf", 0xE797, int_s390_vpksf, z_packs_cc,
-                               v128h, v128f, 2>;
-  defm VPKSG : BinaryVRRbSPair<"vpksg", 0xE797, int_s390_vpksg, z_packs_cc,
-                               v128f, v128g, 3>;
+
+  def VPKSH : BinaryVRRb<"vpksh", 0xE797, int_s390_vpksh, v128b, v128h, 1, !and (0, 14)>;
+  def VPKSF : BinaryVRRb<"vpksf", 0xE797, int_s390_vpksf, v128h, v128f, 2, !and (0, 14)>;
+  def VPKSG : BinaryVRRb<"vpksg", 0xE797, int_s390_vpksg, v128f, v128g, 3, !and (0, 14)>;
+
+  def VPKSHS : BinaryVRRb<"vpkshs", 0xE797, z_packs_cc, v128b, v128h, 1, !add (!and (0, 14), 1)>;
+  def VPKSFS : BinaryVRRb<"vpksfs", 0xE797, z_packs_cc, v128h, v128f, 2, !add (!and (0, 14), 1)>;
+  def VPKSGS : BinaryVRRb<"vpksgs", 0xE797, z_packs_cc, v128f, v128g, 3, !add (!and (0, 14), 1)>;
 
   // Pack saturate logical.
   def  VPKLS  : BinaryVRRbSPairGeneric<"vpkls", 0xE795>;
@@ -424,6 +420,12 @@ let Predicates = [FeatureVector] in {
   defm VPKLSG : BinaryVRRbSPair<"vpklsg", 0xE795, int_s390_vpklsg, z_packls_cc,
                                 v128f, v128g, 3>;
 
+  // Pack
+  def VPK  : BinaryVRRcGeneric<"vpk", 0xE794>;
+  def VPKH : BinaryVRRc<"vpkh", 0xE794, z_pack, v128b, v128h, 1>;
+  def VPKF : BinaryVRRc<"vpkf", 0xE794, z_pack, v128h, v128f, 2>;
+  def VPKG : BinaryVRRc<"vpkg", 0xE794, z_pack, v128f, v128g, 3>;
+
   // Sign-extend to doubleword.
   def VSEG  : UnaryVRRaGeneric<"vseg", 0xE75F>;
   def VSEGB : UnaryVRRa<"vsegb", 0xE75F, z_vsei8,  v128g, v128g, 0>;

>From 779ff44e84bb89953c30657453d9a3ccb4cc5bc6 Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Tue, 26 Aug 2025 10:50:47 +0200
Subject: [PATCH 3/3] s390x: map signed saturating truncation to a packs

---
 llvm/lib/Target/SystemZ/SystemZInstrVector.td | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/llvm/lib/Target/SystemZ/SystemZInstrVector.td b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
index 10584c2e235aa..6d05912c9112f 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrVector.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
@@ -399,6 +399,9 @@ let Predicates = [FeatureVector] in {
 // Widening and narrowing
 //===----------------------------------------------------------------------===//
 
+def replicate_i32_min : PatFrag<(ops), (v4i32 (build_vector (i32 -32768), (i32 -32768), (i32 -32768), (i32 -32768)))>;
+def replicate_i32_max : PatFrag<(ops), (v4i32 (build_vector (i32 32768), (i32 32768), (i32 32768), (i32 32768)))>;
+
 let Predicates = [FeatureVector] in {
   // Pack saturate.
   def  VPKS  : BinaryVRRbSPairGeneric<"vpks", 0xE797>;
@@ -407,6 +410,14 @@ let Predicates = [FeatureVector] in {
   def VPKSF : BinaryVRRb<"vpksf", 0xE797, int_s390_vpksf, v128h, v128f, 2, !and (0, 14)>;
   def VPKSG : BinaryVRRb<"vpksg", 0xE797, int_s390_vpksg, v128f, v128g, 3, !and (0, 14)>;
 
+  def : Pat<
+    (v8i16 (z_pack
+      (smin (smax (v4i32 VR128:$a), replicate_i32_min), replicate_i32_max),
+      (smin (smax (v4i32 VR128:$b), replicate_i32_min), replicate_i32_max)
+    )),
+    (VPKSF VR128:$a, VR128:$b)
+  >;
+
   def VPKSHS : BinaryVRRb<"vpkshs", 0xE797, z_packs_cc, v128b, v128h, 1, !add (!and (0, 14), 1)>;
   def VPKSFS : BinaryVRRb<"vpksfs", 0xE797, z_packs_cc, v128h, v128f, 2, !add (!and (0, 14), 1)>;
   def VPKSGS : BinaryVRRb<"vpksgs", 0xE797, z_packs_cc, v128f, v128g, 3, !add (!and (0, 14), 1)>;



More information about the llvm-commits mailing list