https://github.com/zibi2 updated 
https://github.com/llvm/llvm-project/pull/223026

>From f8b97cc936cc8e9ba56a32809d8abece43d2f074 Mon Sep 17 00:00:00 2001
From: Zibi Sarbinowski <[email protected]>
Date: Fri, 11 Sep 2026 15:33:39 -0400
Subject: [PATCH 1/2] [SystemZ] Add i128 support for z/OS XPLINK64 ABI

Add support for passing and returning 128-bit integers (i128) in the
z/OS XPLINK64 calling convention using vector registers.

- Gate i128 availability on z/OS behind the vector facility (arch11/z13)
  via hasInt128Type() override in the SystemZ target
- Add CC_XPLINK_Int128 custom handler that maps i128 to v16i8 for
  register allocation in VR24-VR31
- Add CC_XPLINK_Int128 to RetCC_SystemZ_XPLINK64 and CC_SystemZ_XPLINK64
- Update convertLocVTToValVT/convertValVTToLocVT to handle i128<->v16i8
  bitcast in addition to the existing i64->v2i64 short vector path
- Guard the i128>64-bit return stack spill path behind isTargetLinux()
  so z/OS can return i128 in a vector register
- Add isTargetLinux() predicate to SystemZSubtarget
- Add driver check: -mvx with hard-float ABI requires at least arch11;
  emit err_drv_incompatible_arch diagnostic for older -march values
- Pass Triple through to getSystemZTargetFeatures() so the -mvx arch
  check has access to target information
- Add new diagnostic err_drv_incompatible_arch to DiagnosticDriverKinds.td

Tests:
- clang/test/CodeGen/SystemZ/zos-alignment.c: gate __int128 layout test
  behind -target-cpu z13
- clang/test/CodeGen/zos-abi-int128-error.c: verify i128 is rejected
  without vector facility and -mvx arch check
- clang/test/Sema/zvector.c: add z/OS zvector test variant
- llvm/test/CodeGen/SystemZ/zos-abi-int128-64.ll: end-to-end ABI test
  for i128 argument/return passing in VRs
- llvm/test/CodeGen/SystemZ/call-zos-i128.ll: update to reflect new
  vector register passing convention
- llvm/test/CodeGen/SystemZ/int-div-09.ll: i128 arg to v16i8 conversion
---
 .../clang/Basic/DiagnosticDriverKinds.td      |   3 +
 clang/lib/Basic/Targets/SystemZ.h             |   5 +
 clang/lib/Driver/ToolChains/Arch/SystemZ.cpp  |  33 ++-
 clang/lib/Driver/ToolChains/Arch/SystemZ.h    |   3 +-
 clang/lib/Driver/ToolChains/CommonArgs.cpp    |   2 +-
 clang/test/CodeGen/SystemZ/zos-alignment.c    |  10 +-
 clang/test/CodeGen/zos-abi-int128-error.c     |  16 ++
 clang/test/Sema/zvector.c                     |   4 +
 llvm/lib/Target/SystemZ/SystemZCallingConv.h  |   8 +
 llvm/lib/Target/SystemZ/SystemZCallingConv.td |   7 +
 .../Target/SystemZ/SystemZISelLowering.cpp    |  29 +-
 llvm/lib/Target/SystemZ/SystemZSubtarget.h    |   3 +
 llvm/test/CodeGen/SystemZ/call-zos-i128.ll    |  14 +-
 llvm/test/CodeGen/SystemZ/int-div-09.ll       |  13 +
 .../test/CodeGen/SystemZ/zos-abi-int128-64.ll | 253 ++++++++++++++++++
 15 files changed, 370 insertions(+), 33 deletions(-)
 create mode 100644 clang/test/CodeGen/zos-abi-int128-error.c
 create mode 100644 llvm/test/CodeGen/SystemZ/int-div-09.ll
 create mode 100644 llvm/test/CodeGen/SystemZ/zos-abi-int128-64.ll

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index df6ff0c2cf399..7e872c5da674d 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -203,6 +203,9 @@ def err_drv_unsupported_unwind_for_platform : Error<
   "unsupported unwind library '%0' for platform '%1'">;
 def err_drv_incompatible_unwindlib : Error<
   "--rtlib=libgcc requires --unwindlib=libgcc">;
+def err_drv_incompatible_arch : Error<
+  "'%0' option requires at least '%1', current '%2' is too low">;
+
 def err_drv_incompatible_options : Error<
   "the combination of '%0' and '%1' is incompatible">;
 def err_drv_invalid_cstdlib_name : Error<
diff --git a/clang/lib/Basic/Targets/SystemZ.h 
b/clang/lib/Basic/Targets/SystemZ.h
index cf7d940c1b2e5..6aaf47fb44f5b 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -261,6 +261,11 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public 
TargetInfo {
   uint64_t getPointerAlignV(LangAS AddrSpace) const override {
     return getPointerWidthV(AddrSpace);
   }
+
+  bool hasInt128Type() const override {
+    return (getTriple().isOSzOS() ? hasFeature("vx")
+                                  : TargetInfo::hasInt128Type());
+  }
 };
 } // namespace targets
 } // namespace clang
