https://github.com/JonPsson1 updated 
https://github.com/llvm/llvm-project/pull/223755

>From 2127ac3f7b76e984d613edbb1a03d8ae04838e52 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <[email protected]>
Date: Tue, 15 Sep 2026 18:34:54 +0200
Subject: [PATCH 01/10] [SystemZ, Clang] Enable verification of integer args
 extensions by default.

This has been temporarily disabled behind a CL option with hopes to enable it
by default globally, which unfortunately did not yet seem like a good idea.

At least now the Clang frontend will verify this always, and hopefully more
frontends will enable this over time.
---
 clang/lib/CodeGen/BackendUtil.cpp             |  1 +
 .../CodeGen/SystemZ/systemz-abi-intargs.c     | 28 ++++++++++++++
 llvm/include/llvm/Target/TargetOptions.h      |  7 ++--
 .../Target/SystemZ/SystemZISelLowering.cpp    | 38 ++++++++++---------
 llvm/lib/Target/SystemZ/SystemZISelLowering.h |  1 +
 llvm/tools/llc/lib/llcdriver.cpp              |  4 --
 6 files changed, 53 insertions(+), 26 deletions(-)
 create mode 100644 clang/test/CodeGen/SystemZ/systemz-abi-intargs.c

diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index f07e4ee84b9b65..19678141651917 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -511,6 +511,7 @@ static bool initTargetOptions(const CompilerInstance &CI,
   Options.MCOptions.PPCUseFullRegisterNames =
       CodeGenOpts.PPCUseFullRegisterNames;
   Options.MisExpect = CodeGenOpts.MisExpect;
+  Options.VerifyArgABICompliance = true;
 
   return true;
 }
diff --git a/clang/test/CodeGen/SystemZ/systemz-abi-intargs.c 
b/clang/test/CodeGen/SystemZ/systemz-abi-intargs.c
new file mode 100644
index 00000000000000..1b9ec7776c02e6
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/systemz-abi-intargs.c
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple s390x-linux-gnu -S -O3 %s -o - \
+// RUN:    -mllvm -debug-only=systemz-lower 2>&1 | FileCheck %s
+//
+// REQUIRES: systemz-registered-target, asserts
+//
+// Check that clang verifies the extensions of narrow integer arguments by 
default.
+
+int __attribute__ ((noinline)) foo(int Arg, unsigned Arg2) {
+  return Arg + Arg2;
+}
+
+int fun(short *Arg, unsigned char *Arg2) {
+  return foo(*Arg, *Arg2);
+}
+
+// CHECK: Return argument verified as ABI compliant        : noundef signext 
i32 @foo(i32 signext, i32 zeroext)
+// CHECK: Outgoing call arguments verified as ABI compliant: noundef signext 
i32 @foo(i32 signext, i32 zeroext)
+
+// CHECK-LABEL: foo:
+// CHECK:       ar   %r3, %r2
+// CHECK-NEXT:  lgfr %r2, %r3
+// CHECK-NEXT:  br   %r14
+//
+// CHECK-LABEL: fun:
+// CHECK:       lgh  %r2, 0(%r2)
+// CHECK-NEXT:  llgc %r3, 0(%r3)
+// CHECK-NEXT:  jg   foo@PLT
+
diff --git a/llvm/include/llvm/Target/TargetOptions.h 
b/llvm/include/llvm/Target/TargetOptions.h
index 264db07ded991f..0bec4ba6203d30 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -134,7 +134,7 @@ class TargetOptions {
         ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false),
         XRayFunctionIndex(true), DebugStrictDwarf(false), JMCInstrument(false),
         EnableCFIFixup(false), MisExpect(false), XCOFFReadOnlyPointers(false),
-        VerifyArgABICompliance(true) {}
+        VerifyArgABICompliance(false) {}
 
   /// NoZerosInBSS - By default some codegens place zero-initialized data to
   /// .bss section. This flag disables such behaviour (necessary, e.g. for
@@ -291,9 +291,8 @@ class TargetOptions {
   unsigned XCOFFReadOnlyPointers : 1;
 
   /// When set to true, call/return argument extensions of narrow integers
-  /// are verified in the target backend if it cares about them. This is
-  /// not done with internal tools like llc that run many tests that ignore
-  /// (lack) these extensions.
+  /// are verified in the target backend if it cares about them. This is off
+  /// by default and enabled explicitly by each front-end separately.
   unsigned VerifyArgABICompliance : 1;
 
   /// Name of the stack usage file (i.e., .su file) if user passes
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 1813f9b97ceaa7..c15d8190d130f5 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11490,7 +11490,7 @@ SDValue 
SystemZTargetLowering::lowerVECREDUCE_ADD(SDValue Op,
       DAG.getConstant(OpVT.getVectorNumElements() - 1, DL, MVT::i32));
 }
 
