Skip to content

Commit 4664008

Browse files
committed
[clang] Add builtins for add with nuw and/or nsw
1 parent dd21aac commit 4664008

File tree

3 files changed

+219
-0
lines changed

3 files changed

+219
-0
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5037,6 +5037,66 @@ def ArithmeticFence : LangBuiltin<"ALL_LANGUAGES"> {
50375037
let Prototype = "void(...)";
50385038
}
50395039

5040+
class SNUWTemplate :
5041+
Template<["int", "long int", "long long int"],
5042+
["_nuw", "l_nuw", "ll_nuw"]>;
5043+
5044+
class SNSWTemplate :
5045+
Template<["int", "long int", "long long int"],
5046+
["_nsw", "l_nsw", "ll_nsw"]>;
5047+
5048+
class SNXWTemplate :
5049+
Template<["int", "long int", "long long int"],
5050+
["_nuw_nsw", "l_nuw_nsw", "ll_nuw_nsw"]>;
5051+
5052+
def SAddNUW : Builtin, SNUWTemplate {
5053+
let Spellings = ["__builtin_sadd"];
5054+
let Attributes = [NoThrow];
5055+
let Prototype = "T(T const, T const)";
5056+
}
5057+
5058+
def SAddNSW : Builtin, SNSWTemplate {
5059+
let Spellings = ["__builtin_sadd"];
5060+
let Attributes = [NoThrow];
5061+
let Prototype = "T(T const, T const)";
5062+
}
5063+
5064+
def SAddNXW : Builtin, SNXWTemplate {
5065+
let Spellings = ["__builtin_sadd"];
5066+
let Attributes = [NoThrow];
5067+
let Prototype = "T(T const, T const)";
5068+
}
5069+
5070+
class UNUWTemplate :
5071+
Template<["unsigned int", "unsigned long int", "unsigned long long int"],
5072+
["_nuw", "l_nuw", "ll_nuw"]>;
5073+
5074+
class UNSWTemplate :
5075+
Template<["unsigned int", "unsigned long int", "unsigned long long int"],
5076+
["_nsw", "l_nsw", "ll_nsw"]>;
5077+
5078+
class UNXWTemplate :
5079+
Template<["unsigned int", "unsigned long int", "unsigned long long int"],
5080+
["_nuw_nsw", "l_nuw_nsw", "ll_nuw_nsw"]>;
5081+
5082+
def UAddNUW : Builtin, UNUWTemplate {
5083+
let Spellings = ["__builtin_uadd"];
5084+
let Attributes = [NoThrow];
5085+
let Prototype = "T(T const, T const)";
5086+
}
5087+
5088+
def UAddNSW : Builtin, UNSWTemplate {
5089+
let Spellings = ["__builtin_uadd"];
5090+
let Attributes = [NoThrow];
5091+
let Prototype = "T(T const, T const)";
5092+
}
5093+
5094+
def UAddNXW : Builtin, UNXWTemplate {
5095+
let Spellings = ["__builtin_uadd"];
5096+
let Attributes = [NoThrow];
5097+
let Prototype = "T(T const, T const)";
5098+
}
5099+
50405100
def CountedByRef : Builtin {
50415101
let Spellings = ["__builtin_counted_by_ref"];
50425102
let Attributes = [NoThrow, CustomTypeChecking];

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6616,6 +6616,54 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
66166616
auto Str = CGM.GetAddrOfConstantCString(Name, "");
66176617
return RValue::get(Str.getPointer());
66186618
}
6619+
6620+
case Builtin::BI__builtin_sadd_nuw:
6621+
case Builtin::BI__builtin_saddl_nuw:
6622+
case Builtin::BI__builtin_saddll_nuw:
6623+
case Builtin::BI__builtin_uadd_nuw:
6624+
case Builtin::BI__builtin_uaddl_nuw:
6625+
case Builtin::BI__builtin_uaddll_nuw:
6626+
6627+
case Builtin::BI__builtin_sadd_nsw:
6628+
case Builtin::BI__builtin_saddl_nsw:
6629+
case Builtin::BI__builtin_saddll_nsw:
6630+
case Builtin::BI__builtin_uadd_nsw:
6631+
case Builtin::BI__builtin_uaddl_nsw:
6632+
case Builtin::BI__builtin_uaddll_nsw:
6633+
6634+
case Builtin::BI__builtin_sadd_nuw_nsw:
6635+
case Builtin::BI__builtin_saddl_nuw_nsw:
6636+
case Builtin::BI__builtin_saddll_nuw_nsw:
6637+
case Builtin::BI__builtin_uadd_nuw_nsw:
6638+
case Builtin::BI__builtin_uaddl_nuw_nsw:
6639+
case Builtin::BI__builtin_uaddll_nuw_nsw: {
6640+
bool NUW = false;
6641+
bool NSW = false;
6642+
switch (BuiltinIDIfNoAsmLabel) {
6643+
case Builtin::BI__builtin_sadd_nuw:
6644+
case Builtin::BI__builtin_saddl_nuw:
6645+
case Builtin::BI__builtin_saddll_nuw:
6646+
case Builtin::BI__builtin_uadd_nuw:
6647+
case Builtin::BI__builtin_uaddl_nuw:
6648+
case Builtin::BI__builtin_uaddll_nuw:
6649+
NUW = true;
6650+
break;
6651+
case Builtin::BI__builtin_sadd_nsw:
6652+
case Builtin::BI__builtin_saddl_nsw:
6653+
case Builtin::BI__builtin_saddll_nsw:
6654+
case Builtin::BI__builtin_uadd_nsw:
6655+
case Builtin::BI__builtin_uaddl_nsw:
6656+
case Builtin::BI__builtin_uaddll_nsw:
6657+
NSW = true;
6658+
break;
6659+
default:
6660+
NUW = NSW = true;
6661+
break;
6662+
}
6663+
llvm::Value *X = EmitScalarExpr(E->getArg(0));
6664+
llvm::Value *Y = EmitScalarExpr(E->getArg(1));
6665+
return RValue::get(Builder.CreateAdd(X, Y, "add", NUW, NSW));
6666+
}
66196667
}
66206668

