https://github.com/maryammo updated 
https://github.com/llvm/llvm-project/pull/202362

>From c09ba98ee90f1e74e7744d3e9719823bf80d9b02 Mon Sep 17 00:00:00 2001
From: Maryam Moghadas <[email protected]>
Date: Fri, 5 Jun 2026 20:18:38 +0000
Subject: [PATCH] [z/OS][Clang]  Add compare and swap builtin functions

---
 clang/include/clang/Basic/BuiltinsZOS.td      | 27 +++++++
 clang/include/clang/Basic/CMakeLists.txt      |  4 ++
 clang/include/clang/Basic/TargetBuiltins.h    | 13 ++--
 clang/lib/Basic/Targets/SystemZ.cpp           | 22 +++++-
 clang/lib/CodeGen/TargetBuiltins/SystemZ.cpp  | 71 +++++++++++++++++--
 .../test/CodeGen/SystemZ/builtins-zos-cds1.c  | 18 +++++
 .../test/CodeGen/SystemZ/builtins-zos-cdsg.c  | 19 +++++
 clang/test/CodeGen/SystemZ/builtins-zos-cs.c  | 12 ++++
 clang/test/CodeGen/SystemZ/builtins-zos-cs1.c | 12 ++++
 clang/test/CodeGen/SystemZ/builtins-zos-csg.c | 17 +++++
 10 files changed, 206 insertions(+), 9 deletions(-)
 create mode 100644 clang/include/clang/Basic/BuiltinsZOS.td
 create mode 100644 clang/test/CodeGen/SystemZ/builtins-zos-cds1.c
 create mode 100644 clang/test/CodeGen/SystemZ/builtins-zos-cdsg.c
 create mode 100644 clang/test/CodeGen/SystemZ/builtins-zos-cs.c
 create mode 100644 clang/test/CodeGen/SystemZ/builtins-zos-cs1.c
 create mode 100644 clang/test/CodeGen/SystemZ/builtins-zos-csg.c

diff --git a/clang/include/clang/Basic/BuiltinsZOS.td 
b/clang/include/clang/Basic/BuiltinsZOS.td
new file mode 100644
index 0000000000000..2089518fd18a8
--- /dev/null
+++ b/clang/include/clang/Basic/BuiltinsZOS.td
@@ -0,0 +1,27 @@
+//===-- BuiltinsZOS.td - z/OS Builtin function database ---------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the z/OS-specific builtin function database.
+//
+//===----------------------------------------------------------------------===//
+
+include "clang/Basic/BuiltinsBase.td"
+
+class SystemZNoPrefixBuiltin<string prototype> : Builtin {
+  let Spellings = [NAME];
+  let Prototype = prototype;
+}
+
+// compare and swap functions
+let Attributes = [NoThrow] in {
+  def __cs : SystemZNoPrefixBuiltin<"int(unsigned int *, unsigned int *, 
unsigned int)">;
+  def __cs1 : SystemZNoPrefixBuiltin<"int(void *, void *, void *)">;
+  def __csg : SystemZNoPrefixBuiltin<"int(void *, void *, void *)">;
+  def __cds1 : SystemZNoPrefixBuiltin<"int(void *, void *, void *)">;
+  def __cdsg : SystemZNoPrefixBuiltin<"int(void *, void *, void *)">;
+}
diff --git a/clang/include/clang/Basic/CMakeLists.txt 
b/clang/include/clang/Basic/CMakeLists.txt
index 20172622ca424..41e18b0c6cf53 100644
--- a/clang/include/clang/Basic/CMakeLists.txt
+++ b/clang/include/clang/Basic/CMakeLists.txt
@@ -146,6 +146,10 @@ clang_tablegen(BuiltinsX86_64.inc -gen-clang-builtins
   SOURCE BuiltinsX86_64.td
   TARGET ClangBuiltinsX86_64)
 
+clang_tablegen(BuiltinsZOS.inc -gen-clang-builtins
+  SOURCE BuiltinsZOS.td
+  TARGET ClangBuiltinsZOS)
+
 clang_tablegen(BuiltinTemplates.inc -gen-clang-builtin-templates
   SOURCE BuiltinTemplates.td
   TARGET ClangBuiltinTemplates)