diff --git a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp 
b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
index 1ef6a725483e8..583d04d8c84f5 100644
--- a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
@@ -53,7 +53,8 @@ std::string systemz::getSystemZTargetCPU(const ArgList &Args,
   return CLANG_SYSTEMZ_DEFAULT_ARCH;
 }
 
-void systemz::getSystemZTargetFeatures(const Driver &D, const ArgList &Args,
+void systemz::getSystemZTargetFeatures(const Driver &D, const llvm::Triple &T,
+                                       const ArgList &Args,
                                        std::vector<llvm::StringRef> &Features) 
{
   // -m(no-)htm overrides use of the transactional-execution facility.
   if (Arg *A = Args.getLastArg(options::OPT_mhtm, options::OPT_mno_htm)) {
@@ -62,18 +63,36 @@ void systemz::getSystemZTargetFeatures(const Driver &D, 
const ArgList &Args,
     else
       Features.push_back("-transactional-execution");
   }
+
+  bool HardFloatABI = false;
+  systemz::FloatABI FloatABI = systemz::getSystemZFloatABI(D, Args);
+  if (FloatABI == systemz::FloatABI::Soft)
+    Features.push_back("+soft-float");
+  else if (FloatABI == systemz::FloatABI::Hard)
+    HardFloatABI = true;
+
   // -m(no-)vx overrides use of the vector facility.
   if (Arg *A = Args.getLastArg(options::OPT_mvx, options::OPT_mno_vx)) {
-    if (A->getOption().matches(options::OPT_mvx))
+
+    // The -mvx requires at least -march=arch11/z13 when -mhard-float is in 
affect.
+    if (A->getOption().matches(options::OPT_mvx)) {
+      auto Arch = getSystemZTargetCPU(Args, T);
+      if (HardFloatABI && llvm::StringSwitch<bool>(Arch)
+              .Case("arch8", true)
+              .Case("z10", true)
+              .Case("arch9", true)
+              .Case("z196", true)
+              .Case("arch10", true)
+              .Case("zEC12", true)
+              .Default(false)) {
+        D.Diag(diag::err_drv_incompatible_arch)
+            << "-mvx" << "-march=arch11" << Arch;
+      }
       Features.push_back("+vector");
-    else
+    } else
       Features.push_back("-vector");
   }
 
-  systemz::FloatABI FloatABI = systemz::getSystemZFloatABI(D, Args);
-  if (FloatABI == systemz::FloatABI::Soft)
-    Features.push_back("+soft-float");
-
   if (const Arg *A = Args.getLastArg(options::OPT_munaligned_symbols,
                                      options::OPT_mno_unaligned_symbols)) {
     if (A->getOption().matches(options::OPT_munaligned_symbols))
diff --git a/clang/lib/Driver/ToolChains/Arch/SystemZ.h 
b/clang/lib/Driver/ToolChains/Arch/SystemZ.h
index f2d30d24ba63c..b5d1da71f58e1 100644
--- a/clang/lib/Driver/ToolChains/Arch/SystemZ.h
+++ b/clang/lib/Driver/ToolChains/Arch/SystemZ.h
@@ -30,7 +30,8 @@ FloatABI getSystemZFloatABI(const Driver &D, const 
llvm::opt::ArgList &Args);
 std::string getSystemZTargetCPU(const llvm::opt::ArgList &Args,
                                 const llvm::Triple &T);
 
-void getSystemZTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+void getSystemZTargetFeatures(const Driver &D, const llvm::Triple &T,
+                              const llvm::opt::ArgList &Args,
                               std::vector<llvm::StringRef> &Features);
 
 } // end namespace systemz
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 64859a318485b..dba514adbff8f 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -922,7 +922,7 @@ void tools::getTargetFeatures(const Driver &D, const 
llvm::Triple &Triple,
     riscv::getRISCVTargetFeatures(D, Triple, Args, Features);
     break;
   case llvm::Triple::systemz:
-    systemz::getSystemZTargetFeatures(D, Args, Features);
+    systemz::getSystemZTargetFeatures(D, Triple, Args, Features);
     break;
   case llvm::Triple::aarch64:
   case llvm::Triple::aarch64_32:
diff --git a/clang/test/CodeGen/SystemZ/zos-alignment.c 
b/clang/test/CodeGen/SystemZ/zos-alignment.c
index 65c6843e0d9ac..a9fe32e248157 100644
--- a/clang/test/CodeGen/SystemZ/zos-alignment.c
+++ b/clang/test/CodeGen/SystemZ/zos-alignment.c
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 -emit-llvm-only -triple s390x-none-zos 
-fdump-record-layouts %s | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -emit-llvm-only -triple s390x-none-zos 
-fdump-record-layouts -DINT128_A \
+// RUN: -target-cpu z13 %s | FileCheck %s --check-prefix=INT128
 // RUN: %clang_cc1 -emit-llvm -triple s390x-none-zos %s -o - | FileCheck %s 
--check-prefix=DECL
 
 static int __attribute__((aligned(32))) v0;
@@ -160,12 +162,14 @@ struct s11 {
 // CHECK-NEXT:         8 |   char b
 // CHECK-NEXT:           | [sizeof=16, align=8]
 
+#ifdef INT128_A
 struct s12 {
   __int128_t a;
 } S12;
-// CHECK:              0 | struct s12
-// CHECK-NEXT:         0 |   __int128_t a
-// CHECK-NEXT:           | [sizeof=16, align=8]
+// INT128:              0 | struct s12
+// INT128-NEXT:         0 |   __int128_t a
+// INT128-NEXT:           | [sizeof=16, align=8]
+#endif
 
 union u0 {
   unsigned short d1 __attribute__((packed));
diff --git a/clang/test/CodeGen/zos-abi-int128-error.c 
b/clang/test/CodeGen/zos-abi-int128-error.c
new file mode 100644
index 0000000000000..2f5eff1a885c7
--- /dev/null
+++ b/clang/test/CodeGen/zos-abi-int128-error.c
@@ -0,0 +1,16 @@
+// The following verifies that __int128 is not supported
+// RUN: %clang_cc1 -triple s390x-unknown-zos -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple s390x-unknown-zos -fsyntax-only -target-cpu arch10 
-verify %s
+// RUN: not %clang -msoft-float --target=s390x-unknown-zos %s 2> %t.err
+// RUN: FileCheck -check-prefix=CHECK-1 %s < %t.err
+// RUN: not %clang -mvx -march=zEC12 --target=s390x-unknown-linux-gnu %s 2> 
%t.err
+// RUN: FileCheck -check-prefix=CHECK-2 %s < %t.err
+// RUN: not %clang -mvx -march=zEC12 -mhard-float 
--target=s390x-unknown-linux-gnu %s 2> %t.err
+// RUN: FileCheck -check-prefix=CHECK-2 %s < %t.err
+// RUN: not %clang -mvx -march=zEC12 -msoft-float 
--target=s390x-unknown-linux-gnu %s 2> %t.err
+// RUN: not FileCheck -check-prefix=CHECK-2 %s < %t.err
+
+__int128 pass_int128(__int128 arg) { return arg; } // expected-error 
{{__int128 is not supported on this target}} expected-error {{__int128 is not 
supported on this target}}
+
+// CHECK-1: error: unsupported option '-msoft-float' for target 
's390x-unknown-zos'
+// CHECK-2: error: '-mvx' option requires at least '-march=arch11', current 
'zEC12' is too low
diff --git a/clang/test/Sema/zvector.c b/clang/test/Sema/zvector.c
index e1e4ab532426d..e3ceac48faf0b 100644
--- a/clang/test/Sema/zvector.c
+++ b/clang/test/Sema/zvector.c
@@ -2,6 +2,10 @@
 // RUN:  -flax-vector-conversions=none -W -Wall -Wconversion \
 // RUN:  -Werror -fsyntax-only -verify %s
 
+// RUN: %clang_cc1 -triple s390x-ibm-zos -fzvector -target-cpu z13 \
+// RUN:  -flax-vector-conversions=none -W -Wall -Wconversion \
+// RUN:  -Werror -fsyntax-only -verify %s
+
 vector signed char sc, sc2;
 vector unsigned char uc, uc2;
 vector bool char bc, bc2;
diff --git a/llvm/lib/Target/SystemZ/SystemZCallingConv.h 
b/llvm/lib/Target/SystemZ/SystemZCallingConv.h
index 9fcd5b8152c5a..88f532125abe3 100644
--- a/llvm/lib/Target/SystemZ/SystemZCallingConv.h
+++ b/llvm/lib/Target/SystemZ/SystemZCallingConv.h
@@ -96,6 +96,14 @@ inline bool CC_XPLINK64_Pointer(unsigned &ValNo, MVT &ValVT, 
MVT &LocVT,
   return false;
 }
 
+inline bool CC_XPLINK_Int128(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
+                                             CCValAssign::LocInfo &LocInfo,
+                                             ISD::ArgFlagsTy &ArgFlags, 
CCState &State) {
+  LocVT = MVT::v16i8;
+  LocInfo = CCValAssign::BCvt;
+  return false;
+}
+
 inline bool CC_XPLINK64_Shadow_Reg(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
                                    CCValAssign::LocInfo &LocInfo,
                                    ISD::ArgFlagsTy &ArgFlags, CCState &State) {
diff --git a/llvm/lib/Target/SystemZ/SystemZCallingConv.td 
b/llvm/lib/Target/SystemZ/SystemZCallingConv.td
index 4f483cf2479dd..7263587d54369 100644
--- a/llvm/lib/Target/SystemZ/SystemZCallingConv.td
+++ b/llvm/lib/Target/SystemZ/SystemZCallingConv.td
@@ -167,6 +167,9 @@ def CSR_SystemZ_XPLINK64_Vector : CalleeSavedRegs<(add 
CSR_SystemZ_XPLINK64,
 // z/OS XPLINK64 return value calling convention
 
//===----------------------------------------------------------------------===//
 def RetCC_SystemZ_XPLINK64 : CallingConv<[
+  // Convert an i128 value to vector
+  CCIfType<[i128], CCCustom<"CC_XPLINK_Int128">>,
+
   // XPLINK64 ABI compliant code widens integral types smaller than i64
   // to i64.
   CCIfType<[i32], CCPromoteToType<i64>>,
@@ -225,6 +228,10 @@ def CC_SystemZ_XPLINK64 : CallingConv<[
   CCIfPtr<CCCustom<"CC_XPLINK64_Pointer">>,
   // long double, can only be passed in GPR2 and GPR3, if available,
   // hence R2Q
+
+  // Convert an i128 value to vector
+  CCIfType<[i128], CCCustom<"CC_XPLINK_Int128">>,
+
   CCIfType<[f128], 
CCIfArgVarArg<CCCustom<"CC_XPLINK64_Allocate128BitVararg">>>,
   // Non fixed vector arguments are treated in the same way as long
   // doubles.
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 8e621aafe27d2..f93cbbfb557ca 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -1900,11 +1900,15 @@ static SDValue convertLocVTToValVT(SelectionDAG &DAG, 
const SDLoc &DL,
   if (VA.isExtInLoc())
     Value = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Value);
   else if (VA.getLocInfo() == CCValAssign::BCvt) {
-    // If this is a short vector argument loaded from the stack,
-    // extend from i64 to full vector size and then bitcast.
-    assert(VA.getLocVT() == MVT::i64);
-    assert(VA.getValVT().isVector());
-    Value = DAG.getBuildVector(MVT::v2i64, DL, {Value, 
DAG.getUNDEF(MVT::i64)});
+    // If the argument is a short vector loaded from the stack,
+    // extend it from i64 to the full vector size and then perform a bitcast.
+    // Alternatively, if the argument is an int128,
+    // directly bitcast it into a vector of v16i8.
+    assert(VA.getLocVT() == MVT::i64 || VA.getLocVT() == MVT::v16i8);
+    assert(VA.getValVT().isVector() || VA.getValVT() == MVT::i128);
+    if (VA.getLocVT() == MVT::i64)
+      Value =
+          DAG.getBuildVector(MVT::v2i64, DL, {Value, DAG.getUNDEF(MVT::i64)});
     Value = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Value);
   } else
     assert(VA.getLocInfo() == CCValAssign::Full && "Unsupported getLocInfo");
@@ -1924,9 +1928,11 @@ static SDValue convertValVTToLocVT(SelectionDAG &DAG, 
const SDLoc &DL,
   case CCValAssign::AExt:
     return DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Value);
   case CCValAssign::BCvt: {
-    assert(VA.getLocVT() == MVT::i64 || VA.getLocVT() == MVT::i128);
+    assert(VA.getLocVT() == MVT::i64 || VA.getLocVT() == MVT::i128 ||
+           VA.getLocVT() == MVT::v16i8);
     assert(VA.getValVT().isVector() || VA.getValVT() == MVT::f32 ||
-           VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::f128);
+           VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::f128 ||
+           VA.getValVT() == MVT::i128);
     // For an f32 vararg we need to first promote it to an f64 and then
     // bitcast it to an i64.
     if (VA.getValVT() == MVT::f32 && VA.getLocVT() == MVT::i64)
@@ -2608,9 +2614,12 @@ bool SystemZTargetLowering::CanLowerReturn(
     const Type *RetTy) const {
   // Special case that we cannot easily detect in RetCC_SystemZ since
   // i128 may not be a legal type.
-  for (auto &Out : Outs)
-    if (Out.ArgVT.isScalarInteger() && Out.ArgVT.getSizeInBits() > 64)
-      return false;
+  // On z/OS we need to skip the convention of passing the return value on
+  // the stack used on zLinux.
+  if (Subtarget.isTargetLinux())
+    for (auto &Out : Outs)
+      if (Out.ArgVT.isScalarInteger() && Out.ArgVT.getSizeInBits() > 64)
+        return false;
 
   SmallVector<CCValAssign, 16> RetLocs;
   CCState RetCCInfo(CallConv, IsVarArg, MF, RetLocs, Context);
diff --git a/llvm/lib/Target/SystemZ/SystemZSubtarget.h 
b/llvm/lib/Target/SystemZ/SystemZSubtarget.h
index 761bc525b59d3..eda9f095fb237 100644
--- a/llvm/lib/Target/SystemZ/SystemZSubtarget.h
+++ b/llvm/lib/Target/SystemZ/SystemZSubtarget.h
@@ -124,6 +124,9 @@ class SystemZSubtarget : public SystemZGenSubtargetInfo {
 
   // Returns TRUE if we are generating code for a s390x machine running zOS
   bool isTargetzOS() const { return TargetTriple.isOSzOS(); }
+
+  // Returns TRUE if we are generating code for a s390x machine running Linux
+  bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
 };
 } // end namespace llvm
 
diff --git a/llvm/test/CodeGen/SystemZ/call-zos-i128.ll 
b/llvm/test/CodeGen/SystemZ/call-zos-i128.ll
index c12e26184f068..e5285377c939e 100644
--- a/llvm/test/CodeGen/SystemZ/call-zos-i128.ll
+++ b/llvm/test/CodeGen/SystemZ/call-zos-i128.ll
@@ -4,14 +4,9 @@
 
 ; CHECK-LABEL: call_i128 DS 0H
 ; CHECK-DAG: larl    1,L#CPI0_0
-; CHECK-DAG: vl      0,0(1),3
-; CHECK-DAG: vst     0,2256(4),3
+; CHECK-DAG: vl      24,0(1),3
 ; CHECK-DAG: larl    1,L#CPI0_1
-; CHECK-DAG: vl      0,0(1),3
-; CHECK-DAG: vst     0,2272(4),3
-; CHECK-DAG: la      1,2288(4)
-; CHECK-DAG: la      2,2272(4)
-; CHECK-DAG: la      3,2256(4)
+; CHECK-DAG: vl      25,0(1),3
 
 define i128 @call_i128() {
 entry:
@@ -20,10 +15,7 @@ entry:
 }
 
 ; CHECK-LABEL: pass_i128 DS 0H
-; CHECK: vl      0,0(3),3
-; CHECK: vl      1,0(2),3
-; CHECK: vaq     0,1,0
-; CHECK: vst     0,0(1),3
+; CHECK: vaq     24,24,25
 define i128 @pass_i128(i128 %arg0, i128 %arg1) {
 entry:
   %N = add i128 %arg0, %arg1
diff --git a/llvm/test/CodeGen/SystemZ/int-div-09.ll 
b/llvm/test/CodeGen/SystemZ/int-div-09.ll
new file mode 100644
index 0000000000000..bd77d62bf23ca
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/int-div-09.ll
@@ -0,0 +1,13 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 5
+; The objective of this test is to check conversion from i128 argument to 
vector v16i8.
+; This test was derived from builtins/floatuntitf.c residing in compiler.rt.
+
+; RUN: env LLVM_EMIT_GNU_AS_ZOS=0 llc -mtriple s390x-ibm-zos < %s | FileCheck 
%s
+$test_i128_arg = comdat any
+define void @test_i128_arg(ptr %this, i128 %__arg) "target-features"="+vector" 
{
+; CHECK-LABEL: test_i128_arg DS 0H
+; CHECK:       * %entry
+; CHECK-NEXT:  * %bb.0:
+entry:
+  ret void
+}
diff --git a/llvm/test/CodeGen/SystemZ/zos-abi-int128-64.ll 
b/llvm/test/CodeGen/SystemZ/zos-abi-int128-64.ll
new file mode 100644
index 0000000000000..afbd5f0b0d5e9
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/zos-abi-int128-64.ll
@@ -0,0 +1,253 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 5
+; RUN: env LLVM_EMIT_GNU_AS_ZOS=0 llc < %s| FileCheck %s
+
+source_filename = "zos-abi-int128-input.c"
+target datalayout = 
"E-m:l-p1:32:32-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
+target triple = "s390x-ibm-zos"
+
+attributes #0 = { "target-cpu"="z13" "target-features"="+vector" }
+
+; Check if GPR1 is used for the first integer argument and
+; VR24 for the second int128 argument and return value.
+;
+define i128 @pi_1i128(i32 signext %a1, i128 %a2) #0 {
+; CHECK-LABEL: pi_1i128 DS 0H
+; CHECK:        stmg 6,7,1904(4)
+; CHECK-NEXT:  L#stack_update0 DS 0H
+; CHECK-NEXT:   aghi 4,-160
+; CHECK:        L#end_of_prologue0 DS 0H
+; CHECK-NEXT:   vlvgp 0,1,1
+; CHECK-NEXT:   vrepf 0,0,3
+; CHECK-NEXT:   vrepib 1,96
+; CHECK-NEXT:   st 1,2204(4)
+; CHECK-NEXT:   vst 24,2184(4),3
+; CHECK-NEXT:   vsrab 0,0,1
+; CHECK-NEXT:   lg 7,2072(4)
+; CHECK-NEXT:   vaq 24,0,24
+; CHECK-NEXT:   aghi 4,160
+; CHECK-NEXT:   b 2(7)
+entry:
+  %a1.addr = alloca i32, align 4
+  %a2.addr = alloca i128, align 8
+  store i32 %a1, ptr %a1.addr, align 4
+  store i128 %a2, ptr %a2.addr, align 8
+  %0 = load i32, ptr %a1.addr, align 4
+  %conv = sext i32 %0 to i128
+  %1 = load i128, ptr %a2.addr, align 8
+  %add = add nsw i128 %conv, %1
+  ret i128 %add
+}
+
+; Check if VR24-31 are used for the first 8 int128 arguments and
+; the 9th int128 argument is loaded from the stack into VR0.
+; In addition, check VR24 is used for return value.
+;
+define i128 @p9i128(i128 %a1, i128 %a2, i128 %a3, i128 %a4, i128 %a5, i128 
%a6, i128 %a7, i128 %a8, i128 %a9) #0 {
+; CHECK-LABEL: p9i128 DS 0H
+; CHECK:        stmg 6,7,1776(4)
+; CHECK-NEXT:  L#stack_update1 DS 0H
+; CHECK-NEXT:   aghi 4,-288
+; CHECK:        L#end_of_prologue1 DS 0H
+; CHECK-NEXT:   vaq 1,24,25
+; CHECK-NEXT:   vaq 1,1,26
+; CHECK-NEXT:   vaq 1,1,27
+; CHECK-NEXT:   vl 0,2592(4),4
+; CHECK-NEXT:   vaq 1,1,28
+; CHECK-NEXT:   vaq 1,1,29
+; CHECK-NEXT:   vst 24,2320(4),3
+; CHECK-NEXT:   vst 25,2304(4),3
+; CHECK-NEXT:   vst 26,2288(4),3
+; CHECK-NEXT:   vst 27,2272(4),3
+; CHECK-NEXT:   vst 28,2256(4),3
+; CHECK-NEXT:   vst 29,2240(4),3
+; CHECK-NEXT:   vst 30,2224(4),3
+; CHECK-NEXT:   vst 31,2208(4),3
+; CHECK-NEXT:   vst 0,2192(4),3
+; CHECK-NEXT:   vaq 1,1,30
+; CHECK-NEXT:   lg 7,2072(4)
+; CHECK-NEXT:   vaq 1,1,31
+; CHECK-NEXT:   vaq 24,1,0
+; CHECK-NEXT:   aghi 4,288
+; CHECK-NEXT:   b 2(7)
+entry:
+  %a1.addr = alloca i128, align 8
+  %a2.addr = alloca i128, align 8
+  %a3.addr = alloca i128, align 8
+  %a4.addr = alloca i128, align 8
+  %a5.addr = alloca i128, align 8
+  %a6.addr = alloca i128, align 8
+  %a7.addr = alloca i128, align 8
+  %a8.addr = alloca i128, align 8
+  %a9.addr = alloca i128, align 8
+  store i128 %a1, ptr %a1.addr, align 8
+  store i128 %a2, ptr %a2.addr, align 8
+  store i128 %a3, ptr %a3.addr, align 8
+  store i128 %a4, ptr %a4.addr, align 8
+  store i128 %a5, ptr %a5.addr, align 8
+  store i128 %a6, ptr %a6.addr, align 8
+  store i128 %a7, ptr %a7.addr, align 8
+  store i128 %a8, ptr %a8.addr, align 8
+  store i128 %a9, ptr %a9.addr, align 8
+  %0 = load i128, ptr %a1.addr, align 8
+  %1 = load i128, ptr %a2.addr, align 8
+  %add = add nsw i128 %0, %1
+  %2 = load i128, ptr %a3.addr, align 8
+  %add1 = add nsw i128 %add, %2
+  %3 = load i128, ptr %a4.addr, align 8
+  %add2 = add nsw i128 %add1, %3
+  %4 = load i128, ptr %a5.addr, align 8
+  %add3 = add nsw i128 %add2, %4
+  %5 = load i128, ptr %a6.addr, align 8
+  %add4 = add nsw i128 %add3, %5
+  %6 = load i128, ptr %a7.addr, align 8
+  %add5 = add nsw i128 %add4, %6
+  %7 = load i128, ptr %a8.addr, align 8
+  %add6 = add nsw i128 %add5, %7
+  %8 = load i128, ptr %a9.addr, align 8
+  %add7 = add nsw i128 %add6, %8
+  ret i128 %add7
+}
+
+; Check if three int128 arguments in addition to variable argument(s) are 
passed in extended argument list.
+;
+define i128 @p3i128_var(i128 %a1, i128 %a2, i128 %a3, ...) #0 {
+; CHECK-LABEL: p3i128_var DS 0H
+; CHECK:        stmg 6,7,1840(4)
+; CHECK-NEXT:  L#stack_update2 DS 0H
+; CHECK-NEXT:   aghi 4,-224
+; CHECK-NEXT:   stg 1,2400(4)
+; CHECK-NEXT:   stg 2,2408(4)
+; CHECK-NEXT:   stg 3,2416(4)
+; CHECK:        L#end_of_prologue2 DS 0H
+; CHECK-NEXT:   vl 0,2448(4),4
+; CHECK-NEXT:   la 0,2464(4)
+; CHECK-NEXT:   vst 24,2256(4),3
+; CHECK-NEXT:   vst 25,2240(4),3
+; CHECK-NEXT:   vst 26,2224(4),3
+; CHECK-NEXT:   stg 0,2200(4)
+; CHECK-NEXT:   vst 0,2208(4),3
+; CHECK-NEXT:   vaq 1,24,25
+; CHECK-NEXT:   lg 7,2072(4)
+; CHECK-NEXT:   vaq 1,1,26
+; CHECK-NEXT:   vsq 24,1,0
+; CHECK-NEXT:   aghi 4,224
+; CHECK-NEXT:   b 2(7)
+entry:
+  %a1.addr = alloca i128, align 8
+  %a2.addr = alloca i128, align 8
+  %a3.addr = alloca i128, align 8
+  %a4 = alloca i128, align 8
+  %args = alloca ptr, align 8
+  store i128 %a1, ptr %a1.addr, align 8
+  store i128 %a2, ptr %a2.addr, align 8
+  store i128 %a3, ptr %a3.addr, align 8
+  call void @llvm.va_start.p0(ptr %args)
+  %argp.cur = load ptr, ptr %args, align 8
+  %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 16
+  store ptr %argp.next, ptr %args, align 8
+  %0 = load i128, ptr %argp.cur, align 8
+  store i128 %0, ptr %a4, align 8
+  call void @llvm.va_end.p0(ptr %args)
+  %1 = load i128, ptr %a1.addr, align 8
+  %2 = load i128, ptr %a2.addr, align 8
+  %add = add nsw i128 %1, %2
+  %3 = load i128, ptr %a3.addr, align 8
+  %add1 = add nsw i128 %add, %3
+  %4 = load i128, ptr %a4, align 8
+  %sub = sub nsw i128 %add1, %4
+  ret i128 %sub
+}
+
+; Check the call side for above functions.
+;
+define signext i32 @main() #0 {
+; CHECK-LABEL: main DS 0H
+; CHECK:        stmg 6,8,1584(4)
+; CHECK-NEXT:  L#stack_update3 DS 0H
+; CHECK-NEXT:   aghi 4,-480
+; CHECK:        L#end_of_prologue3 DS 0H
+; CHECK-NEXT:   vgbm 0,0
+; CHECK-NEXT:   vgbm 24,0
+; CHECK-NEXT:   lgr 8,5
+; CHECK-NEXT:   lg 6,8(5)
+; CHECK-NEXT:   lg 5,0(5)
+; CHECK-NEXT:   lghi 1,10
+; CHECK-NEXT:   mvhi 2524(4),0
+; CHECK-NEXT:   vst 0,2504(4),3
+; CHECK-NEXT:   basr 7,6
+; CHECK-NEXT:   bcr 0,0
+; CHECK-NEXT:   vl 0,2504(4),3
+; CHECK-NEXT:   vaq 24,0,24
+; CHECK-NEXT:   vl 0,2376(4),3
+; CHECK-NEXT:   vl 31,2392(4),3
+; CHECK-NEXT:   vl 30,2408(4),3
+; CHECK-NEXT:   vl 29,2424(4),3
+; CHECK-NEXT:   vl 28,2440(4),3
+; CHECK-NEXT:   vl 27,2456(4),3
+; CHECK-NEXT:   vl 26,2472(4),3
+; CHECK-NEXT:   vl 25,2488(4),3
+; CHECK-NEXT:   lg 6,24(8)
+; CHECK-NEXT:   lg 5,16(8)
+; CHECK-NEXT:   vst 24,2504(4),3
+; CHECK-NEXT:   vst 0,2304(4),3
+; CHECK-NEXT:   basr 7,6
+; CHECK-NEXT:   bcr 0,0
+; CHECK-NEXT:   vl 0,2504(4),3
+; CHECK-NEXT:   vaq 24,0,24
+; CHECK-NEXT:   vl 0,2456(4),3
+; CHECK-NEXT:   vl 26,2472(4),3
+; CHECK-NEXT:   vl 25,2488(4),3
+; CHECK-NEXT:   lg 6,40(8)
+; CHECK-NEXT:   lg 5,32(8)
+; CHECK-NEXT:   vst 24,2504(4),3
+; CHECK-NEXT:   vst 0,2224(4),3
+; CHECK-NEXT:   basr 7,6
+; CHECK-NEXT:   bcr 0,0
+; CHECK-NEXT:   vl 0,2504(4),3
+; CHECK-NEXT:   vaq 0,0,24
+; CHECK-NEXT:   vst 0,2504(4),3
+; CHECK-NEXT:   lmg 7,8,2072(4)
+; CHECK-NEXT:   lghi 3,0
+; CHECK-NEXT:   aghi 4,480
+; CHECK-NEXT:   b 2(7)
+entry:
+  %retval = alloca i32, align 4
+  %a1 = alloca i128, align 8
+  %a2 = alloca i128, align 8
+  %a3 = alloca i128, align 8
+  %s4 = alloca i128, align 8
+  %a5 = alloca i128, align 8
+  %a6 = alloca i128, align 8
+  %a7 = alloca i128, align 8
+  %a8 = alloca i128, align 8
+  %a9 = alloca i128, align 8
+  store i32 0, ptr %retval, align 4
+  store i128 0, ptr %a1, align 8
+  %0 = load i128, ptr %a1, align 8
+  %call = call i128 @pi_1i128(i32 signext 10, i128 %0)
+  %1 = load i128, ptr %a1, align 8
+  %add = add nsw i128 %1, %call
+  store i128 %add, ptr %a1, align 8
+  %2 = load i128, ptr %a1, align 8
+  %3 = load i128, ptr %a2, align 8
+  %4 = load i128, ptr %a3, align 8
+  %5 = load i128, ptr %s4, align 8
+  %6 = load i128, ptr %a5, align 8
+  %7 = load i128, ptr %a6, align 8
+  %8 = load i128, ptr %a7, align 8
+  %9 = load i128, ptr %a8, align 8
+  %10 = load i128, ptr %a9, align 8
+  %call1 = call i128 @p9i128(i128 %2, i128 %3, i128 %4, i128 %5, i128 %6, i128 
%7, i128 %8, i128 %9, i128 %10)
+  %11 = load i128, ptr %a1, align 8
+  %add2 = add nsw i128 %11, %call1
+  store i128 %add2, ptr %a1, align 8
+  %12 = load i128, ptr %a1, align 8
+  %13 = load i128, ptr %a2, align 8
+  %14 = load i128, ptr %a3, align 8
+  %15 = load i128, ptr %s4, align 8
+  %call3 = call i128 (i128, i128, i128, ...) @p3i128_var(i128 %12, i128 %13, 
i128 %14, i128 %15)
+  %16 = load i128, ptr %a1, align 8
+  %add4 = add nsw i128 %16, %call3
+  store i128 %add4, ptr %a1, align 8
+  ret i32 0
+}

>From 431747b3cd53d77b6d32974615931ea1f8965efb Mon Sep 17 00:00:00 2001
From: Zibi Sarbinowski <[email protected]>
Date: Fri, 11 Sep 2026 15:46:15 -0400
Subject: [PATCH 2/2] [SystemZ] clang-format fixes for i128 XPLINK64 ABI
 changes

---
 clang/lib/Driver/ToolChains/Arch/SystemZ.cpp | 17 +++++++++--------
 llvm/lib/Target/SystemZ/SystemZCallingConv.h |  4 ++--
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp 
b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
index 583d04d8c84f5..69a06f1dddf46 100644
--- a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
@@ -74,17 +74,18 @@ void systemz::getSystemZTargetFeatures(const Driver &D, 
const llvm::Triple &T,
   // -m(no-)vx overrides use of the vector facility.
   if (Arg *A = Args.getLastArg(options::OPT_mvx, options::OPT_mno_vx)) {
 
-    // The -mvx requires at least -march=arch11/z13 when -mhard-float is in 
affect.
+    // The -mvx requires at least -march=arch11/z13 when -mhard-float is in
+    // affect.
     if (A->getOption().matches(options::OPT_mvx)) {
       auto Arch = getSystemZTargetCPU(Args, T);
       if (HardFloatABI && llvm::StringSwitch<bool>(Arch)
-              .Case("arch8", true)
-              .Case("z10", true)
-              .Case("arch9", true)
-              .Case("z196", true)
-              .Case("arch10", true)
-              .Case("zEC12", true)
-              .Default(false)) {
+                              .Case("arch8", true)
+                              .Case("z10", true)
+                              .Case("arch9", true)
+                              .Case("z196", true)
+                              .Case("arch10", true)
+                              .Case("zEC12", true)
+                              .Default(false)) {
         D.Diag(diag::err_drv_incompatible_arch)
             << "-mvx" << "-march=arch11" << Arch;
       }
diff --git a/llvm/lib/Target/SystemZ/SystemZCallingConv.h 
b/llvm/lib/Target/SystemZ/SystemZCallingConv.h
index 88f532125abe3..91a1fe8f12d96 100644
--- a/llvm/lib/Target/SystemZ/SystemZCallingConv.h
+++ b/llvm/lib/Target/SystemZ/SystemZCallingConv.h
@@ -97,8 +97,8 @@ inline bool CC_XPLINK64_Pointer(unsigned &ValNo, MVT &ValVT, 
MVT &LocVT,
 }
 
 inline bool CC_XPLINK_Int128(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
-                                             CCValAssign::LocInfo &LocInfo,
-                                             ISD::ArgFlagsTy &ArgFlags, 
CCState &State) {
+                             CCValAssign::LocInfo &LocInfo,
+                             ISD::ArgFlagsTy &ArgFlags, CCState &State) {
   LocVT = MVT::v16i8;
   LocInfo = CCValAssign::BCvt;
   return false;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to