66216669
// If this is an alias for a lib function (e.g. __builtin_sin), emit
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Test CodeGen for nuw/nsw builtins.
2+
3+
// RUN: %clang_cc1 -triple "x86_64-unknown-unknown" -emit-llvm -x c %s -o - | FileCheck %s
4+
5+
//------------------------------------------------------------------------------
6+
// int
7+
//------------------------------------------------------------------------------
8+
int test_sadd_nuw(int x, int y) { return __builtin_sadd_nuw(x, y); }
9+
// CHECK-LABEL: @test_sadd_nuw
10+
// CHECK: [[RV:%.+]] = add nuw i32
11+
// CHECK: ret i32 [[RV]]
12+
13+
int test_sadd_nsw(int x, int y) { return __builtin_sadd_nsw(x, y); }
14+
// CHECK-LABEL: @test_sadd_nsw
15+
// CHECK: [[RV:%.+]] = add nsw i32
16+
// CHECK: ret i32 [[RV]]
17+
18+
int test_sadd_nuw_nsw(int x, int y) { return __builtin_sadd_nuw_nsw(x, y); }
19+
// CHECK-LABEL: @test_sadd_nuw_nsw
20+
// CHECK: [[RV:%.+]] = add nuw nsw i32
21+
// CHECK: ret i32 [[RV]]
22+
23+
//------------------------------------------------------------------------------
24+
// long int
25+
//------------------------------------------------------------------------------
26+
long int test_saddl_nuw(long int x, long int y) { return __builtin_saddl_nuw(x, y); }
27+
// CHECK-LABEL: @test_saddl_nuw
28+
// CHECK: [[RV:%.+]] = add nuw i64
29+
// CHECK: ret i64 [[RV]]
30+
31+
long int test_saddl_nsw(long int x, long int y) { return __builtin_saddl_nsw(x, y); }
32+
// CHECK-LABEL: @test_saddl_nsw
33+
// CHECK: [[RV:%.+]] = add nsw i64
34+
// CHECK: ret i64 [[RV]]
35+
36+
long int test_saddl_nuw_nsw(long int x, long int y) { return __builtin_saddl_nuw_nsw(x, y); }
37+
// CHECK-LABEL: @test_saddl_nuw_nsw
38+
// CHECK: [[RV:%.+]] = add nuw nsw i64
39+
// CHECK: ret i64 [[RV]]
40+
41+
//------------------------------------------------------------------------------
42+
// long int
43+
//------------------------------------------------------------------------------
44+
long long int test_saddll_nuw(long long int x, long long int y) { return __builtin_saddll_nuw(x, y); }
45+
// CHECK-LABEL: @test_saddll_nuw
46+
// CHECK: [[RV:%.+]] = add nuw i64
47+
// CHECK: ret i64 [[RV]]
48+
49+
long long int test_saddll_nsw(long long int x, long long int y) { return __builtin_saddll_nsw(x, y); }
50+
// CHECK-LABEL: @test_saddll_nsw
51+
// CHECK: [[RV:%.+]] = add nsw i64
52+
// CHECK: ret i64 [[RV]]
53+
54+
long long int test_saddll_nuw_nsw(long long int x, long long int y) { return __builtin_saddll_nuw_nsw(x, y); }
55+
// CHECK-LABEL: @test_saddll_nuw_nsw
56+
// CHECK: [[RV:%.+]] = add nuw nsw i64
57+
// CHECK: ret i64 [[RV]]
58+
59+
//------------------------------------------------------------------------------
60+
// unsigned int
61+
//------------------------------------------------------------------------------
62+
unsigned int test_uadd_nuw(unsigned int x, unsigned int y) { return __builtin_uadd_nuw(x, y); }
63+
// CHECK-LABEL: @test_uadd_nuw
64+
// CHECK: [[RV:%.+]] = add nuw i32
65+
// CHECK: ret i32 [[RV]]
66+
67+
unsigned int test_uadd_nsw(unsigned int x, unsigned int y) { return __builtin_uadd_nsw(x, y); }
68+
// CHECK-LABEL: @test_uadd_nsw
69+
// CHECK: [[RV:%.+]] = add nsw i32
70+
// CHECK: ret i32 [[RV]]
71+
72+
unsigned int test_uadd_nuw_nsw(unsigned int x, unsigned int y) { return __builtin_uadd_nuw_nsw(x, y); }
73+
// CHECK-LABEL: @test_uadd_nuw_nsw
74+
// CHECK: [[RV:%.+]] = add nuw nsw i32
75+
// CHECK: ret i32 [[RV]]
76+
77+
//------------------------------------------------------------------------------
78+
// unsigned long int
79+
//------------------------------------------------------------------------------
80+
unsigned long int test_uaddl_nuw(unsigned long int x, unsigned long int y) { return __builtin_uaddl_nuw(x, y); }
81+
// CHECK-LABEL: @test_uaddl_nuw
82+
// CHECK: [[RV:%.+]] = add nuw i64
83+
// CHECK: ret i64 [[RV]]
84+
85+
unsigned long int test_uaddl_nsw(unsigned long int x, unsigned long int y) { return __builtin_uaddl_nsw(x, y); }
86+
// CHECK-LABEL: @test_uaddl_nsw
87+
// CHECK: [[RV:%.+]] = add nsw i64
88+
// CHECK: ret i64 [[RV]]
89+
90+
unsigned long int test_uaddl_nuw_nsw(unsigned long int x, unsigned long int y) { return __builtin_uaddl_nuw_nsw(x, y); }
91+
// CHECK-LABEL: @test_uaddl_nuw_nsw
92+
// CHECK: [[RV:%.+]] = add nuw nsw i64
93+
// CHECK: ret i64 [[RV]]
94+
95+
//------------------------------------------------------------------------------
96+
// unsigned long long int
97+
//------------------------------------------------------------------------------
98+
unsigned long long int test_uaddll_nuw(unsigned long long int x, unsigned long long int y) { return __builtin_uaddll_nuw(x, y); }
99+
// CHECK-LABEL: @test_uaddll_nuw
100+
// CHECK: [[RV:%.+]] = add nuw i64
101+
// CHECK: ret i64 [[RV]]
102+
103+
unsigned long long int test_uaddll_nsw(unsigned long long int x, unsigned long long int y) { return __builtin_uaddll_nsw(x, y); }
104+
// CHECK-LABEL: @test_uaddll_nsw
105+
// CHECK: [[RV:%.+]] = add nsw i64
106+
// CHECK: ret i64 [[RV]]
107+
108+
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); }
109+
// CHECK-LABEL: @test_uaddll_nuw_nsw
110+
// CHECK: [[RV:%.+]] = add nuw nsw i64
111+
// CHECK: ret i64 [[RV]]

0 commit comments

Comments
 (0)