diff --git a/clang/include/clang/Basic/TargetBuiltins.h 
b/clang/include/clang/Basic/TargetBuiltins.h
index 9b4613c853206..bd0287d766225 100644
--- a/clang/include/clang/Basic/TargetBuiltins.h
+++ b/clang/include/clang/Basic/TargetBuiltins.h
@@ -457,13 +457,18 @@ namespace clang {
 
   /// SystemZ builtins
   namespace SystemZ {
-    enum {
-        LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+  enum {
+    LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
 #define GET_BUILTIN_ENUMERATORS
 #include "clang/Basic/BuiltinsSystemZ.inc"
 #undef GET_BUILTIN_ENUMERATORS
-        LastTSBuiltin
-    };
+    FirstZOSBuiltin,
+    LastSystemZBuiltin = FirstZOSBuiltin - 1,
+#define GET_BUILTIN_ENUMERATORS
+#include "clang/Basic/BuiltinsZOS.inc"
+#undef GET_BUILTIN_ENUMERATORS
+    LastTSBuiltin
+  };
   }
 
   /// WebAssembly builtins
diff --git a/clang/lib/Basic/Targets/SystemZ.cpp 
b/clang/lib/Basic/Targets/SystemZ.cpp
index 750629ac94f87..080a961b95d0d 100644
--- a/clang/lib/Basic/Targets/SystemZ.cpp
+++ b/clang/lib/Basic/Targets/SystemZ.cpp
@@ -22,7 +22,9 @@ using namespace clang;
 using namespace clang::targets;
 
 static constexpr int NumBuiltins =
-    clang::SystemZ::LastTSBuiltin - Builtin::FirstTSBuiltin;
+    clang::SystemZ::LastSystemZBuiltin - Builtin::FirstTSBuiltin + 1;
+static constexpr int NumBuiltinsZOS =
+    clang::SystemZ::LastTSBuiltin - clang::SystemZ::LastSystemZBuiltin - 1;
 
 #define GET_BUILTIN_STR_TABLE
 #include "clang/Basic/BuiltinsSystemZ.inc"
@@ -41,6 +43,20 @@ static constexpr Builtin::Info PrefixedBuiltinInfos[] = {
 };
 static_assert((std::size(BuiltinInfos) + std::size(PrefixedBuiltinInfos)) ==
               NumBuiltins);
+namespace clang {
+namespace ZOS {
+#define GET_BUILTIN_STR_TABLE
+#include "clang/Basic/BuiltinsZOS.inc"
+#undef GET_BUILTIN_STR_TABLE
+
+static constexpr Builtin::Info BuiltinInfos[] = {
+#define GET_BUILTIN_INFOS
+#include "clang/Basic/BuiltinsZOS.inc"
+#undef GET_BUILTIN_INFOS
+};
+static_assert((std::size(BuiltinInfos)) == NumBuiltinsZOS);
+} // namespace ZOS
+} // namespace clang
 
 const char *const SystemZTargetInfo::GCCRegNames[] = {
     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
@@ -216,6 +232,10 @@ void SystemZTargetInfo::getTargetDefines(const LangOptions 
&Opts,
 
 llvm::SmallVector<Builtin::InfosShard>
 SystemZTargetInfo::getTargetBuiltins() const {
+  if (getTriple().isOSzOS())
+    return {{&BuiltinStrings, BuiltinInfos},
+            {&BuiltinStrings, PrefixedBuiltinInfos, "__builtin_s390_"},
+            {&ZOS::BuiltinStrings, ZOS::BuiltinInfos}};
   return {{&BuiltinStrings, BuiltinInfos},
           {&BuiltinStrings, PrefixedBuiltinInfos, "__builtin_s390_"}};
 }
diff --git a/clang/lib/CodeGen/TargetBuiltins/SystemZ.cpp 
b/clang/lib/CodeGen/TargetBuiltins/SystemZ.cpp
index c33d7581f50b8..1c115baf5cf78 100644
--- a/clang/lib/CodeGen/TargetBuiltins/SystemZ.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/SystemZ.cpp
@@ -10,6 +10,7 @@
 //
 
//===----------------------------------------------------------------------===//
 
+#include "CGBuiltin.h"
 #include "CodeGenFunction.h"
 #include "clang/Basic/TargetBuiltins.h"
 #include "llvm/IR/IntrinsicsS390.h"
@@ -36,6 +37,54 @@ static Value *EmitSystemZIntrinsicWithCC(CodeGenFunction 
&CGF,
   return CGF.Builder.CreateExtractValue(Call, 0);
 }
 
+/// For z/OS, the builtin __cs1 has the following signature:
+/// int __cs1(void * Comparand,
+///           void * Destination,
+///           void * Exchange);
+/// Whereas the llvm 'cmpxchg' instruction has the following syntax:
+/// compxchg *Destination, Comparand, Exchange.
+/// So we need to swap Comparand & Destination and dereference Comparand &
+/// Exchange when invoking CreateAtomicCmpXchng. For this reason we can not use
+/// the utility function MakeAtomicCmpXchgValue.
+static Value *EmitAtomicCmpXchgForZOSIntrin(CodeGenFunction &CGF,
+                                            const CallExpr *E,
+                                            llvm::Type *IntType, bool HasAddr) 
{
+
+  CharUnits Alignment =
+      CGF.getContext().toCharUnitsFromBits(IntType->getScalarSizeInBits());
+  llvm::Value *DestinationPtr = CGF.EmitScalarExpr(E->getArg(1));
+  llvm::Value *ComparandPtr = CGF.EmitScalarExpr(E->getArg(0));
+
+  Address DestinationAddr = Address(DestinationPtr, IntType, Alignment);
+  Address ComparandAddr = Address(ComparandPtr, IntType, Alignment);
+
+  llvm::Value *Comparand = CGF.Builder.CreateLoad(ComparandAddr);
+  llvm::Value *Exchange;
+  if (HasAddr) {
+    llvm::Value *ExchangePtr = CGF.EmitScalarExpr(E->getArg(2));
+    Address ExchangeAddr = Address(ExchangePtr, IntType, Alignment);
+    Exchange = CGF.Builder.CreateLoad(ExchangeAddr);
+  } else {
+    Exchange =
+        EmitToInt(CGF, CGF.EmitScalarExpr(E->getArg(2)),
+                  E->getArg(2)->getType(), cast<llvm::IntegerType>(IntType));
+  }
+
+  Value *Result = CGF.Builder.CreateAtomicCmpXchg(
+      DestinationAddr, Comparand, Exchange,
+      llvm::AtomicOrdering::SequentiallyConsistent,
+      llvm::AtomicOrdering::SequentiallyConsistent);
+
+  // Store Destination in Comparand.
+  CGF.Builder.CreateStore(CGF.Builder.CreateExtractValue(Result, 0),
+                          ComparandAddr);
+
+  // Extract boolean success flag, inverse it and zext it to int.
+  llvm::Value *RetVal =
+      CGF.Builder.CreateNot(CGF.Builder.CreateExtractValue(Result, 1));
+  return CGF.Builder.CreateZExt(RetVal, CGF.ConvertType(E->getType()));
+}
+
 Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID,
                                                const CallExpr *E) {
   switch (BuiltinID) {
@@ -68,11 +117,25 @@ Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned 
BuiltinID,
     Function *F = CGM.getIntrinsic(Intrinsic::s390_ntstg);
     return Builder.CreateCall(F, {Data, Address});
   }
+  case SystemZ::BI__cs: {
+    return EmitAtomicCmpXchgForZOSIntrin(*this, E, Int32Ty, false);
+  }
+  case SystemZ::BI__cs1: {
+    return EmitAtomicCmpXchgForZOSIntrin(*this, E, Int32Ty, true);
+  }
+  case SystemZ::BI__csg:
+  case SystemZ::BI__cds1: {
+    return EmitAtomicCmpXchgForZOSIntrin(*this, E, Int64Ty, true);
+  }
+  case SystemZ::BI__cdsg: {
+    llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128);
+    return EmitAtomicCmpXchgForZOSIntrin(*this, E, Int128Ty, true);
+  }
 
-  // Vector builtins.  Note that most vector builtins are mapped automatically
-  // to target-specific LLVM intrinsics.  The ones handled specially here can
-  // be represented via standard LLVM IR, which is preferable to enable common
-  // LLVM optimizations.
+    // Vector builtins.  Note that most vector builtins are mapped 
automatically
+    // to target-specific LLVM intrinsics.  The ones handled specially here can
+    // be represented via standard LLVM IR, which is preferable to enable 
common
+    // LLVM optimizations.
 
   case SystemZ::BI__builtin_s390_vclzb:
   case SystemZ::BI__builtin_s390_vclzh:
diff --git a/clang/test/CodeGen/SystemZ/builtins-zos-cds1.c 
b/clang/test/CodeGen/SystemZ/builtins-zos-cds1.c
new file mode 100644
index 0000000000000..1534ed11ff066
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/builtins-zos-cds1.c
@@ -0,0 +1,18 @@
+// REQUIRES: systemz-registered-target
+// RUN: %clang_cc1 -triple s390x-none-zos %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-linux-gnu %s -verify
+
+typedef struct __attribute__((__aligned__(8))) {
+  int a;
+  int b;
+} double_word;
+
+int func(double_word *a, double_word *b, double_word *c) {
+  return __cds1(a, b, c);
+}
+// expected-error@11 {{call to undeclared function '__cds1'; ISO C99 and later 
do not support implicit function declarations}}
+
+// CHECK: cmpxchg ptr {{.*}}, i64 {{.*}}, i64 {{.*}} seq_cst seq_cst, align 8
+// CHECK: store i64 {{.*}}, ptr {{.*}}, align 8
+// CHECK: xor i1 {{.*}}, true
+
diff --git a/clang/test/CodeGen/SystemZ/builtins-zos-cdsg.c 
b/clang/test/CodeGen/SystemZ/builtins-zos-cdsg.c
new file mode 100644
index 0000000000000..9cf0271600af0
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/builtins-zos-cdsg.c
@@ -0,0 +1,19 @@
+// REQUIRES: systemz-registered-target
+// RUN: %clang_cc1 -triple s390x-none-zos %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-linux-gnu %s -verify=loz
+
+typedef struct __attribute__((__aligned__(16))) {
+  int a;
+  int b;
+  int c;
+  int d;
+} quadruple_word;
+
+int func(quadruple_word *a, quadruple_word *b, quadruple_word *c) {
+  return __cdsg(a, b, c);
+}
+// loz-error@13 {{call to undeclared function '__cdsg'; ISO C99 and later do 
not support implicit function declarations}}
+
+// CHECK: cmpxchg ptr {{.*}}, i128 {{.*}}, i128 {{.*}} seq_cst seq_cst, align 
16
+// CHECK: store i128 {{.*}}, ptr {{.*}}, align 16
+// CHECK: xor i1 {{.*}}, true
diff --git a/clang/test/CodeGen/SystemZ/builtins-zos-cs.c 
b/clang/test/CodeGen/SystemZ/builtins-zos-cs.c
new file mode 100644
index 0000000000000..6877a86dd3c53
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/builtins-zos-cs.c
@@ -0,0 +1,12 @@
+// REQUIRES: systemz-registered-target
+// RUN: %clang_cc1 -triple s390x-none-zos %s -emit-llvm -o - | FileCheck 
-check-prefix=CHECK %s
+// RUN: %clang_cc1 -triple s390x-linux-gnu %s -verify
+
+int func(unsigned int *a, unsigned int *b, unsigned int c) {
+    return __cs(a, b, c);
+}
+// expected-error@6 {{call to undeclared function '__cs'; ISO C99 and later do 
not support implicit function declarations}}
+
+// CHECK: cmpxchg ptr {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4
+// CHECK: store i32 {{.*}}, ptr {{.*}}, align 4
+// CHECK: xor i1 {{.*}}, true
diff --git a/clang/test/CodeGen/SystemZ/builtins-zos-cs1.c 
b/clang/test/CodeGen/SystemZ/builtins-zos-cs1.c
new file mode 100644
index 0000000000000..2f036736d9e22
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/builtins-zos-cs1.c
@@ -0,0 +1,12 @@
+// REQUIRES: systemz-registered-target
+// RUN: %clang_cc1 -triple s390x-none-zos %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-linux-gnu %s -verify
+
+int func(int *a, int *b, int *c) {
+  return __cs1(a, b, c);
+}
+// expected-error@6 {{call to undeclared function '__cs1'; ISO C99 and later 
do not support implicit function declarations}}
+
+// CHECK: cmpxchg ptr {{.*}}, i32 {{.*}}, i32 {{.*}} seq_cst seq_cst, align 4
+// CHECK: store i32 {{.*}}, ptr {{.*}}, align 4
+// CHECK: xor i1 {{.*}}, true
diff --git a/clang/test/CodeGen/SystemZ/builtins-zos-csg.c 
b/clang/test/CodeGen/SystemZ/builtins-zos-csg.c
new file mode 100644
index 0000000000000..eb2add0b56d62
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/builtins-zos-csg.c
@@ -0,0 +1,17 @@
+// REQUIRES: systemz-registered-target
+// RUN: %clang_cc1 -triple s390x-none-zos %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-linux-gnu %s -verify=loz
+
+typedef struct __attribute__((__aligned__(8))) {
+  int a;
+  int b;
+} double_word;
+
+int func(double_word *a, double_word *b, double_word *c) {
+  return __csg(a, b, c);
+}
+// loz-error@11 {{call to undeclared function '__csg'; ISO C99 and later do 
not support implicit function declarations}}
+
+// CHECK: cmpxchg ptr {{.*}}, i64 {{.*}}, i64 {{.*}} seq_cst seq_cst, align 8
+// CHECK: store i64 {{.*}}, ptr {{.*}}, align 8
+// CHECK: xor i1 {{.*}}, true

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

Reply via email to