[llvm-branch-commits] [llvm] SystemZ: Make v2i64 legal on subtargets without vector support (PR #234296)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Oct 22 22:12:32 PDT 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/234296

>From 1948dcfb11731c9b8f7b97f627478a038f3e0e25 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sun, 11 Oct 2026 20:15:36 +0200
Subject: [PATCH] SystemZ: Make v2i64 legal on subtargets without vector
 support

Without the vector feature, the GR128 even/odd register pairs were
modeled with MVT::Untyped, since no 128-bit type was legal. Use v2i64
instead, which is what the pairs functionally are.

v2i64 values can be built from and split into their halves with
subregister operations. Everything else is expanded. Loads and stores
are split into i64 halves, so they don't tie up a register
pair. Bitcasts to and from f128 use the FPR pair halves.

This takes care to avoid changing the calling convention. Vectors that
would be broken down into v2i64 are still passed as individual i64
elements. Inline assembly operands still use untyped, which is listed
first in the GR128 type list, so i128 operands are not bitcast to
v2i64.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply at anthropic.com>
---
 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp |   8 ++
 .../Target/SystemZ/SystemZISelDAGToDAG.cpp    |   2 +
 .../Target/SystemZ/SystemZISelLowering.cpp    | 113 ++++++++++++------
 llvm/lib/Target/SystemZ/SystemZISelLowering.h |   6 +-
 llvm/lib/Target/SystemZ/SystemZInstrFP.td     |  12 ++
 llvm/lib/Target/SystemZ/SystemZInstrInfo.td   |  28 ++++-
 llvm/lib/Target/SystemZ/SystemZOperators.td   |  12 +-
 .../lib/Target/SystemZ/SystemZRegisterInfo.td |   8 +-
 llvm/test/CodeGen/SystemZ/bitcast.ll          |   2 +-
 llvm/test/CodeGen/SystemZ/mixed-ptr-sizes.ll  |   6 +-
 llvm/test/CodeGen/SystemZ/vec-abi-01.ll       |   8 +-
 .../CodeGen/SystemZ/vec-i64-abi-novector.ll   |  12 +-
 .../CodeGen/SystemZ/vec-v2i64-novector.ll     |  36 +++---
 13 files changed, 168 insertions(+), 85 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 84bfc6aa43dc48..f481d548b9cb20 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -540,6 +540,10 @@ void SelectionDAGLegalize::LegalizeStoreOps(SDNode *Node) {
       ReplaceNode(SDValue(Node, 0), Result);
       break;
     }
+    case TargetLowering::Expand:
+      assert(VT.isVector() && "Cannot expand a scalar store");
+      ReplaceNode(SDValue(Node, 0), TLI.scalarizeVectorStore(ST, DAG));
+      break;
     }
     return;
   }
@@ -719,6 +723,10 @@ void SelectionDAGLegalize::LegalizeLoadOps(SDNode *Node) {
       RChain = Res.getValue(1);
       break;
     }
+    case TargetLowering::Expand:
+      assert(VT.isVector() && "Cannot expand a scalar load");
+      std::tie(RVal, RChain) = TLI.scalarizeVectorLoad(LD, DAG);
+      break;
     }
     if (RChain.getNode() != Node) {
       assert(RVal.getNode() != Node && "Load must be completely replaced");
diff --git a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
index 86fa6985a53ce6..ba18c3f049a080 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
@@ -1798,6 +1798,8 @@ void SystemZDAGToDAGISel::Select(SDNode *Node) {
   }
 
   case ISD::BUILD_VECTOR: {
+    if (!Subtarget->hasVector())
+      break;
     auto *BVN = cast<BuildVectorSDNode>(Node);
     SystemZVectorConstantInfo VCI(BVN);
     if (VCI.isVectorConstantLegal(*Subtarget)) {
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index a508c705b02904..dd0368bc2569a8 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -132,6 +132,10 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
       addRegisterClass(MVT::i128, &SystemZ::VR128BitRegClass);
   }
 
+  // Without vector support, model GR128 register pairs as v2i64.
+  if (!Subtarget.hasVector())
+    addRegisterClass(MVT::v2i64, &SystemZ::GR128BitRegClass);
+
   // Compute derived properties from the register classes
   computeRegisterProperties(Subtarget.getRegisterInfo());
 
@@ -428,7 +432,7 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
       setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Expand);
     }
 
