[clang] [clang] Add builtins for `add` with `nuw` and/or `nsw` (PR #130354)

via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 7 13:39:22 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: None (macurtis-amd)

<details>
<summary>Changes</summary>

To be used for OpenMP runtime library development where lack of control over nuw/nsw prevents analysis by ScalarEvolution and subsequently loop unrolling.

---
Full diff: https://github.com/llvm/llvm-project/pull/130354.diff


3 Files Affected:

- (modified) clang/include/clang/Basic/Builtins.td (+60) 
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+48) 
- (added) clang/test/CodeGen/builtins-int-wrap.c (+111) 


``````````diff
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 2268df70927a7..ba9250516ec1b 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5037,6 +5037,66 @@ def ArithmeticFence : LangBuiltin<"ALL_LANGUAGES"> {
   let Prototype = "void(...)";
 }
 
+class SNUWTemplate :
+  Template<["int",      "long int",  "long long int"],
+           ["_nuw",     "l_nuw",     "ll_nuw"]>;
+
+class SNSWTemplate :
+  Template<["int",      "long int",  "long long int"],
+           ["_nsw",     "l_nsw",     "ll_nsw"]>;
+
+class SNXWTemplate :
+  Template<["int",      "long int",  "long long int"],
+           ["_nuw_nsw", "l_nuw_nsw", "ll_nuw_nsw"]>;
+
+def SAddNUW : Builtin, SNUWTemplate {
+  let Spellings = ["__builtin_sadd"];
+  let Attributes = [NoThrow];
+  let Prototype = "T(T const, T const)";
+}
+
+def SAddNSW : Builtin, SNSWTemplate {
+  let Spellings = ["__builtin_sadd"];
+  let Attributes = [NoThrow];
+  let Prototype = "T(T const, T const)";
+}
+
+def SAddNXW : Builtin, SNXWTemplate {
+  let Spellings = ["__builtin_sadd"];
+  let Attributes = [NoThrow];
+  let Prototype = "T(T const, T const)";
+}
+
+class UNUWTemplate :
+  Template<["unsigned int", "unsigned long int", "unsigned long long int"],
+           ["_nuw",         "l_nuw",             "ll_nuw"]>;
+
+class UNSWTemplate :
+  Template<["unsigned int", "unsigned long int", "unsigned long long int"],
+           ["_nsw",         "l_nsw",             "ll_nsw"]>;
+
+class UNXWTemplate :
+  Template<["unsigned int", "unsigned long int", "unsigned long long int"],
+           ["_nuw_nsw",     "l_nuw_nsw",         "ll_nuw_nsw"]>;
+
+def UAddNUW : Builtin, UNUWTemplate {
+  let Spellings = ["__builtin_uadd"];
+  let Attributes = [NoThrow];
+  let Prototype = "T(T const, T const)";
+}
+
+def UAddNSW : Builtin, UNSWTemplate {
+  let Spellings = ["__builtin_uadd"];
+  let Attributes = [NoThrow];
+  let Prototype = "T(T const, T const)";
+}
+
+def UAddNXW : Builtin, UNXWTemplate {
+  let Spellings = ["__builtin_uadd"];
+  let Attributes = [NoThrow];
+  let Prototype = "T(T const, T const)";
+}
+
 def CountedByRef : Builtin {
   let Spellings = ["__builtin_counted_by_ref"];
   let Attributes = [NoThrow, CustomTypeChecking];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index b86bb242755be..227cffe8ae2f7 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -6616,6 +6616,54 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     auto Str = CGM.GetAddrOfConstantCString(Name, "");
     return RValue::get(Str.getPointer());
   }
