[llvm] 4a4987b - [SystemZ] Optimize vector zero/sign extensions
Ulrich Weigand via llvm-commits
llvm-commits at lists.llvm.org
Sat Mar 15 10:29:23 PDT 2025
Author: Ulrich Weigand
Date: 2025-03-15T18:28:44+01:00
New Revision: 4a4987be360ac7e4caad65bed54de4ed1d9342ed
URL: https://github.com/llvm/llvm-project/commit/4a4987be360ac7e4caad65bed54de4ed1d9342ed
DIFF: https://github.com/llvm/llvm-project/commit/4a4987be360ac7e4caad65bed54de4ed1d9342ed.diff
LOG: [SystemZ] Optimize vector zero/sign extensions
Generate more efficient code for zero or sign extensions where
the source is a subvector generated via SHUFFLE_VECTOR.
Specifically, recognize patterns corresponding to (series of)
VECTOR UNPACK instructions, or the VECTOR SIGN EXTEND TO
DOUBLEWORD instruction.
As a special case, also handle zero or sign extensions of a
vector element to i128.
Fixes: https://github.com/llvm/llvm-project/issues/129576
Fixes: https://github.com/llvm/llvm-project/issues/129899
Added:
llvm/test/CodeGen/SystemZ/vec-unpack-01.ll
llvm/test/CodeGen/SystemZ/vec-unpack-02.ll
llvm/test/CodeGen/SystemZ/vec-unpack-03.ll
llvm/test/CodeGen/SystemZ/vec-unpack-04.ll
Modified:
llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
llvm/lib/Target/SystemZ/SystemZInstrVector.td
llvm/test/CodeGen/SystemZ/vec-cmp-cmp-logic-select.ll
llvm/test/CodeGen/SystemZ/vec-cmpsel.ll
llvm/test/CodeGen/SystemZ/vec-move-23.ll
llvm/test/CodeGen/SystemZ/vec-shift-07.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index d16d35a4ffb7b..78706f20d2cae 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -5800,7 +5800,8 @@ static SDValue getGeneralPermuteNode(SelectionDAG &DAG, const SDLoc &DL,
namespace {
// Describes a general N-operand vector shuffle.
struct GeneralShuffle {
- GeneralShuffle(EVT vt) : VT(vt), UnpackFromEltSize(UINT_MAX) {}
+ GeneralShuffle(EVT vt)
+ : VT(vt), UnpackFromEltSize(UINT_MAX), UnpackLow(false) {}
void addUndef();
bool add(SDValue, unsigned);
SDValue getNode(SelectionDAG &, const SDLoc &);
@@ -5821,8 +5822,10 @@ struct GeneralShuffle {
// Holds a value of 1, 2 or 4 if a final unpack has been prepared for.
unsigned UnpackFromEltSize;
+ // True if the final unpack uses the low half.
+ bool UnpackLow;
};
-}
+} // namespace
// Add an extra undefined element to the shuffle.
void GeneralShuffle::addUndef() {
@@ -6027,11 +6030,21 @@ void GeneralShuffle::tryPrepareForUnpack() {
if (MatchUnpack) {
if (Ops.size() == 2) {
// Don't use unpack if a single source operand needs rearrangement.
- for (unsigned i = 0; i < SystemZ::VectorBytes / 2; i++)
- if (SrcBytes[i] != -1 && SrcBytes[i] % 16 != int(i)) {
+ bool CanUseUnpackLow = true, CanUseUnpackHigh = true;
+ for (unsigned i = 0; i < SystemZ::VectorBytes / 2; i++) {
+ if (SrcBytes[i] == -1)
+ continue;
+ if (SrcBytes[i] % 16 != int(i))
+ CanUseUnpackHigh = false;
+ if (SrcBytes[i] % 16 != int(i + SystemZ::VectorBytes / 2))
+ CanUseUnpackLow = false;
+ if (!CanUseUnpackLow && !CanUseUnpackHigh) {
UnpackFromEltSize = UINT_MAX;
return;
}
+ }
+ if (!CanUseUnpackHigh)
+ UnpackLow = true;
}
break;
}
@@ -6046,13 +6059,19 @@ void GeneralShuffle::tryPrepareForUnpack() {
// Apply the unpack in reverse to the Bytes array.
unsigned B = 0;
+ if (UnpackLow) {
+ while (B < SystemZ::VectorBytes / 2)
+ Bytes[B++] = -1;
+ }
for (unsigned Elt = 0; Elt < SystemZ::VectorBytes;) {
Elt += UnpackFromEltSize;
for (unsigned i = 0; i < UnpackFromEltSize; i++, Elt++, B++)
Bytes[B] = Bytes[Elt];
}
- while (B < SystemZ::VectorBytes)
- Bytes[B++] = -1;
+ if (!UnpackLow) {
+ while (B < SystemZ::VectorBytes)
+ Bytes[B++] = -1;
+ }
// Remove the zero vector from Ops
Ops.erase(&Ops[ZeroVecOpNo]);
@@ -6079,7 +6098,9 @@ SDValue GeneralShuffle::insertUnpackIfPrepared(SelectionDAG &DAG,
unsigned OutBits = InBits * 2;
EVT OutVT = MVT::getVectorVT(MVT::getIntegerVT(OutBits),
SystemZ::VectorBits / OutBits);
- return DAG.getNode(SystemZISD::UNPACKL_HIGH, DL, OutVT, PackedOp);
+ return DAG.getNode(UnpackLow ? SystemZISD::UNPACKL_LOW
+ : SystemZISD::UNPACKL_HIGH,
+ DL, OutVT, PackedOp);
}
// Return true if the given BUILD_VECTOR is a scalar-to-vector conversion.
@@ -6486,12 +6507,55 @@ lowerSIGN_EXTEND_VECTOR_INREG(SDValue Op, SelectionDAG &DAG) const {
EVT InVT = PackedOp.getValueType();
unsigned ToBits = OutVT.getScalarSizeInBits();
unsigned FromBits = InVT.getScalarSizeInBits();
+ unsigned StartOffset = 0;
+
+ // If the input is a VECTOR_SHUFFLE, there are a number of important
+ // cases where we can directly implement the sign-extension of the
+ // original input lanes of the shuffle.
+ if (PackedOp.getOpcode() == ISD::VECTOR_SHUFFLE) {
+ ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(PackedOp.getNode());
+ ArrayRef<int> ShuffleMask = SVN->getMask();
+ int OutNumElts = OutVT.getVectorNumElements();
+
+ // Recognize the special case where the sign-extension can be done
+ // by the VSEG instruction. Handled via the default expander.
+ if (ToBits == 64 && OutNumElts == 2) {
+ int NumElem = ToBits / FromBits;
+ if (ShuffleMask[0] == NumElem - 1 && ShuffleMask[1] == 2 * NumElem - 1)
+ return SDValue();
+ }
+
+ // Recognize the special case where we can fold the shuffle by
+ // replacing some of the UNPACK_HIGH with UNPACK_LOW.
+ int StartOffsetCandidate = -1;
+ for (int Elt = 0; Elt < OutNumElts; Elt++) {
+ if (ShuffleMask[Elt] == -1)
+ continue;
+ if (ShuffleMask[Elt] % OutNumElts == Elt) {
+ if (StartOffsetCandidate == -1)
+ StartOffsetCandidate = ShuffleMask[Elt] - Elt;
+ if (StartOffsetCandidate == ShuffleMask[Elt] - Elt)
+ continue;
+ }
+ StartOffsetCandidate = -1;
+ break;
+ }
+ if (StartOffsetCandidate != -1) {
+ StartOffset = StartOffsetCandidate;
+ PackedOp = PackedOp.getOperand(0);
+ }
+ }
+
do {
FromBits *= 2;
- EVT OutVT = MVT::getVectorVT(MVT::getIntegerVT(FromBits),
- SystemZ::VectorBits / FromBits);
- PackedOp =
- DAG.getNode(SystemZISD::UNPACK_HIGH, SDLoc(PackedOp), OutVT, PackedOp);
+ unsigned OutNumElts = SystemZ::VectorBits / FromBits;
+ EVT OutVT = MVT::getVectorVT(MVT::getIntegerVT(FromBits), OutNumElts);
+ unsigned Opcode = SystemZISD::UNPACK_HIGH;
+ if (StartOffset >= OutNumElts) {
+ Opcode = SystemZISD::UNPACK_LOW;
+ StartOffset -= OutNumElts;
+ }
+ PackedOp = DAG.getNode(Opcode, SDLoc(PackedOp), OutVT, PackedOp);
} while (FromBits != ToBits);
return PackedOp;
}
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrVector.td b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
index 3e78b3d175f4b..db957bb7c0294 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrVector.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrVector.td
@@ -1970,6 +1970,22 @@ let Predicates = [FeatureVector] in {
(VLEG (VGBM 0), bdxaddr12only:$addr, 1)>;
}
+// Zero-extensions from VR element to i128 on arch15.
+let Predicates = [FeatureVectorEnhancements3] in {
+ def : Pat<(i128 (zext (i64 (z_vector_extract (v2i64 VR128:$src), 0)))),
+ (VUPLHG VR128:$src)>;
+ def : Pat<(i128 (zext (i64 (z_vector_extract (v2i64 VR128:$src), 1)))),
+ (VUPLLG VR128:$src)>;
+ def : Pat<(i128 (zext (i32 (z_vector_extract (v4i32 VR128:$src), 0)))),
+ (VUPLHG (VUPLHF VR128:$src))>;
+ def : Pat<(i128 (zext (i32 (z_vector_extract (v4i32 VR128:$src), 1)))),
+ (VUPLHG (VUPLLF VR128:$src))>;
+ def : Pat<(i128 (zext (i32 (z_vector_extract (v4i32 VR128:$src), 2)))),
+ (VUPLLG (VUPLHF VR128:$src))>;
+ def : Pat<(i128 (zext (i32 (z_vector_extract (v4i32 VR128:$src), 3)))),
+ (VUPLLG (VUPLLF VR128:$src))>;
+}
+
// In-register i128 sign-extensions on arch15.
let Predicates = [FeatureVectorEnhancements3] in {
def : Pat<(i128 (sext_inreg VR128:$x, i8)), (VUPLG (VSEGB VR128:$x))>;
@@ -2034,6 +2050,22 @@ let Predicates = [FeatureVector] in {
(VSRAB (VLREPG bdxaddr12only:$addr), (VREPIB 64))>;
}
+// Sign-extensions from VR element to i128 on arch15.
+let Predicates = [FeatureVectorEnhancements3] in {
+ def : Pat<(i128 (sext (i64 (z_vector_extract (v2i64 VR128:$src), 0)))),
+ (VUPHG VR128:$src)>;
+ def : Pat<(i128 (sext (i64 (z_vector_extract (v2i64 VR128:$src), 1)))),
+ (VUPLG VR128:$src)>;
+ def : Pat<(i128 (sext (i32 (z_vector_extract (v4i32 VR128:$src), 0)))),
+ (VUPHG (VUPHF VR128:$src))>;
+ def : Pat<(i128 (sext (i32 (z_vector_extract (v4i32 VR128:$src), 1)))),
+ (VUPHG (VUPLF VR128:$src))>;
+ def : Pat<(i128 (sext (i32 (z_vector_extract (v4i32 VR128:$src), 2)))),
+ (VUPLG (VUPHF VR128:$src))>;
+ def : Pat<(i128 (sext (i32 (z_vector_extract (v4i32 VR128:$src), 3)))),
+ (VUPLG (VUPLF VR128:$src))>;
+}
+
// i128 comparison pseudo-instructions.
let Predicates = [FeatureVector], Defs = [CC],
usesCustomInserter = 1, hasNoSchedulingInfo = 1 in {
diff --git a/llvm/test/CodeGen/SystemZ/vec-cmp-cmp-logic-select.ll b/llvm/test/CodeGen/SystemZ/vec-cmp-cmp-logic-select.ll
index 9ed7ca2179733..c13293bd64a16 100644
--- a/llvm/test/CodeGen/SystemZ/vec-cmp-cmp-logic-select.ll
+++ b/llvm/test/CodeGen/SystemZ/vec-cmp-cmp-logic-select.ll
@@ -58,8 +58,7 @@ define <16 x i16> @fun3(<16 x i8> %val1, <16 x i8> %val2, <16 x i16> %val3, <16
; CHECK: # %bb.0:
; CHECK-DAG: vceqb [[REG0:%v[0-9]+]], %v24, %v26
; CHECK-DAG: vuphb [[REG2:%v[0-9]+]], [[REG0]]
-; CHECK-DAG: vmrlg [[REG1:%v[0-9]+]], [[REG0]], [[REG0]]
-; CHECK-DAG: vuphb [[REG1]], [[REG1]]
+; CHECK-DAG: vuplb [[REG1:%v[0-9]+]], [[REG0]]
; CHECK-DAG: vceqh [[REG3:%v[0-9]+]], %v28, %v25
; CHECK-DAG: vceqh [[REG4:%v[0-9]+]], %v30, %v27
; CHECK-DAG: vl [[REG5:%v[0-9]+]], 176(%r15)
@@ -186,10 +185,9 @@ define <8 x i32> @fun10(<8 x i16> %val1, <8 x i16> %val2, <8 x i16> %val3, <8 x
; CHECK-DAG: vceqh [[REG1:%v[0-9]+]], %v28, %v30
; CHECK-NEXT: vx [[REG2:%v[0-9]+]], [[REG0]], [[REG1]]
; CHECK-DAG: vuphh [[REG3:%v[0-9]+]], [[REG2]]
-; CHECK-DAG: vmrlg [[REG4:%v[0-9]+]], [[REG2]], [[REG2]]
-; CHECK-DAG: vuphh [[REG5:%v[0-9]+]], [[REG4]]
+; CHECK-DAG: vuplhw [[REG4:%v[0-9]+]], [[REG2]]
; CHECK-NEXT: vsel %v24, %v25, %v29, [[REG3]]
-; CHECK-NEXT: vsel %v26, %v27, %v31, [[REG5]]
+; CHECK-NEXT: vsel %v26, %v27, %v31, [[REG4]]
; CHECK-NEXT: br %r14
%cmp0 = icmp eq <8 x i16> %val1, %val2
%cmp1 = icmp eq <8 x i16> %val3, %val4
@@ -347,10 +345,9 @@ define <4 x i64> @fun18(<4 x i32> %val1, <4 x i32> %val2, <4 x i16> %val3, <4 x
; CHECK-NEXT: vuphh %v1, %v1
; CHECK-NEXT: vn %v0, %v0, %v1
; CHECK-DAG: vuphf [[REG0:%v[0-9]+]], %v0
-; CHECK-DAG: vmrlg [[REG1:%v[0-9]+]], %v0, %v0
-; CHECK-DAG: vuphf [[REG2:%v[0-9]+]], [[REG1]]
+; CHECK-DAG: vuplf [[REG1:%v[0-9]+]], %v0
; CHECK-NEXT: vsel %v24, %v25, %v29, [[REG0]]
-; CHECK-NEXT: vsel %v26, %v27, %v31, [[REG2]]
+; CHECK-NEXT: vsel %v26, %v27, %v31, [[REG1]]
; CHECK-NEXT: br %r14
%cmp0 = icmp eq <4 x i32> %val1, %val2
%cmp1 = icmp eq <4 x i16> %val3, %val4
@@ -455,14 +452,13 @@ define <4 x i64> @fun24(<4 x i64> %val1, <4 x i64> %val2, <4 x i32> %val3, <4 x
; CHECK-LABEL: fun24:
; CHECK: # %bb.0:
; CHECK-NEXT: vceqf [[REG0:%v[0-9]+]], %v25, %v27
-; CHECK-NEXT: vuphf [[REG1:%v[0-9]+]], [[REG0]]
-; CHECK-NEXT: vmrlg [[REG2:%v[0-9]+]], [[REG0]], [[REG0]]
+; CHECK-DAG: vuphf [[REG1:%v[0-9]+]], [[REG0]]
+; CHECK-DAG: vuplf [[REG2:%v[0-9]+]], [[REG0]]
; CHECK-DAG: vceqg [[REG3:%v[0-9]+]], %v24, %v28
; CHECK-DAG: vceqg [[REG4:%v[0-9]+]], %v26, %v30
-; CHECK-DAG: vuphf [[REG5:%v[0-9]+]], [[REG2]]
; CHECK-DAG: vl [[REG6:%v[0-9]+]], 176(%r15)
; CHECK-DAG: vl [[REG7:%v[0-9]+]], 160(%r15)
-; CHECK-DAG: vx [[REG8:%v[0-9]+]], [[REG4]], [[REG5]]
+; CHECK-DAG: vx [[REG8:%v[0-9]+]], [[REG4]], [[REG2]]
; CHECK-DAG: vx [[REG9:%v[0-9]+]], [[REG3]], [[REG1]]
; CHECK-DAG: vsel %v24, %v29, [[REG7]], [[REG9]]
; CHECK-DAG: vsel %v26, %v31, [[REG6]], [[REG8]]
@@ -631,8 +627,7 @@ define <4 x double> @fun29(<4 x float> %val1, <4 x float> %val2, <4 x float> %va
; CHECK-NEXT: vfchdb %v2, %v3, %v2
; CHECK-NEXT: vpkg %v1, %v2, %v1
; CHECK-NEXT: vx %v0, %v0, %v1
-; CHECK-NEXT: vmrlg %v1, %v0, %v0
-; CHECK-NEXT: vuphf %v1, %v1
+; CHECK-NEXT: vuplf %v1, %v0
; CHECK-NEXT: vuphf %v0, %v0
; CHECK-NEXT: vsel %v24, %v25, %v29, %v0
; CHECK-NEXT: vsel %v26, %v27, %v31, %v1
@@ -643,8 +638,7 @@ define <4 x double> @fun29(<4 x float> %val1, <4 x float> %val2, <4 x float> %va
; CHECK-Z14-NEXT: vfchsb %v0, %v24, %v26
; CHECK-Z14-NEXT: vfchsb %v1, %v28, %v30
; CHECK-Z14-NEXT: vx %v0, %v0, %v1
-; CHECK-Z14-NEXT: vmrlg %v1, %v0, %v0
-; CHECK-Z14-NEXT: vuphf %v1, %v1
+; CHECK-Z14-NEXT: vuplf %v1, %v0
; CHECK-Z14-NEXT: vuphf %v0, %v0
; CHECK-Z14-NEXT: vsel %v24, %v25, %v29, %v0
; CHECK-Z14-NEXT: vsel %v26, %v27, %v31, %v1
@@ -816,11 +810,10 @@ define <4 x double> @fun34(<4 x double> %val1, <4 x double> %val2, <4 x float> %
; CHECK-DAG: vfchdb [[REG11:%v[0-9]+]], [[REG9]], [[REG7]]
; CHECK-DAG: vpkg [[REG12:%v[0-9]+]], [[REG11]], [[REG4]]
; CHECK-DAG: vuphf [[REG13:%v[0-9]+]], [[REG12]]
-; CHECK-DAG: vmrlg [[REG14:%v[0-9]+]], [[REG12]], [[REG12]]
-; CHECK-NEXT: vfchdb [[REG15:%v[0-9]+]], %v24, %v28
-; CHECK-NEXT: vfchdb [[REG16:%v[0-9]+]], %v26, %v30
-; CHECK-NEXT: vuphf [[REG17:%v[0-9]+]], [[REG14]]
-; CHECK-NEXT: vn [[REG18:%v[0-9]+]], [[REG16]], [[REG17]]
+; CHECK-DAG: vuplf [[REG14:%v[0-9]+]], [[REG12]]
+; CHECK-DAG: vfchdb [[REG15:%v[0-9]+]], %v24, %v28
+; CHECK-DAG: vfchdb [[REG16:%v[0-9]+]], %v26, %v30
+; CHECK-NEXT: vn [[REG18:%v[0-9]+]], [[REG16]], [[REG14]]
; CHECK-NEXT: vn [[REG19:%v[0-9]+]], [[REG15]], [[REG13]]
; CHECK-NEXT: vsel %v24, %v29, [[REG10]], [[REG19]]
; CHECK-NEXT: vsel %v26, %v31, [[REG8]], [[REG18]]
@@ -829,13 +822,12 @@ define <4 x double> @fun34(<4 x double> %val1, <4 x double> %val2, <4 x float> %
; CHECK-Z14-LABEL: fun34:
; CHECK-Z14: # %bb.0:
; CHECK-Z14-NEXT: vfchsb %v4, %v25, %v27
+; CHECK-Z14-NEXT: vl %v0, 176(%r15)
+; CHECK-Z14-NEXT: vl %v1, 160(%r15)
+; CHECK-Z14-NEXT: vfchdb %v2, %v24, %v28
+; CHECK-Z14-NEXT: vfchdb %v3, %v26, %v30
; CHECK-Z14-NEXT: vuphf %v5, %v4
-; CHECK-Z14-NEXT: vmrlg %v4, %v4, %v4
-; CHECK-Z14-DAG: vfchdb %v2, %v24, %v28
-; CHECK-Z14-DAG: vfchdb %v3, %v26, %v30
-; CHECK-Z14-DAG: vuphf %v4, %v4
-; CHECK-Z14-DAG: vl %v0, 176(%r15)
-; CHECK-Z14-DAG: vl %v1, 160(%r15)
+; CHECK-Z14-NEXT: vuplf %v4, %v4
; CHECK-Z14-NEXT: vn %v3, %v3, %v4
; CHECK-Z14-NEXT: vn %v2, %v2, %v5
; CHECK-Z14-NEXT: vsel %v24, %v29, %v1, %v2
diff --git a/llvm/test/CodeGen/SystemZ/vec-cmpsel.ll b/llvm/test/CodeGen/SystemZ/vec-cmpsel.ll
index 200c25179d38d..f93ecc348af65 100644
--- a/llvm/test/CodeGen/SystemZ/vec-cmpsel.ll
+++ b/llvm/test/CodeGen/SystemZ/vec-cmpsel.ll
@@ -43,8 +43,7 @@ define <16 x i16> @fun3(<16 x i8> %val1, <16 x i8> %val2, <16 x i16> %val3, <16
; CHECK: # %bb.0:
; CHECK-NEXT: vceqb %v0, %v24, %v26
; CHECK-DAG: vuphb [[REG0:%v[0-9]+]], %v0
-; CHECK-DAG: vmrlg [[REG1:%v[0-9]+]], %v0, %v0
-; CHECK-DAG: vuphb [[REG1]], [[REG1]]
+; CHECK-DAG: vuplb [[REG1:%v[0-9]+]], %v0
; CHECK-NEXT: vsel %v24, %v28, %v25, [[REG0]]
; CHECK-NEXT: vsel %v26, %v30, %v27, [[REG1]]
; CHECK-NEXT: br %r14
@@ -129,8 +128,7 @@ define <8 x i32> @fun10(<8 x i16> %val1, <8 x i16> %val2, <8 x i32> %val3, <8 x
; CHECK: # %bb.0:
; CHECK-NEXT: vceqh %v0, %v24, %v26
; CHECK-DAG: vuphh [[REG0:%v[0-9]+]], %v0
-; CHECK-DAG: vmrlg [[REG1:%v[0-9]+]], %v0, %v0
-; CHECK-DAG: vuphh [[REG1]], [[REG1]]
+; CHECK-DAG: vuplhw [[REG1:%v[0-9]+]], %v0
; CHECK-NEXT: vsel %v24, %v28, %v25, [[REG0]]
; CHECK-NEXT: vsel %v26, %v30, %v27, [[REG1]]
; CHECK-NEXT: br %r14
@@ -228,8 +226,7 @@ define <4 x i64> @fun18(<4 x i32> %val1, <4 x i32> %val2, <4 x i64> %val3, <4 x
; CHECK: # %bb.0:
; CHECK-NEXT: vceqf %v0, %v24, %v26
; CHECK-DAG: vuphf [[REG0:%v[0-9]+]], %v0
-; CHECK-DAG: vmrlg [[REG1:%v[0-9]+]], %v0, %v0
-; CHECK-DAG: vuphf [[REG1]], [[REG1]]
+; CHECK-DAG: vuplf [[REG1]], %v0
; CHECK-NEXT: vsel %v24, %v28, %v25, [[REG0]]
; CHECK-NEXT: vsel %v26, %v30, %v27, [[REG1]]
; CHECK-NEXT: br %r14
@@ -428,8 +425,7 @@ define <4 x double> @fun29(<4 x float> %val1, <4 x float> %val2, <4 x double> %v
; CHECK-NEXT: vldeb %v2, %v2
; CHECK-NEXT: vfchdb %v1, %v2, %v1
; CHECK-NEXT: vpkg [[REG0:%v[0-9]+]], %v1, %v0
-; CHECK-DAG: vmrlg [[REG1:%v[0-9]+]], [[REG0]], [[REG0]]
-; CHECK-DAG: vuphf [[REG1]], [[REG1]]
+; CHECK-DAG: vuplf [[REG1:%v[0-9]+]], [[REG0]]
; CHECK-DAG: vuphf [[REG2:%v[0-9]+]], [[REG0]]
; CHECK-NEXT: vsel %v24, %v28, %v25, [[REG2]]
; CHECK-NEXT: vsel %v26, %v30, %v27, [[REG1]]
@@ -439,8 +435,7 @@ define <4 x double> @fun29(<4 x float> %val1, <4 x float> %val2, <4 x double> %v
; CHECK-Z14: # %bb.0:
; CHECK-Z14-NEXT: vfchsb %v0, %v24, %v26
; CHECK-Z14-DAG: vuphf [[REG0:%v[0-9]+]], %v0
-; CHECK-Z14-DAG: vmrlg [[REG1:%v[0-9]+]], %v0, %v0
-; CHECK-Z14-DAG: vuphf [[REG1]], [[REG1]]
+; CHECK-Z14-DAG: vuplf [[REG1:%v[0-9]+]], %v0
; CHECK-Z14-NEXT: vsel %v24, %v28, %v25, [[REG0]]
; CHECK-Z14-NEXT: vsel %v26, %v30, %v27, [[REG1]]
; CHECK-Z14-NEXT: br %r14
diff --git a/llvm/test/CodeGen/SystemZ/vec-move-23.ll b/llvm/test/CodeGen/SystemZ/vec-move-23.ll
index 11ad6f3605804..1976e6710ecf9 100644
--- a/llvm/test/CodeGen/SystemZ/vec-move-23.ll
+++ b/llvm/test/CodeGen/SystemZ/vec-move-23.ll
@@ -143,19 +143,17 @@ define void @fun8(<2 x i64> %dwords, ptr %ptr) {
; Test that this results in vectorized conversions.
define void @fun9(ptr %Src, ptr %ptr) {
; CHECK-LABEL: fun9
-; Z15: larl %r1, .LCPI9_0
-; Z15-NEXT: vl %v0, 16(%r2), 4
+; Z15: vl %v0, 16(%r2), 4
; Z15-NEXT: vl %v1, 0(%r2), 4
-; Z15-NEXT: vl %v2, 0(%r1), 3
-; Z15-NEXT: vperm %v2, %v2, %v1, %v2
-; Z15-NEXT: vuplhh %v1, %v1
+; Z15-NEXT: vuplhh %v2, %v1
+; Z15-NEXT: vupllh %v1, %v1
; Z15-NEXT: vuplhh %v0, %v0
; Z15-NEXT: vcelfb %v2, %v2, 0, 0
; Z15-NEXT: vcelfb %v1, %v1, 0, 0
; Z15-NEXT: vcelfb %v0, %v0, 0, 0
; Z15-NEXT: vsteg %v0, 32(%r3), 0
-; Z15-NEXT: vst %v2, 16(%r3), 4
-; Z15-NEXT: vst %v1, 0(%r3), 4
+; Z15-NEXT: vst %v1, 16(%r3), 4
+; Z15-NEXT: vst %v2, 0(%r3), 4
; Z15-NEXT: br %r14
%Val = load <10 x i16>, ptr %Src
diff --git a/llvm/test/CodeGen/SystemZ/vec-shift-07.ll b/llvm/test/CodeGen/SystemZ/vec-shift-07.ll
index f229c5e25a462..afb04045957a8 100644
--- a/llvm/test/CodeGen/SystemZ/vec-shift-07.ll
+++ b/llvm/test/CodeGen/SystemZ/vec-shift-07.ll
@@ -180,3 +180,33 @@ define <2 x i64> @f16(<16 x i32> %val) {
%vec1 = insertelement <2 x i64> %vec0, i64 %ext1, i32 1
ret <2 x i64> %vec1
}
+
+; Test a shufflevector-based v2i8->v2i64 extension.
+define <2 x i64> @f17(<16 x i8> %val) {
+; CHECK-LABEL: f17:
+; CHECK: vsegb %v24, %v24
+; CHECK: br %r14
+ %shuf = shufflevector <16 x i8> %val, <16 x i8> poison, <2 x i32> <i32 7, i32 15>
+ %ret = sext <2 x i8> %shuf to <2 x i64>
+ ret <2 x i64> %ret
+}
+
+; Test a shufflevector-based v2i16->v2i64 extension.
+define <2 x i64> @f18(<8 x i16> %val) {
+; CHECK-LABEL: f18:
+; CHECK: vsegh %v24, %v24
+; CHECK: br %r14
+ %shuf = shufflevector <8 x i16> %val, <8 x i16> poison, <2 x i32> <i32 3, i32 7>
+ %ret = sext <2 x i16> %shuf to <2 x i64>
+ ret <2 x i64> %ret
+}
+
+; Test a shufflevector-based v2i32->v2i64 extension.
+define <2 x i64> @f19(<4 x i32> %val) {
+; CHECK-LABEL: f19:
+; CHECK: vsegf %v24, %v24
+; CHECK: br %r14
+ %shuf = shufflevector <4 x i32> %val, <4 x i32> poison, <2 x i32> <i32 1, i32 3>
+ %ret = sext <2 x i32> %shuf to <2 x i64>
+ ret <2 x i64> %ret
+}
diff --git a/llvm/test/CodeGen/SystemZ/vec-unpack-01.ll b/llvm/test/CodeGen/SystemZ/vec-unpack-01.ll
new file mode 100644
index 0000000000000..9355341d6ca89
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/vec-unpack-01.ll
@@ -0,0 +1,270 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+
+; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s
+
+define <8 x i16> @f1(<16 x i8> %a) {
+; CHECK-LABEL: f1:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphb %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %1 = sext <8 x i8> %0 to <8 x i16>
+ ret <8 x i16> %1
+}
+
+define <8 x i16> @f2(<16 x i8> %a) {
+; CHECK-LABEL: f2:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplb %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ %1 = sext <8 x i8> %0 to <8 x i16>
+ ret <8 x i16> %1
+}
+
+define <4 x i32> @f3(<8 x i16> %a) {
+; CHECK-LABEL: f3:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphh %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %1 = sext <4 x i16> %0 to <4 x i32>
+ ret <4 x i32> %1
+}
+
+define <4 x i32> @f4(<8 x i16> %a) {
+; CHECK-LABEL: f4:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplhw %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %1 = sext <4 x i16> %0 to <4 x i32>
+ ret <4 x i32> %1
+}
+
+define <4 x i32> @f5(<16 x i8> %a) {
+; CHECK-LABEL: f5:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphb %v0, %v24
+; CHECK-NEXT: vuphh %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %1 = sext <4 x i8> %0 to <4 x i32>
+ ret <4 x i32> %1
+}
+
+define <4 x i32> @f6(<16 x i8> %a) {
+; CHECK-LABEL: f6:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphb %v0, %v24
+; CHECK-NEXT: vuplhw %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %1 = sext <4 x i8> %0 to <4 x i32>
+ ret <4 x i32> %1
+}
+
+define <4 x i32> @f7(<16 x i8> %a) {
+; CHECK-LABEL: f7:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplb %v0, %v24
+; CHECK-NEXT: vuphh %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <4 x i32> <i32 8, i32 9, i32 10, i32 11>
+ %1 = sext <4 x i8> %0 to <4 x i32>
+ ret <4 x i32> %1
+}
+
+define <4 x i32> @f8(<16 x i8> %a) {
+; CHECK-LABEL: f8:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplb %v0, %v24
+; CHECK-NEXT: vuplhw %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
+ %1 = sext <4 x i8> %0 to <4 x i32>
+ ret <4 x i32> %1
+}
+
+define <2 x i64> @f9(<4 x i32> %a) {
+; CHECK-LABEL: f9:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphf %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
+ %1 = sext <2 x i32> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f10(<4 x i32> %a) {
+; CHECK-LABEL: f10:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplf %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 2, i32 3>
+ %1 = sext <2 x i32> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f11(<8 x i16> %a) {
+; CHECK-LABEL: f11:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphh %v0, %v24
+; CHECK-NEXT: vuphf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <8 x i16> %a, <8 x i16> poison, <2 x i32> <i32 0, i32 1>
+ %1 = sext <2 x i16> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f12(<8 x i16> %a) {
+; CHECK-LABEL: f12:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphh %v0, %v24
+; CHECK-NEXT: vuplf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <8 x i16> %a, <8 x i16> poison, <2 x i32> <i32 2, i32 3>
+ %1 = sext <2 x i16> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f13(<8 x i16> %a) {
+; CHECK-LABEL: f13:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplhw %v0, %v24
+; CHECK-NEXT: vuphf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <8 x i16> %a, <8 x i16> poison, <2 x i32> <i32 4, i32 5>
+ %1 = sext <2 x i16> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f14(<8 x i16> %a) {
+; CHECK-LABEL: f14:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplhw %v0, %v24
+; CHECK-NEXT: vuplf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <8 x i16> %a, <8 x i16> poison, <2 x i32> <i32 6, i32 7>
+ %1 = sext <2 x i16> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f15(<16 x i8> %a) {
+; CHECK-LABEL: f15:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphb %v0, %v24
+; CHECK-NEXT: vuphh %v0, %v0
+; CHECK-NEXT: vuphf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <2 x i32> <i32 0, i32 1>
+ %1 = sext <2 x i8> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f16(<16 x i8> %a) {
+; CHECK-LABEL: f16:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphb %v0, %v24
+; CHECK-NEXT: vuphh %v0, %v0
+; CHECK-NEXT: vuplf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <2 x i32> <i32 2, i32 3>
+ %1 = sext <2 x i8> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f17(<16 x i8> %a) {
+; CHECK-LABEL: f17:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphb %v0, %v24
+; CHECK-NEXT: vuplhw %v0, %v0
+; CHECK-NEXT: vuphf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <2 x i32> <i32 4, i32 5>
+ %1 = sext <2 x i8> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f18(<16 x i8> %a) {
+; CHECK-LABEL: f18:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphb %v0, %v24
+; CHECK-NEXT: vuplhw %v0, %v0
+; CHECK-NEXT: vuplf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <2 x i32> <i32 6, i32 7>
+ %1 = sext <2 x i8> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f19(<16 x i8> %a) {
+; CHECK-LABEL: f19:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplb %v0, %v24
+; CHECK-NEXT: vuphh %v0, %v0
+; CHECK-NEXT: vuphf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <2 x i32> <i32 8, i32 9>
+ %1 = sext <2 x i8> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f20(<16 x i8> %a) {
+; CHECK-LABEL: f20:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplb %v0, %v24
+; CHECK-NEXT: vuphh %v0, %v0
+; CHECK-NEXT: vuplf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <2 x i32> <i32 10, i32 11>
+ %1 = sext <2 x i8> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f21(<16 x i8> %a) {
+; CHECK-LABEL: f21:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplb %v0, %v24
+; CHECK-NEXT: vuplhw %v0, %v0
+; CHECK-NEXT: vuphf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <2 x i32> <i32 12, i32 13>
+ %1 = sext <2 x i8> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f22(<16 x i8> %a) {
+; CHECK-LABEL: f22:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplb %v0, %v24
+; CHECK-NEXT: vuplhw %v0, %v0
+; CHECK-NEXT: vuplf %v24, %v0
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <2 x i32> <i32 14, i32 15>
+ %1 = sext <2 x i8> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
diff --git a/llvm/test/CodeGen/SystemZ/vec-unpack-02.ll b/llvm/test/CodeGen/SystemZ/vec-unpack-02.ll
new file mode 100644
index 0000000000000..301fea1b19586
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/vec-unpack-02.ll
@@ -0,0 +1,79 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+
+; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=arch15 | FileCheck %s
+
+define i128 @f1(<2 x i64> %a) {
+; CHECK-LABEL: f1:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphg %v0, %v24
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <2 x i64> %a, i32 0
+ %1 = sext i64 %0 to i128
+ ret i128 %1
+}
+
+define i128 @f2(<2 x i64> %a) {
+; CHECK-LABEL: f2:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplg %v0, %v24
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <2 x i64> %a, i32 1
+ %1 = sext i64 %0 to i128
+ ret i128 %1
+}
+
+define i128 @f3(<4 x i32> %a) {
+; CHECK-LABEL: f3:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphf %v0, %v24
+; CHECK-NEXT: vuphg %v0, %v0
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <4 x i32> %a, i32 0
+ %1 = sext i32 %0 to i128
+ ret i128 %1
+}
+
+define i128 @f4(<4 x i32> %a) {
+; CHECK-LABEL: f4:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplf %v0, %v24
+; CHECK-NEXT: vuphg %v0, %v0
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <4 x i32> %a, i32 1
+ %1 = sext i32 %0 to i128
+ ret i128 %1
+}
+
+define i128 @f5(<4 x i32> %a) {
+; CHECK-LABEL: f5:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuphf %v0, %v24
+; CHECK-NEXT: vuplg %v0, %v0
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <4 x i32> %a, i32 2
+ %1 = sext i32 %0 to i128
+ ret i128 %1
+}
+
+define i128 @f6(<4 x i32> %a) {
+; CHECK-LABEL: f6:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplf %v0, %v24
+; CHECK-NEXT: vuplg %v0, %v0
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <4 x i32> %a, i32 3
+ %1 = sext i32 %0 to i128
+ ret i128 %1
+}
diff --git a/llvm/test/CodeGen/SystemZ/vec-unpack-03.ll b/llvm/test/CodeGen/SystemZ/vec-unpack-03.ll
new file mode 100644
index 0000000000000..de4c51e695bf4
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/vec-unpack-03.ll
@@ -0,0 +1,70 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+
+; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s
+
+define <8 x i16> @f1(<16 x i8> %a) {
+; CHECK-LABEL: f1:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplhb %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %1 = zext <8 x i8> %0 to <8 x i16>
+ ret <8 x i16> %1
+}
+
+define <8 x i16> @f2(<16 x i8> %a) {
+; CHECK-LABEL: f2:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vupllb %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <16 x i8> %a, <16 x i8> poison, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ %1 = zext <8 x i8> %0 to <8 x i16>
+ ret <8 x i16> %1
+}
+
+define <4 x i32> @f3(<8 x i16> %a) {
+; CHECK-LABEL: f3:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplhh %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %1 = zext <4 x i16> %0 to <4 x i32>
+ ret <4 x i32> %1
+}
+
+define <4 x i32> @f4(<8 x i16> %a) {
+; CHECK-LABEL: f4:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vupllh %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
+ %1 = zext <4 x i16> %0 to <4 x i32>
+ ret <4 x i32> %1
+}
+
+define <2 x i64> @f5(<4 x i32> %a) {
+; CHECK-LABEL: f5:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplhf %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
+ %1 = zext <2 x i32> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
+define <2 x i64> @f6(<4 x i32> %a) {
+; CHECK-LABEL: f6:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vupllf %v24, %v24
+; CHECK-NEXT: br %r14
+start:
+ %0 = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 2, i32 3>
+ %1 = zext <2 x i32> %0 to <2 x i64>
+ ret <2 x i64> %1
+}
+
diff --git a/llvm/test/CodeGen/SystemZ/vec-unpack-04.ll b/llvm/test/CodeGen/SystemZ/vec-unpack-04.ll
new file mode 100644
index 0000000000000..2cf8d1325e16a
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/vec-unpack-04.ll
@@ -0,0 +1,79 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+
+; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=arch15 | FileCheck %s
+
+define i128 @f1(<2 x i64> %a) {
+; CHECK-LABEL: f1:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplhg %v0, %v24
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <2 x i64> %a, i32 0
+ %1 = zext i64 %0 to i128
+ ret i128 %1
+}
+
+define i128 @f2(<2 x i64> %a) {
+; CHECK-LABEL: f2:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vupllg %v0, %v24
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <2 x i64> %a, i32 1
+ %1 = zext i64 %0 to i128
+ ret i128 %1
+}
+
+define i128 @f3(<4 x i32> %a) {
+; CHECK-LABEL: f3:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplhf %v0, %v24
+; CHECK-NEXT: vuplhg %v0, %v0
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <4 x i32> %a, i32 0
+ %1 = zext i32 %0 to i128
+ ret i128 %1
+}
+
+define i128 @f4(<4 x i32> %a) {
+; CHECK-LABEL: f4:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vupllf %v0, %v24
+; CHECK-NEXT: vuplhg %v0, %v0
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <4 x i32> %a, i32 1
+ %1 = zext i32 %0 to i128
+ ret i128 %1
+}
+
+define i128 @f5(<4 x i32> %a) {
+; CHECK-LABEL: f5:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vuplhf %v0, %v24
+; CHECK-NEXT: vupllg %v0, %v0
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <4 x i32> %a, i32 2
+ %1 = zext i32 %0 to i128
+ ret i128 %1
+}
+
+define i128 @f6(<4 x i32> %a) {
+; CHECK-LABEL: f6:
+; CHECK: # %bb.0: # %start
+; CHECK-NEXT: vupllf %v0, %v24
+; CHECK-NEXT: vupllg %v0, %v0
+; CHECK-NEXT: vst %v0, 0(%r2), 3
+; CHECK-NEXT: br %r14
+start:
+ %0 = extractelement <4 x i32> %a, i32 3
+ %1 = zext i32 %0 to i128
+ ret i128 %1
+}
More information about the llvm-commits
mailing list