-    if (isTypeLegal(VT)) {
+    if (Subtarget.hasVector() && isTypeLegal(VT)) {
       // These operations are legal for anything that can be stored in a
       // vector register, even if there is no native support for the format
       // as such.  In particular, we can do these for v4f32 even though there
@@ -446,9 +450,19 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
     }
   }
 
+  if (!Subtarget.hasVector()) {
+    // A v2i64 GR128 pair can only be built from or split into its halves.
+    // Loads and stores are expanded to avoid tying up a register pair.
+    setOperationAction({ISD::BUILD_VECTOR, ISD::SCALAR_TO_VECTOR, ISD::BITCAST,
+                        ISD::UNDEF, ISD::POISON},
+                       MVT::v2i64, Legal);
+    setOperationAction({ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT},
+                       MVT::v2i64, Custom);
+  }
+
   // Handle integer vector types.
   for (MVT VT : MVT::integer_fixedlen_vector_valuetypes()) {
-    if (isTypeLegal(VT)) {
+    if (Subtarget.hasVector() && isTypeLegal(VT)) {
       // These operations have direct equivalents.
       setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Legal);
       setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Legal);
@@ -853,8 +867,10 @@ SystemZTargetLowering::getPreferredVectorAction(MVT VT) const {
   //     type (v2i64).
 
   // Expand (narrow) f16 vectors during type legalization to avoid
-  // operations for all elements as with expansion after widening.
-  if (VT.getScalarType() == MVT::f16)
+  // operations for all elements as with expansion after widening. Without
+  // vector support, v2i64 is only legal as a GR128 pair, so do not widen or
+  // promote to it.
+  if (!Subtarget.hasVector() || VT.getScalarType() == MVT::f16)
     return VT.getVectorElementCount().isScalar() ? TypeScalarizeVector
                                                  : TypeSplitVector;
   if (VT.getScalarSizeInBits() % 8 == 0)
@@ -871,8 +887,16 @@ unsigned SystemZTargetLowering::getVectorTypeBreakdownForCallingConv(
     return NumIntermediates =
                divideCeil(VT.getVectorNumElements(), SystemZ::VectorBytes / 2);
   }
-  return TargetLowering::getVectorTypeBreakdownForCallingConv(
+  unsigned NumRegs = TargetLowering::getVectorTypeBreakdownForCallingConv(
       Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
+  // Without vector support, v2i64 is a GR128 pair, which is never used to pass
+  // values. Pass the elements individually.
+  if (RegisterVT == MVT::v2i64 && !Subtarget.hasVector()) {
+    IntermediateVT = RegisterVT = MVT::i64;
+    NumIntermediates *= 2;
+    NumRegs *= 2;
+  }
+  return NumRegs;
 }
 
 MVT SystemZTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
@@ -886,7 +910,11 @@ MVT SystemZTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
   // Pass fp16 vectors in VR(s).
   if (Subtarget.hasVector() && VT.isVectorOf(MVT::f16))
     return MVT::v8f16;
-  return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
+  MVT RegisterVT =
+      TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
+  if (RegisterVT == MVT::v2i64 && !Subtarget.hasVector())
+    return MVT::i64;
+  return RegisterVT;
 }
 
 unsigned SystemZTargetLowering::getNumRegistersForCallingConv(
@@ -894,7 +922,13 @@ unsigned SystemZTargetLowering::getNumRegistersForCallingConv(
   // Pass fp16 vectors in VR(s).
   if (Subtarget.hasVector() && VT.isVectorOf(MVT::f16))
     return divideCeil(VT.getVectorNumElements(), SystemZ::VectorBytes / 2);
-  return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
+  unsigned NumRegs =
+      TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);
+  MVT RegisterVT =
+      TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
+  if (RegisterVT == MVT::v2i64 && !Subtarget.hasVector())
+    return NumRegs * 2;
+  return NumRegs;
 }
 
 EVT SystemZTargetLowering::getSetCCResultType(const DataLayout &DL,
@@ -1291,6 +1325,18 @@ SystemZTargetLowering::emitEHSjLjLongJmp(MachineInstr &MI,
   return MBB;
 }
 
+bool SystemZTargetLowering::canMergeStoresTo(unsigned AS, EVT MemVT,
+                                             const MachineFunction &MF) const {
+  // Without vector support, a v2i64 store would just be split again.
+  return MemVT != MVT::v2i64 || Subtarget.hasVector();
+}
+
+bool SystemZTargetLowering::aggressivelyPreferBuildVectorSources(
+    EVT VecVT) const {
+  // Without vector support, a v2i64 is just a pair of GPRs.
+  return !Subtarget.hasVector();
+}
+
 /// Returns true if stack probing through inline assembly is requested.
 bool SystemZTargetLowering::hasInlineStackProbe(const MachineFunction &MF) const {
   // If the function specifically requests inline stack probes, emit them.
@@ -1988,10 +2034,7 @@ static SDValue lowerI128ToGR128(SelectionDAG &DAG, SDValue In) {
     std::tie(Lo, Hi) = DAG.SplitScalar(In, DL, MVT::i64, MVT::i64);
   }
 
-  // FIXME: If v2i64 were a legal type, we could use it instead of
-  // Untyped here.  This might enable improved folding.
-  SDNode *Pair = DAG.getMachineNode(SystemZ::PAIR128, DL,
-                                    MVT::Untyped, Hi, Lo);
+  SDNode *Pair = DAG.getMachineNode(SystemZ::PAIR128, DL, MVT::v2i64, Hi, Lo);
   return SDValue(Pair, 0);
 }
 
@@ -3751,7 +3794,7 @@ static void lowerMUL_LOHI32(SelectionDAG &DAG, const SDLoc &DL, unsigned Extend,
 static void lowerGR128Binary(SelectionDAG &DAG, const SDLoc &DL, EVT VT,
                              unsigned Opcode, SDValue Op0, SDValue Op1,
                              SDValue &Even, SDValue &Odd) {
-  SDValue Result = DAG.getNode(Opcode, DL, MVT::Untyped, Op0, Op1);
+  SDValue Result = DAG.getNode(Opcode, DL, MVT::v2i64, Op0, Op1);
   bool Is32Bit = is32Bit(VT);
   Even = DAG.getTargetExtractSubreg(SystemZ::even128(Is32Bit), DL, VT, Result);
   Odd = DAG.getTargetExtractSubreg(SystemZ::odd128(Is32Bit), DL, VT, Result);
@@ -6741,6 +6784,11 @@ static SDValue convertFromF16(SDValue Op, SDLoc DL, SelectionDAG &DAG) {
   return Shft;
 }
 
+static bool isInBoundsConstantVectorIndex(EVT VecVT, SDValue Idx) {
+  auto *CIdx = dyn_cast<ConstantSDNode>(Idx);
+  return CIdx && CIdx->getZExtValue() < VecVT.getVectorNumElements();
+}
+
 SDValue SystemZTargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,
                                                       SelectionDAG &DAG) const {
   // Handle insertions of floating-point values.
@@ -6750,18 +6798,17 @@ SDValue SystemZTargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,
   SDValue Op2 = Op.getOperand(2);
   EVT VT = Op.getValueType();
 
+  // A constant index selects a GR128 subregister.
+  if (!Subtarget.hasVector())
+    return isInBoundsConstantVectorIndex(VT, Op2) ? Op : SDValue();
+
   // Insertions into constant indices of a v2f64 can be done using VPDI.
   // However, if the inserted value is a bitcast or a constant then it's
   // better to use GPRs, as below.
-  if (VT == MVT::v2f64 &&
-      Op1.getOpcode() != ISD::BITCAST &&
+  if (VT == MVT::v2f64 && Op1.getOpcode() != ISD::BITCAST &&
       Op1.getOpcode() != ISD::ConstantFP &&
-      Op2.getOpcode() == ISD::Constant) {
-    uint64_t Index = Op2->getAsZExtVal();
-    unsigned Mask = VT.getVectorNumElements() - 1;
-    if (Index <= Mask)
-      return Op;
-  }
+      isInBoundsConstantVectorIndex(VT, Op2))
+    return Op;
 
   // Otherwise bitcast to the equivalent integer form and insert via a GPR.
   MVT IntVT = MVT::getIntegerVT(VT.getScalarSizeInBits());
@@ -6787,12 +6834,11 @@ SystemZTargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op,
   EVT VecVT = Op0.getValueType();
 
   // Extractions of constant indices can be done directly.
-  if (auto *CIndexN = dyn_cast<ConstantSDNode>(Op1)) {
-    uint64_t Index = CIndexN->getZExtValue();
-    unsigned Mask = VecVT.getVectorNumElements() - 1;
-    if (Index <= Mask)
-      return Op;
-  }
+  if (isInBoundsConstantVectorIndex(VecVT, Op1))
+    return Op;
+
+  if (!Subtarget.hasVector())
+    return SDValue();
 
   // Otherwise bitcast to the equivalent integer form and extract via a GPR.
   MVT IntVT = MVT::getIntegerVT(VT.getSizeInBits());
@@ -7454,7 +7500,7 @@ SystemZTargetLowering::LowerOperationWrapper(SDNode *N,
   switch (N->getOpcode()) {
   case ISD::ATOMIC_LOAD: {
     SDLoc DL(N);
-    SDVTList Tys = DAG.getVTList(MVT::Untyped, MVT::Other);
+    SDVTList Tys = DAG.getVTList(MVT::v2i64, MVT::Other);
     SDValue Ops[] = { N->getOperand(0), N->getOperand(1) };
     MachineMemOperand *MMO = cast<AtomicSDNode>(N)->getMemOperand();
     SDValue Res = DAG.getMemIntrinsicNode(SystemZISD::ATOMIC_LOAD_128,
@@ -7490,7 +7536,7 @@ SystemZTargetLowering::LowerOperationWrapper(SDNode *N,
   }
   case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS: {
     SDLoc DL(N);
-    SDVTList Tys = DAG.getVTList(MVT::Untyped, MVT::i32, MVT::Other);
+    SDVTList Tys = DAG.getVTList(MVT::v2i64, MVT::i32, MVT::Other);
     SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
                       lowerI128ToGR128(DAG, N->getOperand(2)),
                       lowerI128ToGR128(DAG, N->getOperand(3)) };
@@ -9623,7 +9669,7 @@ SystemZTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
     return;
   }
   EVT VT = Op.getValueType();
-  if (Op.getResNo() != 0 || VT == MVT::Untyped)
+  if (Op.getResNo() != 0)
     return;
   assert (Known.getBitWidth() == VT.getScalarSizeInBits() &&
           "KnownBits does not match VT in bitwidth");
@@ -11409,15 +11455,6 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter(
   }
 }
 
-// This is only used by the isel schedulers, and is needed only to prevent
-// compiler from crashing when list-ilp is used.
-const TargetRegisterClass *
-SystemZTargetLowering::getRepRegClassFor(MVT VT) const {
-  if (VT == MVT::Untyped)
-    return &SystemZ::ADDR128BitRegClass;
-  return TargetLowering::getRepRegClassFor(VT);
-}
-
 SDValue SystemZTargetLowering::lowerGET_ROUNDING(SDValue Op,
                                                  SelectionDAG &DAG) const {
   SDLoc dl(Op);
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index a74de78e620e64..59ab1c893d229d 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -99,6 +99,11 @@ class SystemZTargetLowering : public TargetLowering {
   MachineBasicBlock *emitEHSjLjLongJmp(MachineInstr &MI,
                                        MachineBasicBlock *MBB) const;
 
+  bool canMergeStoresTo(unsigned AS, EVT MemVT,
+                        const MachineFunction &MF) const override;
+
+  bool aggressivelyPreferBuildVectorSources(EVT VecVT) const override;
+
   bool hasInlineStackProbe(const MachineFunction &MF) const override;
   AtomicExpansionKind shouldCastAtomicLoadInIR(LoadInst *LI) const override;
   AtomicExpansionKind shouldCastAtomicStoreInIR(StoreInst *SI) const override;
@@ -462,7 +467,6 @@ class SystemZTargetLowering : public TargetLowering {
 
   MachineMemOperand::Flags
   getTargetMMOFlags(const Instruction &I) const override;
-  const TargetRegisterClass *getRepRegClassFor(MVT VT) const override;
 
 private:
   bool enableNarrowIntArgsVerification() const;
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrFP.td b/llvm/lib/Target/SystemZ/SystemZInstrFP.td
index 80f58ed87b4d21..4c98d511096458 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrFP.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrFP.td
@@ -84,6 +84,18 @@ let Predicates = [FeatureNoVectorEnhancements1] in
 def LGDR : UnaryRRE<"lgdr", 0xB3CD, bitconvert, GR64, FP64>;
 def LDGR : UnaryRRE<"ldgr", 0xB3C1, bitconvert, FP64, GR64>;
 
+// Moves between GR128 and FP128 register pairs.
+let Predicates = [FeatureNoVector] in {
+  def : Pat<(f128 (bitconvert (v2i64 GR128:$src))),
+            (REG_SEQUENCE FP128Bit,
+              (LDGR (EXTRACT_SUBREG GR128:$src, subreg_h64)), subreg_h64,
+              (LDGR (EXTRACT_SUBREG GR128:$src, subreg_l64)), subreg_l64)>;
+  def : Pat<(v2i64 (bitconvert (f128 FP128:$src))),
+            (REG_SEQUENCE GR128Bit,
+              (LGDR (EXTRACT_SUBREG FP128:$src, subreg_h64)), subreg_h64,
+              (LGDR (EXTRACT_SUBREG FP128:$src, subreg_l64)), subreg_l64)>;
+}
+
 // fcopysign with an FP16 result.
 let isCodeGenOnly = 1 in {
   def CPSDRhh : BinaryRRFb<"cpsdr", 0xB372, fcopysign, FP16, FP16, FP16>;
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
index 36c8adaa4b3a15..02d5a1f21219a1 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -481,8 +481,7 @@ let canFoldAsLoad = 1, SimpleBDXLoad = 1, mayLoad = 1,
   // These instructions are split after register allocation, so we don't
   // want a custom inserter.
   let Has20BitOffset = 1, HasIndex = 1, Is128Bit = 1 in {
-    def L128 : Pseudo<(outs GR128:$dst), (ins bdxaddr20only128:$src),
-                      [(set GR128:$dst, (load bdxaddr20only128:$src))]>;
+    def L128 : Pseudo<(outs GR128:$dst), (ins bdxaddr20only128:$src), []>;
   }
 }
 let Defs = [CC], CCValues = 0xE, CompareZeroCCMask = 0xE in {
@@ -525,8 +524,7 @@ let SimpleBDXStore = 1, mayStore = 1 in {
   // These instructions are split after register allocation, so we don't
   // want a custom inserter.
   let Has20BitOffset = 1, HasIndex = 1, Is128Bit = 1 in {
-    def ST128 : Pseudo<(outs), (ins GR128:$src, bdxaddr20only128:$dst),
-                       [(store GR128:$src, bdxaddr20only128:$dst)]>;
+    def ST128 : Pseudo<(outs), (ins GR128:$src, bdxaddr20only128:$dst), []>;
   }
 }
 
@@ -2757,6 +2755,28 @@ defm : BlockLoadStore<anyextloadi16, i64, MVCImm, NCImm, OCImm, XCImm, 1>;
 defm : BlockLoadStore<anyextloadi32, i64, MVCImm, NCImm, OCImm, XCImm, 3>;
 defm : BlockLoadStore<load, i64, MVCImm, NCImm, OCImm, XCImm, 7>;
 
+//===----------------------------------------------------------------------===//
+// GR128 vectors
+//===----------------------------------------------------------------------===//
+
+let Predicates = [FeatureNoVector] in {
+  def : Pat<(v2i64 (build_vector GR64:$hi, GR64:$lo)),
+            (REG_SEQUENCE GR128Bit, GR64:$hi, subreg_h64, GR64:$lo, subreg_l64)>;
+
+  def : Pat<(i64 (extractelt GR128:$src, (i32 0))),
+            (EXTRACT_SUBREG GR128:$src, subreg_h64)>;
+  def : Pat<(i64 (extractelt GR128:$src, (i32 1))),
+            (EXTRACT_SUBREG GR128:$src, subreg_l64)>;
+
+  def : Pat<(v2i64 (insertelt GR128:$src, GR64:$elt, (i32 0))),
+            (INSERT_SUBREG GR128:$src, GR64:$elt, subreg_h64)>;
+  def : Pat<(v2i64 (insertelt GR128:$src, GR64:$elt, (i32 1))),
+            (INSERT_SUBREG GR128:$src, GR64:$elt, subreg_l64)>;
+
+  def : Pat<(v2i64 (scalar_to_vector GR64:$src)),
+            (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), GR64:$src, subreg_h64)>;
+}
+
 //===----------------------------------------------------------------------===//
 // Mnemonic Aliases
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SystemZ/SystemZOperators.td b/llvm/lib/Target/SystemZ/SystemZOperators.td
index 005b79638218a5..6c02c1973c0879 100644
--- a/llvm/lib/Target/SystemZ/SystemZOperators.td
+++ b/llvm/lib/Target/SystemZ/SystemZOperators.td
@@ -50,7 +50,7 @@ def SDT_ZProbedAlloca       : SDTypeProfile<1, 2,
                                              SDTCisSameAs<0, 2>,
                                              SDTCisPtrTy<0>]>;
 def SDT_ZGR128Binary        : SDTypeProfile<1, 2,
-                                            [SDTCisVT<0, untyped>,
+                                            [SDTCisVT<0, v2i64>,
                                              SDTCisInt<1>,
                                              SDTCisInt<2>]>;
 def SDT_ZBinaryWithFlags    : SDTypeProfile<2, 2,
@@ -96,17 +96,17 @@ def SDT_ZAtomicCmpSwap      : SDTypeProfile<2, 3,
                                              SDTCisSameAs<0, 3>,
                                              SDTCisSameAs<0, 4>]>;
 def SDT_ZAtomicLoad128      : SDTypeProfile<1, 1,
-                                            [SDTCisVT<0, untyped>,
+                                            [SDTCisVT<0, v2i64>,
                                              SDTCisPtrTy<1>]>;
 def SDT_ZAtomicStore128     : SDTypeProfile<0, 2,
-                                            [SDTCisVT<0, untyped>,
+                                            [SDTCisVT<0, v2i64>,
                                              SDTCisPtrTy<1>]>;
 def SDT_ZAtomicCmpSwap128   : SDTypeProfile<2, 3,
-                                            [SDTCisVT<0, untyped>,
+                                            [SDTCisVT<0, v2i64>,
                                              SDTCisVT<1, i32>,
                                              SDTCisPtrTy<2>,
-                                             SDTCisVT<3, untyped>,
-                                             SDTCisVT<4, untyped>]>;
+                                             SDTCisVT<3, v2i64>,
+                                             SDTCisVT<4, v2i64>]>;
 def SDT_ZMemMemLength       : SDTypeProfile<0, 3,
                                             [SDTCisPtrTy<0>,
                                              SDTCisPtrTy<1>,
diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
index 1ef8e81c8f8299..f90769a1153837 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
@@ -128,10 +128,10 @@ defm GRX32 : SystemZRegClass<"GRX32", [i32], 32,
                                R12L,R12H,R13L,R13H,R14L,R14H,R15L,R15H)
                              ]>;
 
-// On machines without SIMD support, i128 is not a legal type, so model the
-// register pairs as untyped instead.
+// Register pairs hold v2i64. Inline assembly operands use untyped, which is
+// listed first so that i128 operands are not bitcast to v2i64.
 // XPLINK64: Allocate all registers in natural order
-defm GR128 : SystemZRegClass<"GR128", [untyped], 128,
+defm GR128 : SystemZRegClass<"GR128", [untyped, v2i64], 128,
                              (add R0Q, R2Q, R4Q, R12Q, R10Q, R8Q, R6Q, R14Q),
                              [(add R0Q, R2Q, R4Q, R6Q, R8Q, R10Q, R12Q, R14Q)]>;
 
@@ -146,7 +146,7 @@ defm ADDR64 : SystemZRegClass<"ADDR64", [i64], 64, (sub GR64Bit, R0D),
 // Not used directly, but needs to exist for ADDR32 and ADDR64 subregs
 // of a GR128.
 // XPLINK64: Allocate all registers in natural order
-defm ADDR128 : SystemZRegClass<"ADDR128", [untyped], 128, (sub GR128Bit, R0Q),
+defm ADDR128 : SystemZRegClass<"ADDR128", [untyped, v2i64], 128, (sub GR128Bit, R0Q),
                                [(add R2Q, R4Q, R6Q, R8Q, R10Q, R12Q, R14Q)]>;
 
 // Any type register. Used for .insn directives when we don't know what the
diff --git a/llvm/test/CodeGen/SystemZ/bitcast.ll b/llvm/test/CodeGen/SystemZ/bitcast.ll
index c639a5fff5b091..90ed710b0fd126 100644
--- a/llvm/test/CodeGen/SystemZ/bitcast.ll
+++ b/llvm/test/CodeGen/SystemZ/bitcast.ll
@@ -8,8 +8,8 @@ define <2 x i64> @bitcast_fp128_to_v2i64(fp128 %arg) {
 ; BASE-NEXT:    ld %f0, 0(%r2)
 ; BASE-NEXT:    ld %f2, 8(%r2)
 ; BASE-NEXT:    axbr %f0, %f0
-; BASE-NEXT:    lgdr %r2, %f0
 ; BASE-NEXT:    lgdr %r3, %f2
+; BASE-NEXT:    lgdr %r2, %f0
 ; BASE-NEXT:    br %r14
 ;
 ; Z13-LABEL: bitcast_fp128_to_v2i64:
diff --git a/llvm/test/CodeGen/SystemZ/mixed-ptr-sizes.ll b/llvm/test/CodeGen/SystemZ/mixed-ptr-sizes.ll
index ad079e2e8689fc..cbd74d2b7ae489 100644
--- a/llvm/test/CodeGen/SystemZ/mixed-ptr-sizes.ll
+++ b/llvm/test/CodeGen/SystemZ/mixed-ptr-sizes.ll
@@ -379,12 +379,12 @@ declare ptr addrspace(1) @domalloc(i64)
 
 define void @f1(ptr %inp, ptr %outp) "target-features"="-vector" {
 ; CHECK-LABEL: f1 DS 0H
-; CHECK:        iilf 0,2147483647
+; CHECK:        lg 0,8(1)
 ; CHECK-NEXT:   iilf 3,2147483647
-; CHECK-NEXT:   n 0,12(1)
 ; CHECK-NEXT:   n 3,4(1)
-; CHECK-NEXT:   st 0,4(2)
+; CHECK-NEXT:   nilh 0,32767
 ; CHECK-NEXT:   st 3,0(2)
+; CHECK-NEXT:   st 0,4(2)
 ; CHECK-NEXT:   b 2(7)
   %in = load <2 x ptr>, ptr %inp, align 8
   %out = addrspacecast <2 x ptr> %in to <2 x ptr addrspace(1)>
diff --git a/llvm/test/CodeGen/SystemZ/vec-abi-01.ll b/llvm/test/CodeGen/SystemZ/vec-abi-01.ll
index 6ce8288aa84995..db99b33168f662 100644
--- a/llvm/test/CodeGen/SystemZ/vec-abi-01.ll
+++ b/llvm/test/CodeGen/SystemZ/vec-abi-01.ll
@@ -259,11 +259,11 @@ entry:
 define void @takeAndStore_long_16(ptr noundef readonly captures(none) dead_on_return %0) {
 ; CHECK-LABEL: takeAndStore_long_16:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    lg %r0, 8(%r2)
+; CHECK-NEXT:    lg %r0, 0(%r2)
 ; CHECK-NEXT:    lgrl %r1, global_long_16 at GOT
-; CHECK-NEXT:    lg %r2, 0(%r2)
-; CHECK-NEXT:    stg %r0, 8(%r1)
-; CHECK-NEXT:    stg %r2, 0(%r1)
+; CHECK-NEXT:    lg %r2, 8(%r2)
+; CHECK-NEXT:    stg %r0, 0(%r1)
+; CHECK-NEXT:    stg %r2, 8(%r1)
 ; CHECK-NEXT:    br %r14
 entry:
   %x = load <2 x i64>, ptr %0, align 16
diff --git a/llvm/test/CodeGen/SystemZ/vec-i64-abi-novector.ll b/llvm/test/CodeGen/SystemZ/vec-i64-abi-novector.ll
index 2bb8cf0e9a91ca..bfd65d23722ee2 100644
--- a/llvm/test/CodeGen/SystemZ/vec-i64-abi-novector.ll
+++ b/llvm/test/CodeGen/SystemZ/vec-i64-abi-novector.ll
@@ -15,12 +15,12 @@ define void @v1i64_arg(<1 x i64> %arg, ptr %out) nounwind {
 define void @v3i64_arg(<3 x i64> %arg, ptr %out) nounwind {
 ; LINUX-LABEL: v3i64_arg:
 ; LINUX:       # %bb.0:
-; LINUX-NEXT:    lg %r0, 0(%r2)
-; LINUX-NEXT:    lg %r1, 8(%r2)
-; LINUX-NEXT:    lg %r2, 16(%r2)
-; LINUX-NEXT:    stg %r2, 16(%r3)
-; LINUX-NEXT:    stg %r1, 8(%r3)
-; LINUX-NEXT:    stg %r0, 0(%r3)
+; LINUX-NEXT:    lg %r0, 16(%r2)
+; LINUX-NEXT:    lg %r1, 0(%r2)
+; LINUX-NEXT:    lg %r2, 8(%r2)
+; LINUX-NEXT:    stg %r2, 8(%r3)
+; LINUX-NEXT:    stg %r1, 0(%r3)
+; LINUX-NEXT:    stg %r0, 16(%r3)
 ; LINUX-NEXT:    br %r14
   store <3 x i64> %arg, ptr %out
   ret void
diff --git a/llvm/test/CodeGen/SystemZ/vec-v2i64-novector.ll b/llvm/test/CodeGen/SystemZ/vec-v2i64-novector.ll
index af220304854e1f..91542744c92478 100644
--- a/llvm/test/CodeGen/SystemZ/vec-v2i64-novector.ll
+++ b/llvm/test/CodeGen/SystemZ/vec-v2i64-novector.ll
@@ -421,18 +421,18 @@ define void @v1i64_add(ptr %a, ptr %b, ptr %out) nounwind {
 define void @v4i64_add(ptr %a, ptr %b, ptr %out) nounwind {
 ; CHECK-LABEL: v4i64_add:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    lg %r0, 24(%r2)
-; CHECK-NEXT:    lg %r1, 16(%r2)
-; CHECK-NEXT:    lg %r5, 8(%r2)
-; CHECK-NEXT:    lg %r2, 0(%r2)
-; CHECK-NEXT:    ag %r2, 0(%r3)
-; CHECK-NEXT:    ag %r5, 8(%r3)
-; CHECK-NEXT:    ag %r1, 16(%r3)
-; CHECK-NEXT:    ag %r0, 24(%r3)
-; CHECK-NEXT:    stg %r0, 24(%r4)
-; CHECK-NEXT:    stg %r1, 16(%r4)
-; CHECK-NEXT:    stg %r5, 8(%r4)
-; CHECK-NEXT:    stg %r2, 0(%r4)
+; CHECK-NEXT:    lg %r0, 0(%r2)
+; CHECK-NEXT:    lg %r1, 8(%r2)
+; CHECK-NEXT:    lg %r5, 16(%r2)
+; CHECK-NEXT:    lg %r2, 24(%r2)
+; CHECK-NEXT:    ag %r2, 24(%r3)
+; CHECK-NEXT:    ag %r5, 16(%r3)
+; CHECK-NEXT:    ag %r1, 8(%r3)
+; CHECK-NEXT:    ag %r0, 0(%r3)
+; CHECK-NEXT:    stg %r0, 0(%r4)
+; CHECK-NEXT:    stg %r1, 8(%r4)
+; CHECK-NEXT:    stg %r5, 16(%r4)
+; CHECK-NEXT:    stg %r2, 24(%r4)
 ; CHECK-NEXT:    br %r14
   %va = load <4 x i64>, ptr %a
   %vb = load <4 x i64>, ptr %b
@@ -447,15 +447,15 @@ define void @phi(ptr %a, ptr %b, i1 %c, ptr %out) nounwind {
 ; CHECK-NEXT:    tmll %r4, 1
 ; CHECK-NEXT:    je .LBB28_2
 ; CHECK-NEXT:  # %bb.1: # %then
-; CHECK-NEXT:    lg %r0, 8(%r3)
-; CHECK-NEXT:    lg %r1, 0(%r3)
+; CHECK-NEXT:    lg %r1, 8(%r3)
+; CHECK-NEXT:    lg %r0, 0(%r3)
 ; CHECK-NEXT:    j .LBB28_3
 ; CHECK-NEXT:  .LBB28_2:
-; CHECK-NEXT:    lg %r0, 8(%r2)
-; CHECK-NEXT:    lg %r1, 0(%r2)
+; CHECK-NEXT:    lg %r1, 8(%r2)
+; CHECK-NEXT:    lg %r0, 0(%r2)
 ; CHECK-NEXT:  .LBB28_3: # %end
-; CHECK-NEXT:    stg %r1, 0(%r5)
-; CHECK-NEXT:    stg %r0, 8(%r5)
+; CHECK-NEXT:    stg %r1, 8(%r5)
+; CHECK-NEXT:    stg %r0, 0(%r5)
 ; CHECK-NEXT:    br %r14
 entry:
   %va = load <2 x i64>, ptr %a



More information about the llvm-branch-commits mailing list