+
+  case Builtin::BI__builtin_sadd_nuw:
+  case Builtin::BI__builtin_saddl_nuw:
+  case Builtin::BI__builtin_saddll_nuw:
+  case Builtin::BI__builtin_uadd_nuw:
+  case Builtin::BI__builtin_uaddl_nuw:
+  case Builtin::BI__builtin_uaddll_nuw:
+
+  case Builtin::BI__builtin_sadd_nsw:
+  case Builtin::BI__builtin_saddl_nsw:
+  case Builtin::BI__builtin_saddll_nsw:
+  case Builtin::BI__builtin_uadd_nsw:
+  case Builtin::BI__builtin_uaddl_nsw:
+  case Builtin::BI__builtin_uaddll_nsw:
+
+  case Builtin::BI__builtin_sadd_nuw_nsw:
+  case Builtin::BI__builtin_saddl_nuw_nsw:
+  case Builtin::BI__builtin_saddll_nuw_nsw:
+  case Builtin::BI__builtin_uadd_nuw_nsw:
+  case Builtin::BI__builtin_uaddl_nuw_nsw:
+  case Builtin::BI__builtin_uaddll_nuw_nsw: {
+    bool NUW = false;
+    bool NSW = false;
+    switch (BuiltinIDIfNoAsmLabel) {
+    case Builtin::BI__builtin_sadd_nuw:
+    case Builtin::BI__builtin_saddl_nuw:
+    case Builtin::BI__builtin_saddll_nuw:
+    case Builtin::BI__builtin_uadd_nuw:
+    case Builtin::BI__builtin_uaddl_nuw:
+    case Builtin::BI__builtin_uaddll_nuw:
+      NUW = true;
+      break;
+    case Builtin::BI__builtin_sadd_nsw:
+    case Builtin::BI__builtin_saddl_nsw:
+    case Builtin::BI__builtin_saddll_nsw:
+    case Builtin::BI__builtin_uadd_nsw:
+    case Builtin::BI__builtin_uaddl_nsw:
+    case Builtin::BI__builtin_uaddll_nsw:
+      NSW = true;
+      break;
+    default:
+      NUW = NSW = true;
+      break;
+    }
+    llvm::Value *X = EmitScalarExpr(E->getArg(0));
+    llvm::Value *Y = EmitScalarExpr(E->getArg(1));
+    return RValue::get(Builder.CreateAdd(X, Y, "add", NUW, NSW));
+  }
   }
 
   // If this is an alias for a lib function (e.g. __builtin_sin), emit