-static void printFunctionArgExts(const Function *F, raw_fd_ostream &OS) {
+static void printFunctionArgExts(const Function *F, raw_ostream &OS) {
   FunctionType *FT = F->getFunctionType();
   const AttributeList &Attrs = F->getAttributes();
   if (Attrs.hasRetAttrs())
@@ -11518,14 +11518,21 @@ bool SystemZTargetLowering::isInternal(const Function 
*Fn) const {
   return Itr->second;
 }
 
+bool SystemZTargetLowering::enableNarrowIntArgsVerification() const {
+  if (!Subtarget.isTargetELF())
+    return false;
+
+  if (EnableIntArgExtCheck.getNumOccurrences())
+    return EnableIntArgExtCheck;
+
+  return getTargetMachine().Options.VerifyArgABICompliance;
+}
+
 void SystemZTargetLowering::
 verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
                              const Function *F, SDValue Callee) const {
-  // Temporarily only do the check when explicitly requested, until it can be
-  // enabled by default.
-  if (!EnableIntArgExtCheck)
+  if (!enableNarrowIntArgsVerification())
     return;
-
   bool IsInternal = false;
   const Function *CalleeFn = nullptr;
   if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
@@ -11542,37 +11549,32 @@ verifyNarrowIntegerArgs_Call(const 
SmallVectorImpl<ISD::OutputArg> &Outs,
     printFunctionArgExts(F, errs());
     llvm_unreachable("");
   }
+  LLVM_DEBUG(dbgs() << "Outgoing call arguments verified as ABI compliant: ";
+             if (CalleeFn != nullptr)
+               printFunctionArgExts(CalleeFn, dbgs());
+             else
+               dbgs() << "-\n";);
 }
 
 void SystemZTargetLowering::
 verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
                             const Function *F) const {
-  // Temporarily only do the check when explicitly requested, until it can be
-  // enabled by default.
-  if (!EnableIntArgExtCheck)
+  if (!enableNarrowIntArgsVerification())
     return;
-
   if (!isInternal(F) && !verifyNarrowIntegerArgs(Outs)) {
     errs() << "ERROR: Missing extension attribute of returned "
            << "value from function:\n";
     printFunctionArgExts(F, errs());
     llvm_unreachable("");
   }
+  LLVM_DEBUG(dbgs() << "Return argument verified as ABI compliant        : ";
+             printFunctionArgExts(F, dbgs()));
 }
 
 // Verify that narrow integer arguments are extended as required by the ABI.
 // Return false if an error is found.
 bool SystemZTargetLowering::verifyNarrowIntegerArgs(
     const SmallVectorImpl<ISD::OutputArg> &Outs) const {
-  if (!Subtarget.isTargetELF())
-    return true;
-
-  if (EnableIntArgExtCheck.getNumOccurrences()) {
-    if (!EnableIntArgExtCheck)
-      return true;
-  } else if (!getTargetMachine().Options.VerifyArgABICompliance)
-    return true;
-
   for (unsigned i = 0; i < Outs.size(); ++i) {
     MVT VT = Outs[i].VT;
     ISD::ArgFlagsTy Flags = Outs[i].Flags;
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 65463c48f3c4ad..c3f7cee4508a37 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -465,6 +465,7 @@ class SystemZTargetLowering : public TargetLowering {
   const TargetRegisterClass *getRepRegClassFor(MVT VT) const override;
 
 private:
+  bool enableNarrowIntArgsVerification() const;
   bool isInternal(const Function *Fn) const;
   mutable std::map<const Function *, bool> IsInternalCache;
   void verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> 
&Outs,
diff --git a/llvm/tools/llc/lib/llcdriver.cpp b/llvm/tools/llc/lib/llcdriver.cpp
index 241c5148bd4ab6..2deda8a93360ac 100644
--- a/llvm/tools/llc/lib/llcdriver.cpp
+++ b/llvm/tools/llc/lib/llcdriver.cpp
@@ -695,10 +695,6 @@ static int compileModule(char **argv, 
SmallVectorImpl<PassPlugin> &PluginList,
   // Return a copy of the output filename via the output param
   OutputFilename = Out->outputFilename();
 
-  // Tell target that this tool is not necessarily used with argument ABI
-  // compliance (i.e. narrow integer argument extensions).
-  Target->Options.VerifyArgABICompliance = 0;
-
   std::unique_ptr<ToolOutputFile> DwoOut;
   if (!SplitDwarfOutputFile.empty()) {
     std::error_code EC;

>From 1935f799e1354e9a44d52864eeb37da4c5f04e59 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <[email protected]>
Date: Tue, 15 Sep 2026 18:45:36 +0200
Subject: [PATCH 02/10] clang-format

---
 llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index c15d8190d130f5..45218dbc44897f 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11550,10 +11550,8 @@ verifyNarrowIntegerArgs_Call(const 
SmallVectorImpl<ISD::OutputArg> &Outs,
     llvm_unreachable("");
   }
   LLVM_DEBUG(dbgs() << "Outgoing call arguments verified as ABI compliant: ";
-             if (CalleeFn != nullptr)
-               printFunctionArgExts(CalleeFn, dbgs());
-             else
-               dbgs() << "-\n";);
+             if (CalleeFn != nullptr) printFunctionArgExts(CalleeFn, dbgs());
+             else dbgs() << "-\n";);
 }
 
 void SystemZTargetLowering::

>From 24487784277ec733fa48aec44aacd051c61d2e8b Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <[email protected]>
Date: Tue, 15 Sep 2026 19:04:55 +0200
Subject: [PATCH 03/10] Skip this if NDEBUG is defined

---
 llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 45218dbc44897f..c937667a187c1b 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11519,6 +11519,10 @@ bool SystemZTargetLowering::isInternal(const Function 
*Fn) const {
 }
 
 bool SystemZTargetLowering::enableNarrowIntArgsVerification() const {
+#ifdef NDEBUG
+  return false;
+#endif
+
   if (!Subtarget.isTargetELF())
     return false;
 

>From ddf46d0c7b590d14586ebbc9693c6b108a18bf12 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <[email protected]>
Date: Wed, 16 Sep 2026 17:15:55 +0200
Subject: [PATCH 04/10] Move down NDEBUG check to respect CL option.

---
 llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index c937667a187c1b..6451a6e4da189a 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11519,16 +11519,16 @@ bool SystemZTargetLowering::isInternal(const Function 
*Fn) const {
 }
 
 bool SystemZTargetLowering::enableNarrowIntArgsVerification() const {
-#ifdef NDEBUG
-  return false;
-#endif
-
   if (!Subtarget.isTargetELF())
     return false;
 
   if (EnableIntArgExtCheck.getNumOccurrences())
     return EnableIntArgExtCheck;
 
+#ifdef NDEBUG
+  return false;
+#endif
+
   return getTargetMachine().Options.VerifyArgABICompliance;
 }
 

>From ad54f9ac5dd3e15995f01b422083aaf48f421507 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <[email protected]>
Date: Fri, 25 Sep 2026 13:28:10 +0200
Subject: [PATCH 05/10] Check for C CallingConv instead of isInternal().

---
 .../Target/SystemZ/SystemZISelLowering.cpp    | 23 ++++++-------------
 llvm/lib/Target/SystemZ/SystemZISelLowering.h |  2 --
 llvm/test/CodeGen/SystemZ/args-14.ll          |  7 +++---
 3 files changed, 10 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 6451a6e4da189a..aea74cc2650c28 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11508,16 +11508,6 @@ static void printFunctionArgExts(const Function *F, 
raw_ostream &OS) {
   OS << ")\n";
 }
 
-bool SystemZTargetLowering::isInternal(const Function *Fn) const {
-  std::map<const Function *, bool>::iterator Itr = IsInternalCache.find(Fn);
-  if (Itr == IsInternalCache.end())
-    Itr = IsInternalCache
-              .insert(std::pair<const Function *, bool>(
-                  Fn, (Fn->hasLocalLinkage() && !Fn->hasAddressTaken())))
-              .first;
-  return Itr->second;
-}
-
 bool SystemZTargetLowering::enableNarrowIntArgsVerification() const {
   if (!Subtarget.isTargetELF())
     return false;
@@ -11537,12 +11527,12 @@ verifyNarrowIntegerArgs_Call(const 
SmallVectorImpl<ISD::OutputArg> &Outs,
                              const Function *F, SDValue Callee) const {
   if (!enableNarrowIntArgsVerification())
     return;
-  bool IsInternal = false;
   const Function *CalleeFn = nullptr;
   if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
-    if ((CalleeFn = dyn_cast<Function>(G->getGlobal())))
-      IsInternal = isInternal(CalleeFn);
-  if (!IsInternal && !verifyNarrowIntegerArgs(Outs)) {
+    CalleeFn = dyn_cast<Function>(G->getGlobal());
+  if (CalleeFn && CalleeFn->getCallingConv() != CallingConv::C)
+    return;
+  if (!verifyNarrowIntegerArgs(Outs)) {
     errs() << "ERROR: Missing extension attribute of passed "
            << "value in call to function:\n" << "Callee:  ";
     if (CalleeFn != nullptr)
@@ -11561,9 +11551,10 @@ verifyNarrowIntegerArgs_Call(const 
SmallVectorImpl<ISD::OutputArg> &Outs,
 void SystemZTargetLowering::
 verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
                             const Function *F) const {
-  if (!enableNarrowIntArgsVerification())
+  if (!enableNarrowIntArgsVerification() ||
+      F->getCallingConv() != CallingConv::C)
     return;
-  if (!isInternal(F) && !verifyNarrowIntegerArgs(Outs)) {
+  if (!verifyNarrowIntegerArgs(Outs)) {
     errs() << "ERROR: Missing extension attribute of returned "
            << "value from function:\n";
     printFunctionArgExts(F, errs());
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index c3f7cee4508a37..986f8626871b00 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -466,8 +466,6 @@ class SystemZTargetLowering : public TargetLowering {
 
 private:
   bool enableNarrowIntArgsVerification() const;
-  bool isInternal(const Function *Fn) const;
-  mutable std::map<const Function *, bool> IsInternalCache;
   void verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> 
&Outs,
                                     const Function *F, SDValue Callee) const;
   void verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
diff --git a/llvm/test/CodeGen/SystemZ/args-14.ll 
b/llvm/test/CodeGen/SystemZ/args-14.ll
index 84e7523e788de4..7948bcc67402b9 100644
--- a/llvm/test/CodeGen/SystemZ/args-14.ll
+++ b/llvm/test/CodeGen/SystemZ/args-14.ll
@@ -27,13 +27,12 @@ define noext i32 @callee_NoExtRet_i32() {
   ret i32 -1
 }
 
-; An internal function is not checked for an extension attribute.
-define internal i32 @callee_NoExtRet_internal(i32 %Arg) {
+; Only the C CallingConv strictly requires extension attributes.
+define internal fastcc i32 @callee_NoExtRet_fastcc(i32 %Arg) {
   ret i32 %Arg
 }
 
-; A call to an internal function is ok without argument extension.
 define void @caller_internal() {
-  call i32 @callee_NoExtRet_internal(i32 0)
+  call fastcc i32 @callee_NoExtRet_fastcc(i32 0)
   ret void
 }

>From e51067c09f503e35d8994ce0a22c7e774cf5fb3d Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <[email protected]>
Date: Mon, 28 Sep 2026 10:44:34 +0200
Subject: [PATCH 06/10] Patch improved:

- Check for SystemZ C ABI with C CallingConv and "not fully internal".
- In (common) case with a Function prototype, check that if the prototype
  argument has ZExt or SExt, then the correpsonding OutputArg should
  also have it.
- Check against both ZExt and SExt flags set, which is not impossible to
  end up with.
- Also handle vararg and indirect calls.
- More tests added, also reflecting cases where (currently) the ext attribute
  found in the prototype is added to the call site (passing test).
---
 .../Target/SystemZ/SystemZISelLowering.cpp    | 102 +++++++++++++-----
 llvm/lib/Target/SystemZ/SystemZISelLowering.h |  13 ++-
 llvm/test/CodeGen/SystemZ/args-14.ll          |  45 ++++++--
 llvm/test/CodeGen/SystemZ/args-15.ll          |   4 +-
 llvm/test/CodeGen/SystemZ/args-16.ll          |  12 ++-
 llvm/test/CodeGen/SystemZ/args-17.ll          |   4 +-
 llvm/test/CodeGen/SystemZ/args-18.ll          |   8 +-
 llvm/test/CodeGen/SystemZ/args-19.ll          |  16 ++-
 llvm/test/CodeGen/SystemZ/args-20.ll          |   8 +-
 .../test/CodeGen/SystemZ/args-21-SExt-ZExt.ll |  19 ++++
 .../test/CodeGen/SystemZ/args-21-ZExt-SExt.ll |  19 ++++
 llvm/test/CodeGen/SystemZ/args-21.ll          |  21 ----
 llvm/test/CodeGen/SystemZ/args-24.ll          |  95 ++++++++++++++++
 llvm/test/CodeGen/SystemZ/args-25.ll          |  31 ++++++
 llvm/test/CodeGen/SystemZ/args-26.ll          |  20 ++++
 llvm/test/CodeGen/SystemZ/args-27.ll          |  20 ++++
 llvm/test/CodeGen/SystemZ/args-28.ll          |  20 ++++
 llvm/test/CodeGen/SystemZ/args-29.ll          |  21 ++++
 llvm/test/CodeGen/SystemZ/args-30.ll          |  16 +++
 19 files changed, 415 insertions(+), 79 deletions(-)
 create mode 100644 llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
 create mode 100644 llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll
 delete mode 100644 llvm/test/CodeGen/SystemZ/args-21.ll
 create mode 100644 llvm/test/CodeGen/SystemZ/args-24.ll
 create mode 100644 llvm/test/CodeGen/SystemZ/args-25.ll
 create mode 100644 llvm/test/CodeGen/SystemZ/args-26.ll
 create mode 100644 llvm/test/CodeGen/SystemZ/args-27.ll
 create mode 100644 llvm/test/CodeGen/SystemZ/args-28.ll
 create mode 100644 llvm/test/CodeGen/SystemZ/args-29.ll
 create mode 100644 llvm/test/CodeGen/SystemZ/args-30.ll

diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index aea74cc2650c28..6da70c60d20cc3 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -2391,7 +2391,7 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI,
     IsTailCall = false;
 
   // Integer args <=32 bits should have an extension attribute.
-  verifyNarrowIntegerArgs_Call(Outs, &MF.getFunction(), Callee);
+  verifyNarrowIntegerArgs_Call(CLI, Outs, &MF.getFunction(), Callee);
 
   // Analyze the operands of the call, assigning locations to each operand.
   SmallVector<CCValAssign, 16> ArgLocs;
@@ -2650,7 +2650,7 @@ SystemZTargetLowering::LowerReturn(SDValue Chain, 
CallingConv::ID CallConv,
   MachineFunction &MF = DAG.getMachineFunction();
 
   // Integer args <=32 bits should have an extension attribute.
-  verifyNarrowIntegerArgs_Ret(Outs, &MF.getFunction());
+  verifyNarrowIntegerArgs_Ret(CallConv, Outs, &MF.getFunction());
 
   // Assign locations to each returned value.
   SmallVector<CCValAssign, 16> RetLocs;
@@ -11505,9 +11505,21 @@ static void printFunctionArgExts(const Function *F, 
raw_ostream &OS) {
       if (ArgAttrs.hasAttribute(A))
         OS << " " << Attribute::getNameFromAttrKind(A);
   }
+  if (F->isVarArg())
+    OS << ", ...";
   OS << ")\n";
 }
 
+bool SystemZTargetLowering::isInternal(const Function *Fn) const {
+  std::map<const Function *, bool>::iterator Itr = IsInternalCache.find(Fn);
+  if (Itr == IsInternalCache.end())
+    Itr = IsInternalCache
+              .insert(std::pair<const Function *, bool>(
+                  Fn, (Fn->hasLocalLinkage() && !Fn->hasAddressTaken())))
+              .first;
+  return Itr->second;
+}
+
 bool SystemZTargetLowering::enableNarrowIntArgsVerification() const {
   if (!Subtarget.isTargetELF())
     return false;
@@ -11522,25 +11534,30 @@ bool 
SystemZTargetLowering::enableNarrowIntArgsVerification() const {
   return getTargetMachine().Options.VerifyArgABICompliance;
 }
 
-void SystemZTargetLowering::
-verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
-                             const Function *F, SDValue Callee) const {
+void SystemZTargetLowering::verifyNarrowIntegerArgs_Call(
+    CallLoweringInfo &CLI, const SmallVectorImpl<ISD::OutputArg> &Outs,
+    const Function *F, SDValue Callee) const {
   if (!enableNarrowIntArgsVerification())
     return;
+  bool IsInternal = false;
   const Function *CalleeFn = nullptr;
   if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
-    CalleeFn = dyn_cast<Function>(G->getGlobal());
-  if (CalleeFn && CalleeFn->getCallingConv() != CallingConv::C)
-    return;
-  if (!verifyNarrowIntegerArgs(Outs)) {
-    errs() << "ERROR: Missing extension attribute of passed "
-           << "value in call to function:\n" << "Callee:  ";
+    if ((CalleeFn = dyn_cast<Function>(G->getGlobal()))) {
+      IsInternal = isInternal(CalleeFn);
+      assert(CalleeFn->getCallingConv() == CLI.CallConv &&
+             "Wrong calling convention used.");
+    }
+  bool C_ABI = CLI.CallConv == CallingConv::C && !IsInternal;
+  if (!verifyNarrowIntegerArgs(C_ABI, Outs, CalleeFn, /*IsRet=*/false)) {
+    errs() << "Callee: ";
     if (CalleeFn != nullptr)
       printFunctionArgExts(CalleeFn, errs());
     else
       errs() << "-\n";
-    errs() << "Caller:  ";
+    errs() << "Caller: ";
     printFunctionArgExts(F, errs());
+    if (CLI.CB)
+      errs() << "      " << *CLI.CB;
     llvm_unreachable("");
   }
   LLVM_DEBUG(dbgs() << "Outgoing call arguments verified as ABI compliant: ";
@@ -11548,15 +11565,14 @@ verifyNarrowIntegerArgs_Call(const 
SmallVectorImpl<ISD::OutputArg> &Outs,
              else dbgs() << "-\n";);
 }
 
-void SystemZTargetLowering::
-verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
-                            const Function *F) const {
-  if (!enableNarrowIntArgsVerification() ||
-      F->getCallingConv() != CallingConv::C)
+void SystemZTargetLowering::verifyNarrowIntegerArgs_Ret(
+    CallingConv::ID CallConv, const SmallVectorImpl<ISD::OutputArg> &Outs,
+    const Function *F) const {
+  if (!enableNarrowIntArgsVerification())
     return;
-  if (!verifyNarrowIntegerArgs(Outs)) {
-    errs() << "ERROR: Missing extension attribute of returned "
-           << "value from function:\n";
+  bool C_ABI = CallConv == CallingConv::C && !isInternal(F);
+  if (!verifyNarrowIntegerArgs(C_ABI, Outs, F, /*IsRet=*/true)) {
+    errs() << "Returning from function: ";
     printFunctionArgExts(F, errs());
     llvm_unreachable("");
   }
@@ -11564,19 +11580,47 @@ verifyNarrowIntegerArgs_Ret(const 
SmallVectorImpl<ISD::OutputArg> &Outs,
              printFunctionArgExts(F, dbgs()));
 }
 
-// Verify that narrow integer arguments are extended as required by the ABI.
-// Return false if an error is found.
+// Verify that narrow integer arguments are extended according to the
+// function header (calllee for a call, containing function for a ret).
+// If C_ABI is true, an extension attribute must be present.
 bool SystemZTargetLowering::verifyNarrowIntegerArgs(
-    const SmallVectorImpl<ISD::OutputArg> &Outs) const {
+    bool C_ABI, const SmallVectorImpl<ISD::OutputArg> &Outs,
+    const Function *FunHeader, bool IsRet) const {
   for (unsigned i = 0; i < Outs.size(); ++i) {
-    MVT VT = Outs[i].VT;
+    EVT OrigArgVT = Outs[i].ArgVT;
+    if (!OrigArgVT.isInteger() || OrigArgVT.getSizeInBits() >= 64)
+      continue;
+    assert(Outs[i].VT == MVT::i32 && "Unexpected integer argument VT.");
     ISD::ArgFlagsTy Flags = Outs[i].Flags;
-    if (VT.isInteger()) {
-      assert((VT == MVT::i32 || VT.getSizeInBits() >= 64) &&
-             "Unexpected integer argument VT.");
-      if (VT == MVT::i32 &&
-          !Flags.isSExt() && !Flags.isZExt() && !Flags.isNoExt())
+    unsigned OrigIdx = Outs[i].OrigArgIndex;
+
+    // Per the C ABI there must be an extension.
+    if (C_ABI && !Flags.isSExt() && !Flags.isZExt() && !Flags.isNoExt()) {
+      errs() << "ERROR:  (C ABI violiation) missing extension attribute on arg 
"
+             << OrigIdx << ".\n";
+      return false;
+    }
+
+    // Flags should reflect the attributes of the function header.
+    if (FunHeader) {
+      const AttributeList &FunAttrs = FunHeader->getAttributes();
+      const AttributeSet Attrs =
+          IsRet ? FunAttrs.getRetAttrs() : FunAttrs.getParamAttrs(OrigIdx);
+      if (Attrs.hasAttribute(Attribute::SExt) && !Flags.isSExt()) {
+        errs() << "ERROR : Missing SExt on arg " << OrigIdx << ".\n";
+        return false;
+      }
+      if (Attrs.hasAttribute(Attribute::ZExt) && !Flags.isZExt()) {
+        errs() << "ERROR : Missing ZExt on arg " << OrigIdx << ".\n";
         return false;
+      }
+    }
+
+    // Flags should not end up with both kinds of extensions.
+    if (Flags.isSExt() && Flags.isZExt()) {
+      errs() << "ERROR : SExt and ZExt are incompatible (arg " << OrigIdx
+             << ").\n";
+      return false;
     }
   }
 
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 986f8626871b00..e1dc04615954fb 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -466,12 +466,17 @@ class SystemZTargetLowering : public TargetLowering {
 
 private:
   bool enableNarrowIntArgsVerification() const;
-  void verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> 
&Outs,
+  bool isInternal(const Function *Fn) const;
+  mutable std::map<const Function *, bool> IsInternalCache;
+  void verifyNarrowIntegerArgs_Call(CallLoweringInfo &CLI,
+                                    const SmallVectorImpl<ISD::OutputArg> 
&Outs,
                                     const Function *F, SDValue Callee) const;
-  void verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
+  void verifyNarrowIntegerArgs_Ret(CallingConv::ID CallConv,
+                                   const SmallVectorImpl<ISD::OutputArg> &Outs,
                                    const Function *F) const;
-  bool
-  verifyNarrowIntegerArgs(const SmallVectorImpl<ISD::OutputArg> &Outs) const;
+  bool verifyNarrowIntegerArgs(bool C_ABI,
+                               const SmallVectorImpl<ISD::OutputArg> &Outs,
+                               const Function *FunHeader, bool IsRet) const;
 
 public:
 };
diff --git a/llvm/test/CodeGen/SystemZ/args-14.ll 
b/llvm/test/CodeGen/SystemZ/args-14.ll
index 7948bcc67402b9..c1b4930009c0b6 100644
--- a/llvm/test/CodeGen/SystemZ/args-14.ll
+++ b/llvm/test/CodeGen/SystemZ/args-14.ll
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -mtriple=s390x-linux-gnu -argext-abi-check
+; REQUIRES: asserts
 
 ; Test that it works to pass structs as outgoing call arguments when the
 ; NoExt attribute is given, either in the call instruction or in the
@@ -7,32 +8,60 @@ define void @caller() {
   call void @bar_Struct_32(i32 noext 123)
   call void @bar_Struct_16(i16 123)
   call void @bar_Struct_8(i8 noext 123)
+  call void @bar_Struct_32_addrtaken(i32 noext 123)
   ret void
 }
 
 declare void @bar_Struct_32(i32 %Arg)
 declare void @bar_Struct_16(i16 noext %Arg)
 declare void @bar_Struct_8(i8 %Arg)
+define internal void @bar_Struct_32_addrtaken(i32 noext %Arg) {
+  ret void
+}
 
 ; Test that it works to return values with the NoExt attribute.
-define noext i8 @callee_NoExtRet_i8() {
+define noext i8 @fun_NoExtRet_i8() {
   ret i8 -1
 }
 
-define noext i16 @callee_NoExtRet_i16() {
+define noext i16 @fun_NoExtRet_i16() {
   ret i16 -1
 }
 
-define noext i32 @callee_NoExtRet_i32() {
+define noext i32 @fun_NoExtRet_i32() {
+  ret i32 -1
+}
+
+define internal noext i32 @fun_NoExtRet_i32_addrtaken() {
   ret i32 -1
 }
 
-; Only the C CallingConv strictly requires extension attributes.
-define internal fastcc i32 @callee_NoExtRet_fastcc(i32 %Arg) {
-  ret i32 %Arg
+declare void @ExtFun(ptr %FunPtr)
+define void @foo() {
+  call void @ExtFun(ptr @bar_Struct_32_addrtaken)
+  call void @ExtFun(ptr @fun_NoExtRet_i32_addrtaken)
+  ret void
+}
+
+; A function that is internal or has a non-C ABI is not checked for an
+; extension attribute.
+define void @caller_non_C_abi(ptr %fptr) {
+  call void @foo_internal(i32 0)
+  call fastcc void @foo_fastcc(i32 0)
+  call fastcc void %fptr(i32 0)
+  ret void
 }
 
-define void @caller_internal() {
-  call fastcc i32 @callee_NoExtRet_fastcc(i32 0)
+define internal void @foo_internal(i32 %Arg) {
   ret void
 }
+
+declare fastcc void @foo_fastcc(i32 %Arg)
+
+define internal i8 @fun_NoRetAttr_internal() {
+  ret i8 -1
+}
+
+define fastcc i8 @fun_NoRetAttr_fastcc() {
+  ret i8 -1
+}
diff --git a/llvm/test/CodeGen/SystemZ/args-15.ll 
b/llvm/test/CodeGen/SystemZ/args-15.ll
index 64217a2a29a6f9..6021a42c226a6b 100644
--- a/llvm/test/CodeGen/SystemZ/args-15.ll
+++ b/llvm/test/CodeGen/SystemZ/args-15.ll
@@ -8,6 +8,6 @@ define i32 @callee_MissingRetAttr() {
   ret i32 -1
 }
 
-; CHECK: ERROR: Missing extension attribute of returned value from function:
-; CHECK: i32 @callee_MissingRetAttr()
+; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Returning from function: i32 @callee_MissingRetAttr()
 ; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-16.ll 
b/llvm/test/CodeGen/SystemZ/args-16.ll
index 846100146e7908..ae75c00c7fd424 100644
--- a/llvm/test/CodeGen/SystemZ/args-16.ll
+++ b/llvm/test/CodeGen/SystemZ/args-16.ll
@@ -4,11 +4,17 @@
 ;
 ; Test detection of missing extension of an i16 return value.
 
-define i16 @callee_MissingRetAttr() {
+define internal i16 @callee_MissingRetAttr() {
   ret i16 -1
 }
 
-; CHECK: ERROR: Missing extension attribute of returned value from function:
-; CHECK: i16 @callee_MissingRetAttr()
+declare void @ExtFun(ptr %FunPtr)
+define void @foo() {
+  call void @ExtFun(ptr @callee_MissingRetAttr)
+  ret void
+}
+
+; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Returning from function: i16 @callee_MissingRetAttr()
 ; CHECK: UNREACHABLE executed
 
diff --git a/llvm/test/CodeGen/SystemZ/args-17.ll 
b/llvm/test/CodeGen/SystemZ/args-17.ll
index 4231d7e9e4772d..58a42c71fd1bc0 100644
--- a/llvm/test/CodeGen/SystemZ/args-17.ll
+++ b/llvm/test/CodeGen/SystemZ/args-17.ll
@@ -8,6 +8,6 @@ define i8 @callee_MissingRetAttr() {
   ret i8 -1
 }
 
-; CHECK: ERROR: Missing extension attribute of returned value from function:
-; CHECK: i8 @callee_MissingRetAttr()
+; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Returning from function: i8 @callee_MissingRetAttr()
 ; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-18.ll 
b/llvm/test/CodeGen/SystemZ/args-18.ll
index bd368fa056c6c9..8e828c0849d69d 100644
--- a/llvm/test/CodeGen/SystemZ/args-18.ll
+++ b/llvm/test/CodeGen/SystemZ/args-18.ll
@@ -11,6 +11,8 @@ define void @caller() {
 
 declare void @bar_Struct(i32 %Arg)
 
-; CHECK: ERROR: Missing extension attribute of passed value in call to 
function:
-; CHECK: Callee:  void @bar_Struct(i32)
-; CHECK: Caller:  void @caller()
+; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Callee: void @bar_Struct(i32)
+; CHECK: Caller: void @caller()
+; CHECK:         call void @bar_Struct(i32 123)
+; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-19.ll 
b/llvm/test/CodeGen/SystemZ/args-19.ll
index 8b5f421f59fdd8..48efda164ba6ec 100644
--- a/llvm/test/CodeGen/SystemZ/args-19.ll
+++ b/llvm/test/CodeGen/SystemZ/args-19.ll
@@ -9,8 +9,16 @@ define void @caller() {
   ret void
 }
 
-declare void @bar_Struct(i16 %Arg)
+define internal void @bar_Struct(i16 %Arg) { ret void }
 
-; CHECK: ERROR: Missing extension attribute of passed value in call to 
function:
-; CHECK: Callee:  void @bar_Struct(i16)
-; CHECK: Caller:  void @caller()
+declare void @ExtFun(ptr %FunPtr)
+define void @foo() {
+  call void @ExtFun(ptr @bar_Struct)
+  ret void
+}
+
+; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Callee: void @bar_Struct(i16)
+; CHECK: Caller: void @caller()
+; CHECK:         call void @bar_Struct(i16 123)
+; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-20.ll 
b/llvm/test/CodeGen/SystemZ/args-20.ll
index ed6f2e52bf6ee9..9868a2c256bc7c 100644
--- a/llvm/test/CodeGen/SystemZ/args-20.ll
+++ b/llvm/test/CodeGen/SystemZ/args-20.ll
@@ -11,6 +11,8 @@ define void @caller() {
 
 declare void @bar_Struct(i8 %Arg)
 
-; CHECK: ERROR: Missing extension attribute of passed value in call to 
function:
-; CHECK: Callee:  void @bar_Struct(i8)
-; CHECK: Caller:  void @caller()
+; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Callee: void @bar_Struct(i8)
+; CHECK: Caller: void @caller()
+; CHECK:         call void @bar_Struct(i8 123)
+; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll 
b/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
new file mode 100644
index 00000000000000..8ab28218b96d18
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
@@ -0,0 +1,19 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN:   | FileCheck %s
+; REQUIRES: asserts
+;
+; Test detection of a call making the wrong kind of extension.
+
+define i64 @fun(i32 signext %Arg) {
+  %S = sext i32 %Arg to i64
+  ret i64 %S
+}
+
+define i64 @foo(i32 %Arg) {
+  %res = call i64 @fun(i32 zeroext %Arg)
+  ret i64 %res
+}
+
+; CHECK: ERROR : SExt and ZExt are incompatible (arg 0).
+; CHECK: Callee: i64 @fun(i32 signext)
+; CHECK: Caller: i64 @foo(i32)
diff --git a/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll 
b/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll
new file mode 100644
index 00000000000000..ce24e4e7b64b18
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll
@@ -0,0 +1,19 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN:   | FileCheck %s
+; REQUIRES: asserts
+;
+; Test detection of a call making the wrong kind of extension.
+
+define internal i64 @fun(i32 zeroext %Arg) {
+  %S = zext i32 %Arg to i64
+  ret i64 %S
+}
+
+define i64 @foo(i32 %Arg) {
+  %res = call i64 @fun(i32 signext %Arg)
+  ret i64 %res
+}
+
+; CHECK: ERROR : SExt and ZExt are incompatible (arg 0).
+; CHECK: Callee: i64 @fun(i32 zeroext)
+; CHECK: Caller: i64 @foo(i32)
diff --git a/llvm/test/CodeGen/SystemZ/args-21.ll 
b/llvm/test/CodeGen/SystemZ/args-21.ll
deleted file mode 100644
index da5c8fe5ffc7fc..00000000000000
--- a/llvm/test/CodeGen/SystemZ/args-21.ll
+++ /dev/null
@@ -1,21 +0,0 @@
-; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
-; RUN:   | FileCheck %s
-; REQUIRES: asserts
-;
-; Test detection of missing extension involving an internal function which is
-; passed as a function pointer to an external function.
-
-define internal i32 @bar(i32 %Arg) {
-  ret i32 %Arg
-}
-
-declare void @ExtFun(ptr %FunPtr);
-
-define void @foo() {
-  call void @ExtFun(ptr @bar)
-  ret void
-}
-
-; CHECK: ERROR: Missing extension attribute of returned value from function:
-; CHECK: i32 @bar(i32)
-; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-24.ll 
b/llvm/test/CodeGen/SystemZ/args-24.ll
new file mode 100644
index 00000000000000..44e3593ad5b056
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-24.ll
@@ -0,0 +1,95 @@
+; RUN: llc < %s -mtriple=s390x-linux-gnu -argext-abi-check
+; REQUIRES: asserts
+;
+; The parameter attributes should match between the call and Function
+; declaration as seen by the instruction selector. One of the attributes
+; should be present with a normal C-ABI call, but internal/non-C calls can
+; also omit the attribute. This seems to work so that the call gets the
+; sign/zero extension attribute if the callee prototype has it even if it was
+; omitted on the call IR instruction.
+
+define void @caller(i32 %Arg32) {
+  ; C Calling Convention
+  call void @bar_should_NoExt(i32 %Arg32)
+  call void @bar_should_NoExt(i32 noext %Arg32)
+  call void @bar_should_NoExt(i32 signext %Arg32)
+  call void @bar_should_NoExt(i32 zeroext %Arg32)
+  call void @bar_should_SExt(i32 %Arg32)
+  call void @bar_should_SExt(i32 noext %Arg32)
+  call void @bar_should_SExt(i32 signext %Arg32)
+  call void @bar_should_ZExt(i32 %Arg32)
+  call void @bar_should_ZExt(i32 noext %Arg32)
+  call void @bar_should_ZExt(i32 zeroext %Arg32)
+
+  ; Internal callee but address taken.
+  call void @bar_should_NoExt_addrtaken(i32 %Arg32)
+  call void @bar_should_NoExt_addrtaken(i32 noext %Arg32)
+  call void @bar_should_NoExt_addrtaken(i32 signext %Arg32)
+  call void @bar_should_NoExt_addrtaken(i32 zeroext %Arg32)
+  call void @bar_should_SExt_addrtaken(i32 %Arg32)
+  call void @bar_should_SExt_addrtaken(i32 noext %Arg32)
+  call void @bar_should_SExt_addrtaken(i32 signext %Arg32)
+  call void @bar_should_ZExt_addrtaken(i32 %Arg32)
+  call void @bar_should_ZExt_addrtaken(i32 noext %Arg32)
+  call void @bar_should_ZExt_addrtaken(i32 zeroext %Arg32)
+
+  ; Internal callee: No extension is ok.
+  call void @bar_internal(i32 %Arg32)
+  call void @bar_internal(i32 noext %Arg32)
+  call void @bar_internal(i32 signext %Arg32)
+  call void @bar_internal(i32 zeroext %Arg32)
+  call void @bar_should_NoExt_internal(i32 %Arg32)
+  call void @bar_should_NoExt_internal(i32 noext %Arg32)
+  call void @bar_should_NoExt_internal(i32 signext %Arg32)
+  call void @bar_should_NoExt_internal(i32 zeroext %Arg32)
+  call void @bar_should_SExt_internal(i32 %Arg32)
+  call void @bar_should_SExt_internal(i32 noext %Arg32)
+  call void @bar_should_SExt_internal(i32 signext %Arg32)
+  call void @bar_should_ZExt_internal(i32 %Arg32)
+  call void @bar_should_ZExt_internal(i32 noext %Arg32)
+  call void @bar_should_ZExt_internal(i32 zeroext %Arg32)
+
+  ; Same with a fastcc: No extension is ok.
+  call fastcc void @bar_fastcc(i32 %Arg32)
+  call fastcc void @bar_fastcc(i32 noext %Arg32)
+  call fastcc void @bar_fastcc(i32 signext %Arg32)
+  call fastcc void @bar_fastcc(i32 zeroext %Arg32)
+  call fastcc void @bar_should_NoExt_fastcc(i32 %Arg32)
+  call fastcc void @bar_should_NoExt_fastcc(i32 noext %Arg32)
+  call fastcc void @bar_should_NoExt_fastcc(i32 signext %Arg32)
+  call fastcc void @bar_should_NoExt_fastcc(i32 zeroext %Arg32)
+  call fastcc void @bar_should_SExt_fastcc(i32 %Arg32)
+  call fastcc void @bar_should_SExt_fastcc(i32 noext %Arg32)
+  call fastcc void @bar_should_SExt_fastcc(i32 signext %Arg32)
+  call fastcc void @bar_should_ZExt_fastcc(i32 %Arg32)
+  call fastcc void @bar_should_ZExt_fastcc(i32 noext %Arg32)
+  call fastcc void @bar_should_ZExt_fastcc(i32 zeroext %Arg32)
+
+  ret void
+}
+
+declare void @bar_should_NoExt(i32 noext %Arg32)
+declare void @bar_should_SExt(i32 signext %Arg32)
+declare void @bar_should_ZExt(i32 zeroext %Arg32)
+
+define internal void @bar_should_NoExt_addrtaken(i32 noext %Arg32) { ret void }
+define internal void @bar_should_SExt_addrtaken(i32 signext %Arg32) { ret void 
}
+define internal void @bar_should_ZExt_addrtaken(i32 zeroext %Arg32) { ret void 
}
+
+define internal void @bar_internal(i32 %Arg32) { ret void }
+define internal void @bar_should_NoExt_internal(i32 noext %Arg32) { ret void }
+define internal void @bar_should_SExt_internal(i32 signext %Arg32) { ret void }
+define internal void @bar_should_ZExt_internal(i32 zeroext %Arg32) { ret void }
+
+declare fastcc void @bar_fastcc(i32 %Arg32)
+declare fastcc void @bar_should_NoExt_fastcc(i32 noext %Arg32)
+declare fastcc void @bar_should_SExt_fastcc(i32 signext %Arg32)
+declare fastcc void @bar_should_ZExt_fastcc(i32 zeroext %Arg32)
+
+declare void @ExtFun(ptr %FunPtr)
+define void @foo() {
+  call void @ExtFun(ptr @bar_should_NoExt_addrtaken)
+  call void @ExtFun(ptr @bar_should_SExt_addrtaken)
+  call void @ExtFun(ptr @bar_should_ZExt_addrtaken)
+  ret void
+}
diff --git a/llvm/test/CodeGen/SystemZ/args-25.ll 
b/llvm/test/CodeGen/SystemZ/args-25.ll
new file mode 100644
index 00000000000000..ab5351ff3ebfe1
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-25.ll
@@ -0,0 +1,31 @@
+; RUN: llc < %s -mtriple=s390x-linux-gnu -argext-abi-check
+; REQUIRES: asserts
+;
+; Test that the lowering of returns as seen by the instruction selector works
+; in accordance to the function header.
+
+define noext i32 @fun_NoExtRet_ccc() { ret i32 0 }
+define signext i32 @fun_SignExtRet_ccc() { ret i32 0 }
+define zeroext i32 @fun_ZeroExtRet_ccc() { ret i32 0 }
+
+define internal noext i32 @fun_NoExtRet_addrtaken() { ret i32 0 }
+define internal signext i32 @fun_SignExtRet_addrtaken() { ret i32 0 }
+define internal zeroext i32 @fun_ZeroExtRet_addrtaken() { ret i32 0 }
+
+declare void @ExtFun(ptr %FunPtr)
+define void @foo() {
+  call void @ExtFun(ptr @fun_NoExtRet_addrtaken)
+  call void @ExtFun(ptr @fun_SignExtRet_addrtaken)
+  call void @ExtFun(ptr @fun_ZeroExtRet_addrtaken)
+  ret void
+}
+
+define internal i32 @fun_internal() { ret i32 0 }
+define internal noext i32 @fun_NoExtRet_internal() { ret i32 0 }
+define internal signext i32 @fun_SignExtRet_internal() { ret i32 0 }
+define internal zeroext i32 @fun_ZeroExtRet_internal() { ret i32 0 }
+
+define fastcc i32 @fun_fastcc() { ret i32 0 }
+define internal noext i32 @fun_NoExtRet_fastcc() { ret i32 0 }
+define internal signext i32 @fun_SignExtRet_fastcc() { ret i32 0 }
+define internal zeroext i32 @fun_ZeroExtRet_fastcc() { ret i32 0 }
diff --git a/llvm/test/CodeGen/SystemZ/args-26.ll 
b/llvm/test/CodeGen/SystemZ/args-26.ll
new file mode 100644
index 00000000000000..e78a020bd184af
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-26.ll
@@ -0,0 +1,20 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN:   | FileCheck %s
+; REQUIRES: asserts
+;
+; Test varargs: call with wrong extension type on a fixed argument.
+
+define i64 @caller(i32 %Arg) {
+  %res = call i64 @bar(i32 signext %Arg, i32 zeroext 0)
+  ret i64 %res
+}
+
+define i64 @bar(i32 zeroext %Arg, ...) {
+  %S = zext i32 %Arg to i64
+  ret i64 %S
+}
+
+; CHECK: ERROR : Missing ZExt on arg 0.
+; CHECK: Callee: i64 @bar(i32 zeroext, ...)
+; CHECK: Caller: i64 @caller(i32)
+; CHECK:         %res = call i64 @bar(i32 signext %Arg, i32 zeroext 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-27.ll 
b/llvm/test/CodeGen/SystemZ/args-27.ll
new file mode 100644
index 00000000000000..e37b2ad3e96aa9
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-27.ll
@@ -0,0 +1,20 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN:   | FileCheck %s
+; REQUIRES: asserts
+;
+; Test varargs: call with missing extension type on a fixed argument.
+
+define i64 @caller(i32 %Arg) {
+  %res = call i64 @bar(i32 %Arg, i32 zeroext 0)
+  ret i64 %res
+}
+
+define i64 @bar(i32 zeroext %Arg, ...) {
+  %S = zext i32 %Arg to i64
+  ret i64 %S
+}
+
+; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Callee: i64 @bar(i32 zeroext, ...)
+; CHECK: Caller: i64 @caller(i32)
+; CHECK:         %res = call i64 @bar(i32 %Arg, i32 zeroext 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-28.ll 
b/llvm/test/CodeGen/SystemZ/args-28.ll
new file mode 100644
index 00000000000000..128f993624fb50
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-28.ll
@@ -0,0 +1,20 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN:   | FileCheck %s
+; REQUIRES: asserts
+;
+; Test varargs: call with missing extension type on a vararg.
+
+define i64 @caller(i32 %Arg) {
+  %res = call i64 @bar(i32 zeroext %Arg, i32 0)
+  ret i64 %res
+}
+
+define i64 @bar(i32 zeroext %Arg, ...) {
+  %S = zext i32 %Arg to i64
+  ret i64 %S
+}
+
+; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 1.
+; CHECK: Callee: i64 @bar(i32 zeroext, ...)
+; CHECK: Caller: i64 @caller(i32)
+; CHECK:         %res = call i64 @bar(i32 zeroext %Arg, i32 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-29.ll 
b/llvm/test/CodeGen/SystemZ/args-29.ll
new file mode 100644
index 00000000000000..f164ec34e3d622
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-29.ll
@@ -0,0 +1,21 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN:   | FileCheck %s
+; REQUIRES: asserts
+;
+; Test varargs: call with the wrong extension kind on an argument, and also
+; test that the split i128 arg (z10) does not mess things up.
+
+define i64 @caller(i32 %Arg) {
+  %res = call i64 @bar(i32 noext %Arg, i128 0, i32 signext %Arg)
+  ret i64 %res
+}
+
+define i64 @bar(i32 noext %A0, i128 %A1, i32 zeroext %A2, ...) {
+  %S = zext i32 %A2 to i64
+  ret i64 %S
+}
+
+; CHECK: ERROR : Missing ZExt on arg 2.
+; CHECK: Callee: i64 @bar(i32 noext, i128, i32 zeroext, ...)
+; CHECK: Caller: i64 @caller(i32)
+; CHECK:         %res = call i64 @bar(i32 noext %Arg, i128 0, i32 signext %Arg)
diff --git a/llvm/test/CodeGen/SystemZ/args-30.ll 
b/llvm/test/CodeGen/SystemZ/args-30.ll
new file mode 100644
index 00000000000000..c9949e4282c2ac
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/args-30.ll
@@ -0,0 +1,16 @@
+; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
+; RUN:   | FileCheck %s
+; REQUIRES: asserts
+;
+; Test an indirect call: even without the function prototype we can check that
+; a C ABI call has some kind of extension.
+
+define void @caller(ptr %fptr) {
+  call void %fptr(i32 0)
+  ret void
+}
+
+; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: Callee: -
+; CHECK: Caller: void @caller(ptr)
+; CHECK:         call void %fptr(i32 0)

>From 9877f2aa2dda43abb040544cf62b5093af7f30ba Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <[email protected]>
Date: Fri, 9 Oct 2026 18:59:44 +0200
Subject: [PATCH 07/10] Remove check against SExt+ZExt for now.

---
 .../Target/SystemZ/SystemZISelLowering.cpp    |  7 -------
 .../test/CodeGen/SystemZ/args-21-SExt-ZExt.ll | 19 -------------------
 .../test/CodeGen/SystemZ/args-21-ZExt-SExt.ll | 19 -------------------
 3 files changed, 45 deletions(-)
 delete mode 100644 llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
 delete mode 100644 llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll

diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 6da70c60d20cc3..986831da3e2d7a 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11615,13 +11615,6 @@ bool SystemZTargetLowering::verifyNarrowIntegerArgs(
         return false;
       }
     }
-
-    // Flags should not end up with both kinds of extensions.
-    if (Flags.isSExt() && Flags.isZExt()) {
-      errs() << "ERROR : SExt and ZExt are incompatible (arg " << OrigIdx
-             << ").\n";
-      return false;
-    }
   }
 
   return true;
diff --git a/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll 
b/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
deleted file mode 100644
index 8ab28218b96d18..00000000000000
--- a/llvm/test/CodeGen/SystemZ/args-21-SExt-ZExt.ll
+++ /dev/null
@@ -1,19 +0,0 @@
-; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
-; RUN:   | FileCheck %s
-; REQUIRES: asserts
-;
-; Test detection of a call making the wrong kind of extension.
-
-define i64 @fun(i32 signext %Arg) {
-  %S = sext i32 %Arg to i64
-  ret i64 %S
-}
-
-define i64 @foo(i32 %Arg) {
-  %res = call i64 @fun(i32 zeroext %Arg)
-  ret i64 %res
-}
-
-; CHECK: ERROR : SExt and ZExt are incompatible (arg 0).
-; CHECK: Callee: i64 @fun(i32 signext)
-; CHECK: Caller: i64 @foo(i32)
diff --git a/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll 
b/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll
deleted file mode 100644
index ce24e4e7b64b18..00000000000000
--- a/llvm/test/CodeGen/SystemZ/args-21-ZExt-SExt.ll
+++ /dev/null
@@ -1,19 +0,0 @@
-; RUN: not --crash llc < %s -mtriple=s390x-linux-gnu -argext-abi-check 2>&1 \
-; RUN:   | FileCheck %s
-; REQUIRES: asserts
-;
-; Test detection of a call making the wrong kind of extension.
-
-define internal i64 @fun(i32 zeroext %Arg) {
-  %S = zext i32 %Arg to i64
-  ret i64 %S
-}
-
-define i64 @foo(i32 %Arg) {
-  %res = call i64 @fun(i32 signext %Arg)
-  ret i64 %res
-}
-
-; CHECK: ERROR : SExt and ZExt are incompatible (arg 0).
-; CHECK: Callee: i64 @fun(i32 zeroext)
-; CHECK: Caller: i64 @foo(i32)

>From 0a4507724823449ffa16952d39b5137067cf022f Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <[email protected]>
Date: Fri, 9 Oct 2026 16:32:59 -0700
Subject: [PATCH 08/10] Rename test.

---
 llvm/test/CodeGen/SystemZ/{args-30.ll => args-21.ll} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename llvm/test/CodeGen/SystemZ/{args-30.ll => args-21.ll} (100%)

diff --git a/llvm/test/CodeGen/SystemZ/args-30.ll 
b/llvm/test/CodeGen/SystemZ/args-21.ll
similarity index 100%
rename from llvm/test/CodeGen/SystemZ/args-30.ll
rename to llvm/test/CodeGen/SystemZ/args-21.ll

>From ba7f6628ff2be0e581c80635af8aa2f52b0a0721 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <[email protected]>
Date: Tue, 13 Oct 2026 23:26:50 +0200
Subject: [PATCH 09/10] Updated per review.

---
 llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 10 +++++-----
 llvm/test/CodeGen/SystemZ/args-15.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-16.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-17.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-18.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-19.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-20.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-21.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-27.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-28.ll            |  2 +-
 10 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 986831da3e2d7a..9521f879f433a4 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11542,11 +11542,8 @@ void 
SystemZTargetLowering::verifyNarrowIntegerArgs_Call(
   bool IsInternal = false;
   const Function *CalleeFn = nullptr;
   if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
-    if ((CalleeFn = dyn_cast<Function>(G->getGlobal()))) {
+    if ((CalleeFn = dyn_cast<Function>(G->getGlobal())))
       IsInternal = isInternal(CalleeFn);
-      assert(CalleeFn->getCallingConv() == CLI.CallConv &&
-             "Wrong calling convention used.");
-    }
   bool C_ABI = CLI.CallConv == CallingConv::C && !IsInternal;
   if (!verifyNarrowIntegerArgs(C_ABI, Outs, CalleeFn, /*IsRet=*/false)) {
     errs() << "Callee: ";
@@ -11586,6 +11583,9 @@ void SystemZTargetLowering::verifyNarrowIntegerArgs_Ret(
 bool SystemZTargetLowering::verifyNarrowIntegerArgs(
     bool C_ABI, const SmallVectorImpl<ISD::OutputArg> &Outs,
     const Function *FunHeader, bool IsRet) const {
+  if (IsRet && Outs.size() != 1)
+    return true;
+
   for (unsigned i = 0; i < Outs.size(); ++i) {
     EVT OrigArgVT = Outs[i].ArgVT;
     if (!OrigArgVT.isInteger() || OrigArgVT.getSizeInBits() >= 64)
@@ -11596,7 +11596,7 @@ bool SystemZTargetLowering::verifyNarrowIntegerArgs(
 
     // Per the C ABI there must be an extension.
     if (C_ABI && !Flags.isSExt() && !Flags.isZExt() && !Flags.isNoExt()) {
-      errs() << "ERROR:  (C ABI violiation) missing extension attribute on arg 
"
+      errs() << "ERROR:  (C ABI violation) missing extension attribute on arg "
              << OrigIdx << ".\n";
       return false;
     }
diff --git a/llvm/test/CodeGen/SystemZ/args-15.ll 
b/llvm/test/CodeGen/SystemZ/args-15.ll
index 6021a42c226a6b..89273057b3345a 100644
--- a/llvm/test/CodeGen/SystemZ/args-15.ll
+++ b/llvm/test/CodeGen/SystemZ/args-15.ll
@@ -8,6 +8,6 @@ define i32 @callee_MissingRetAttr() {
   ret i32 -1
 }
 
-; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Returning from function: i32 @callee_MissingRetAttr()
 ; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-16.ll 
b/llvm/test/CodeGen/SystemZ/args-16.ll
index ae75c00c7fd424..bbc15904aaff16 100644
--- a/llvm/test/CodeGen/SystemZ/args-16.ll
+++ b/llvm/test/CodeGen/SystemZ/args-16.ll
@@ -14,7 +14,7 @@ define void @foo() {
   ret void
 }
 
-; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Returning from function: i16 @callee_MissingRetAttr()
 ; CHECK: UNREACHABLE executed
 
diff --git a/llvm/test/CodeGen/SystemZ/args-17.ll 
b/llvm/test/CodeGen/SystemZ/args-17.ll
index 58a42c71fd1bc0..69b913ca34b531 100644
--- a/llvm/test/CodeGen/SystemZ/args-17.ll
+++ b/llvm/test/CodeGen/SystemZ/args-17.ll
@@ -8,6 +8,6 @@ define i8 @callee_MissingRetAttr() {
   ret i8 -1
 }
 
-; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Returning from function: i8 @callee_MissingRetAttr()
 ; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-18.ll 
b/llvm/test/CodeGen/SystemZ/args-18.ll
index 8e828c0849d69d..070f63b3da2ed4 100644
--- a/llvm/test/CodeGen/SystemZ/args-18.ll
+++ b/llvm/test/CodeGen/SystemZ/args-18.ll
@@ -11,7 +11,7 @@ define void @caller() {
 
 declare void @bar_Struct(i32 %Arg)
 
-; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Callee: void @bar_Struct(i32)
 ; CHECK: Caller: void @caller()
 ; CHECK:         call void @bar_Struct(i32 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-19.ll 
b/llvm/test/CodeGen/SystemZ/args-19.ll
index 48efda164ba6ec..2c666336c44114 100644
--- a/llvm/test/CodeGen/SystemZ/args-19.ll
+++ b/llvm/test/CodeGen/SystemZ/args-19.ll
@@ -17,7 +17,7 @@ define void @foo() {
   ret void
 }
 
-; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Callee: void @bar_Struct(i16)
 ; CHECK: Caller: void @caller()
 ; CHECK:         call void @bar_Struct(i16 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-20.ll 
b/llvm/test/CodeGen/SystemZ/args-20.ll
index 9868a2c256bc7c..a7d0f333530eb5 100644
--- a/llvm/test/CodeGen/SystemZ/args-20.ll
+++ b/llvm/test/CodeGen/SystemZ/args-20.ll
@@ -11,7 +11,7 @@ define void @caller() {
 
 declare void @bar_Struct(i8 %Arg)
 
-; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Callee: void @bar_Struct(i8)
 ; CHECK: Caller: void @caller()
 ; CHECK:         call void @bar_Struct(i8 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-21.ll 
b/llvm/test/CodeGen/SystemZ/args-21.ll
index c9949e4282c2ac..a5cc0cb8afeff6 100644
--- a/llvm/test/CodeGen/SystemZ/args-21.ll
+++ b/llvm/test/CodeGen/SystemZ/args-21.ll
@@ -10,7 +10,7 @@ define void @caller(ptr %fptr) {
   ret void
 }
 
-; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Callee: -
 ; CHECK: Caller: void @caller(ptr)
 ; CHECK:         call void %fptr(i32 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-27.ll 
b/llvm/test/CodeGen/SystemZ/args-27.ll
index e37b2ad3e96aa9..2a1b83a570ada7 100644
--- a/llvm/test/CodeGen/SystemZ/args-27.ll
+++ b/llvm/test/CodeGen/SystemZ/args-27.ll
@@ -14,7 +14,7 @@ define i64 @bar(i32 zeroext %Arg, ...) {
   ret i64 %S
 }
 
-; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 0.
+; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Callee: i64 @bar(i32 zeroext, ...)
 ; CHECK: Caller: i64 @caller(i32)
 ; CHECK:         %res = call i64 @bar(i32 %Arg, i32 zeroext 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-28.ll 
b/llvm/test/CodeGen/SystemZ/args-28.ll
index 128f993624fb50..8cf803effc5f58 100644
--- a/llvm/test/CodeGen/SystemZ/args-28.ll
+++ b/llvm/test/CodeGen/SystemZ/args-28.ll
@@ -14,7 +14,7 @@ define i64 @bar(i32 zeroext %Arg, ...) {
   ret i64 %S
 }
 
-; CHECK: ERROR:  (C ABI violiation) missing extension attribute on arg 1.
+; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 1.
 ; CHECK: Callee: i64 @bar(i32 zeroext, ...)
 ; CHECK: Caller: i64 @caller(i32)
 ; CHECK:         %res = call i64 @bar(i32 zeroext %Arg, i32 0)

>From 0c7b3e7ec0eb23132e4562e9478fd609e99af168 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <[email protected]>
Date: Wed, 14 Oct 2026 20:13:10 +0200
Subject: [PATCH 10/10] Fix diagnostic messages.

---
 llvm/lib/Target/SystemZ/SystemZISelLowering.cpp |  9 +++++----
 llvm/test/CodeGen/SystemZ/args-15.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-16.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-17.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-18.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-19.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-20.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-21.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-26.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-27.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-28.ll            |  2 +-
 llvm/test/CodeGen/SystemZ/args-29.ll            | 10 +++++-----
 12 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp 
b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 9521f879f433a4..dc0f412cccbd32 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -11596,8 +11596,9 @@ bool SystemZTargetLowering::verifyNarrowIntegerArgs(
 
     // Per the C ABI there must be an extension.
     if (C_ABI && !Flags.isSExt() && !Flags.isZExt() && !Flags.isNoExt()) {
-      errs() << "ERROR:  (C ABI violation) missing extension attribute on arg "
-             << OrigIdx << ".\n";
+      errs() << "ERROR: (C ABI violation) missing extension attribute on "
+             << (IsRet ? "return value" : Twine("arg ") + Twine(OrigIdx))
+             << ".\n";
       return false;
     }
 
@@ -11607,11 +11608,11 @@ bool SystemZTargetLowering::verifyNarrowIntegerArgs(
       const AttributeSet Attrs =
           IsRet ? FunAttrs.getRetAttrs() : FunAttrs.getParamAttrs(OrigIdx);
       if (Attrs.hasAttribute(Attribute::SExt) && !Flags.isSExt()) {
-        errs() << "ERROR : Missing SExt on arg " << OrigIdx << ".\n";
+        errs() << "ERROR: Missing SExt on arg " << OrigIdx << ".\n";
         return false;
       }
       if (Attrs.hasAttribute(Attribute::ZExt) && !Flags.isZExt()) {
-        errs() << "ERROR : Missing ZExt on arg " << OrigIdx << ".\n";
+        errs() << "ERROR: Missing ZExt on arg " << OrigIdx << ".\n";
         return false;
       }
     }
diff --git a/llvm/test/CodeGen/SystemZ/args-15.ll 
b/llvm/test/CodeGen/SystemZ/args-15.ll
index 89273057b3345a..6e69f9ef5ac813 100644
--- a/llvm/test/CodeGen/SystemZ/args-15.ll
+++ b/llvm/test/CodeGen/SystemZ/args-15.ll
@@ -8,6 +8,6 @@ define i32 @callee_MissingRetAttr() {
   ret i32 -1
 }
 
-; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on return value.
 ; CHECK: Returning from function: i32 @callee_MissingRetAttr()
 ; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-16.ll 
b/llvm/test/CodeGen/SystemZ/args-16.ll
index bbc15904aaff16..c2c4e88a3bfcd9 100644
--- a/llvm/test/CodeGen/SystemZ/args-16.ll
+++ b/llvm/test/CodeGen/SystemZ/args-16.ll
@@ -14,7 +14,7 @@ define void @foo() {
   ret void
 }
 
-; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on return value.
 ; CHECK: Returning from function: i16 @callee_MissingRetAttr()
 ; CHECK: UNREACHABLE executed
 
diff --git a/llvm/test/CodeGen/SystemZ/args-17.ll 
b/llvm/test/CodeGen/SystemZ/args-17.ll
index 69b913ca34b531..e0759f126ee528 100644
--- a/llvm/test/CodeGen/SystemZ/args-17.ll
+++ b/llvm/test/CodeGen/SystemZ/args-17.ll
@@ -8,6 +8,6 @@ define i8 @callee_MissingRetAttr() {
   ret i8 -1
 }
 
-; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on return value.
 ; CHECK: Returning from function: i8 @callee_MissingRetAttr()
 ; CHECK: UNREACHABLE executed
diff --git a/llvm/test/CodeGen/SystemZ/args-18.ll 
b/llvm/test/CodeGen/SystemZ/args-18.ll
index 070f63b3da2ed4..f166130121d6a9 100644
--- a/llvm/test/CodeGen/SystemZ/args-18.ll
+++ b/llvm/test/CodeGen/SystemZ/args-18.ll
@@ -11,7 +11,7 @@ define void @caller() {
 
 declare void @bar_Struct(i32 %Arg)
 
-; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Callee: void @bar_Struct(i32)
 ; CHECK: Caller: void @caller()
 ; CHECK:         call void @bar_Struct(i32 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-19.ll 
b/llvm/test/CodeGen/SystemZ/args-19.ll
index 2c666336c44114..7f1ac319700761 100644
--- a/llvm/test/CodeGen/SystemZ/args-19.ll
+++ b/llvm/test/CodeGen/SystemZ/args-19.ll
@@ -17,7 +17,7 @@ define void @foo() {
   ret void
 }
 
-; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Callee: void @bar_Struct(i16)
 ; CHECK: Caller: void @caller()
 ; CHECK:         call void @bar_Struct(i16 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-20.ll 
b/llvm/test/CodeGen/SystemZ/args-20.ll
index a7d0f333530eb5..fa631f535d1d5d 100644
--- a/llvm/test/CodeGen/SystemZ/args-20.ll
+++ b/llvm/test/CodeGen/SystemZ/args-20.ll
@@ -11,7 +11,7 @@ define void @caller() {
 
 declare void @bar_Struct(i8 %Arg)
 
-; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Callee: void @bar_Struct(i8)
 ; CHECK: Caller: void @caller()
 ; CHECK:         call void @bar_Struct(i8 123)
diff --git a/llvm/test/CodeGen/SystemZ/args-21.ll 
b/llvm/test/CodeGen/SystemZ/args-21.ll
index a5cc0cb8afeff6..c4892dc420fd07 100644
--- a/llvm/test/CodeGen/SystemZ/args-21.ll
+++ b/llvm/test/CodeGen/SystemZ/args-21.ll
@@ -10,7 +10,7 @@ define void @caller(ptr %fptr) {
   ret void
 }
 
-; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Callee: -
 ; CHECK: Caller: void @caller(ptr)
 ; CHECK:         call void %fptr(i32 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-26.ll 
b/llvm/test/CodeGen/SystemZ/args-26.ll
index e78a020bd184af..31b35413c2fe0d 100644
--- a/llvm/test/CodeGen/SystemZ/args-26.ll
+++ b/llvm/test/CodeGen/SystemZ/args-26.ll
@@ -14,7 +14,7 @@ define i64 @bar(i32 zeroext %Arg, ...) {
   ret i64 %S
 }
 
-; CHECK: ERROR : Missing ZExt on arg 0.
+; CHECK: ERROR: Missing ZExt on arg 0.
 ; CHECK: Callee: i64 @bar(i32 zeroext, ...)
 ; CHECK: Caller: i64 @caller(i32)
 ; CHECK:         %res = call i64 @bar(i32 signext %Arg, i32 zeroext 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-27.ll 
b/llvm/test/CodeGen/SystemZ/args-27.ll
index 2a1b83a570ada7..78ea8f53054f88 100644
--- a/llvm/test/CodeGen/SystemZ/args-27.ll
+++ b/llvm/test/CodeGen/SystemZ/args-27.ll
@@ -14,7 +14,7 @@ define i64 @bar(i32 zeroext %Arg, ...) {
   ret i64 %S
 }
 
-; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 0.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 0.
 ; CHECK: Callee: i64 @bar(i32 zeroext, ...)
 ; CHECK: Caller: i64 @caller(i32)
 ; CHECK:         %res = call i64 @bar(i32 %Arg, i32 zeroext 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-28.ll 
b/llvm/test/CodeGen/SystemZ/args-28.ll
index 8cf803effc5f58..3999c46886cbb7 100644
--- a/llvm/test/CodeGen/SystemZ/args-28.ll
+++ b/llvm/test/CodeGen/SystemZ/args-28.ll
@@ -14,7 +14,7 @@ define i64 @bar(i32 zeroext %Arg, ...) {
   ret i64 %S
 }
 
-; CHECK: ERROR:  (C ABI violation) missing extension attribute on arg 1.
+; CHECK: ERROR: (C ABI violation) missing extension attribute on arg 1.
 ; CHECK: Callee: i64 @bar(i32 zeroext, ...)
 ; CHECK: Caller: i64 @caller(i32)
 ; CHECK:         %res = call i64 @bar(i32 zeroext %Arg, i32 0)
diff --git a/llvm/test/CodeGen/SystemZ/args-29.ll 
b/llvm/test/CodeGen/SystemZ/args-29.ll
index f164ec34e3d622..ef0a8030187b0f 100644
--- a/llvm/test/CodeGen/SystemZ/args-29.ll
+++ b/llvm/test/CodeGen/SystemZ/args-29.ll
@@ -6,16 +6,16 @@
 ; test that the split i128 arg (z10) does not mess things up.
 
 define i64 @caller(i32 %Arg) {
-  %res = call i64 @bar(i32 noext %Arg, i128 0, i32 signext %Arg)
+  %res = call i64 @bar(i32 noext %Arg, i128 0, i32 zeroext %Arg)
   ret i64 %res
 }
 
-define i64 @bar(i32 noext %A0, i128 %A1, i32 zeroext %A2, ...) {
+define i64 @bar(i32 noext %A0, i128 %A1, i32 signext %A2, ...) {
   %S = zext i32 %A2 to i64
   ret i64 %S
 }
 
-; CHECK: ERROR : Missing ZExt on arg 2.
-; CHECK: Callee: i64 @bar(i32 noext, i128, i32 zeroext, ...)
+; CHECK: ERROR: Missing SExt on arg 2.
+; CHECK: Callee: i64 @bar(i32 noext, i128, i32 signext, ...)
 ; CHECK: Caller: i64 @caller(i32)
-; CHECK:         %res = call i64 @bar(i32 noext %Arg, i128 0, i32 signext %Arg)
+; CHECK:         %res = call i64 @bar(i32 noext %Arg, i128 0, i32 zeroext %Arg)

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

Reply via email to