diff --git a/clang/test/CodeGen/builtins-int-wrap.c b/clang/test/CodeGen/builtins-int-wrap.c
new file mode 100644
index 0000000000000..16eb92681fcc1
--- /dev/null
+++ b/clang/test/CodeGen/builtins-int-wrap.c
@@ -0,0 +1,111 @@
+// Test CodeGen for nuw/nsw builtins.
+
+// RUN: %clang_cc1 -triple "x86_64-unknown-unknown" -emit-llvm -x c %s -o - | FileCheck %s
+
+//------------------------------------------------------------------------------
+// int
+//------------------------------------------------------------------------------
+int test_sadd_nuw(int x, int y) { return __builtin_sadd_nuw(x, y); }
+// CHECK-LABEL: @test_sadd_nuw
+// CHECK: [[RV:%.+]] = add nuw i32
+// CHECK: ret i32 [[RV]]
+
+int test_sadd_nsw(int x, int y) { return __builtin_sadd_nsw(x, y); }
+// CHECK-LABEL: @test_sadd_nsw
+// CHECK: [[RV:%.+]] = add nsw i32
+// CHECK: ret i32 [[RV]]
+
+int test_sadd_nuw_nsw(int x, int y) { return __builtin_sadd_nuw_nsw(x, y); }
+// CHECK-LABEL: @test_sadd_nuw_nsw
+// CHECK: [[RV:%.+]] = add nuw nsw i32
+// CHECK: ret i32 [[RV]]
+
+//------------------------------------------------------------------------------
+// long int
+//------------------------------------------------------------------------------
+long int test_saddl_nuw(long int x, long int y) { return __builtin_saddl_nuw(x, y); }
+// CHECK-LABEL: @test_saddl_nuw
+// CHECK: [[RV:%.+]] = add nuw i64
+// CHECK: ret i64 [[RV]]
+
+long int test_saddl_nsw(long int x, long int y) { return __builtin_saddl_nsw(x, y); }
+// CHECK-LABEL: @test_saddl_nsw
+// CHECK: [[RV:%.+]] = add nsw i64
+// CHECK: ret i64 [[RV]]
+
+long int test_saddl_nuw_nsw(long int x, long int y) { return __builtin_saddl_nuw_nsw(x, y); }
+// CHECK-LABEL: @test_saddl_nuw_nsw
+// CHECK: [[RV:%.+]] = add nuw nsw i64
+// CHECK: ret i64 [[RV]]
+
+//------------------------------------------------------------------------------
+// long int
+//------------------------------------------------------------------------------
+long long int test_saddll_nuw(long long int x, long long int y) { return __builtin_saddll_nuw(x, y); }
+// CHECK-LABEL: @test_saddll_nuw
+// CHECK: [[RV:%.+]] = add nuw i64
+// CHECK: ret i64 [[RV]]
+
+long long int test_saddll_nsw(long long int x, long long int y) { return __builtin_saddll_nsw(x, y); }
+// CHECK-LABEL: @test_saddll_nsw
+// CHECK: [[RV:%.+]] = add nsw i64
+// CHECK: ret i64 [[RV]]
+
+long long int test_saddll_nuw_nsw(long long int x, long long int y) { return __builtin_saddll_nuw_nsw(x, y); }
+// CHECK-LABEL: @test_saddll_nuw_nsw
+// CHECK: [[RV:%.+]] = add nuw nsw i64
+// CHECK: ret i64 [[RV]]
+
+//------------------------------------------------------------------------------
+// unsigned int
+//------------------------------------------------------------------------------
+unsigned int test_uadd_nuw(unsigned int x, unsigned int y) { return __builtin_uadd_nuw(x, y); }
+// CHECK-LABEL: @test_uadd_nuw
+// CHECK: [[RV:%.+]] = add nuw i32
+// CHECK: ret i32 [[RV]]
+
+unsigned int test_uadd_nsw(unsigned int x, unsigned int y) { return __builtin_uadd_nsw(x, y); }
+// CHECK-LABEL: @test_uadd_nsw
+// CHECK: [[RV:%.+]] = add nsw i32
+// CHECK: ret i32 [[RV]]
+
+unsigned int test_uadd_nuw_nsw(unsigned int x, unsigned int y) { return __builtin_uadd_nuw_nsw(x, y); }
+// CHECK-LABEL: @test_uadd_nuw_nsw
+// CHECK: [[RV:%.+]] = add nuw nsw i32
+// CHECK: ret i32 [[RV]]
+
+//------------------------------------------------------------------------------
+// unsigned long int
+//------------------------------------------------------------------------------
+unsigned long int test_uaddl_nuw(unsigned long int x, unsigned long int y) { return __builtin_uaddl_nuw(x, y); }
+// CHECK-LABEL: @test_uaddl_nuw
+// CHECK: [[RV:%.+]] = add nuw i64
+// CHECK: ret i64 [[RV]]
+
+unsigned long int test_uaddl_nsw(unsigned long int x, unsigned long int y) { return __builtin_uaddl_nsw(x, y); }
+// CHECK-LABEL: @test_uaddl_nsw
+// CHECK: [[RV:%.+]] = add nsw i64
+// CHECK: ret i64 [[RV]]
+
+unsigned long int test_uaddl_nuw_nsw(unsigned long int x, unsigned long int y) { return __builtin_uaddl_nuw_nsw(x, y); }
+// CHECK-LABEL: @test_uaddl_nuw_nsw
+// CHECK: [[RV:%.+]] = add nuw nsw i64
+// CHECK: ret i64 [[RV]]
+
+//------------------------------------------------------------------------------
+// unsigned long long int
+//------------------------------------------------------------------------------
+unsigned long long int test_uaddll_nuw(unsigned long long int x, unsigned long long int y) { return __builtin_uaddll_nuw(x, y); }
+// CHECK-LABEL: @test_uaddll_nuw
+// CHECK: [[RV:%.+]] = add nuw i64
+// CHECK: ret i64 [[RV]]
+
+unsigned long long int test_uaddll_nsw(unsigned long long int x, unsigned long long int y) { return __builtin_uaddll_nsw(x, y); }
+// CHECK-LABEL: @test_uaddll_nsw
+// CHECK: [[RV:%.+]] = add nsw i64
+// CHECK: ret i64 [[RV]]
+
+unsigned long long int test_uaddll_nuw_nsw(unsigned long long int x, unsigned long long int y) { return __builtin_uaddll_nuw_nsw(x, y); }
+// CHECK-LABEL: @test_uaddll_nuw_nsw
+// CHECK: [[RV:%.+]] = add nuw nsw i64
+// CHECK: ret i64 [[RV]]

``````````

</details>


https://github.com/llvm/llvm-project/pull/130354


More information about the cfe-commits mailing list