Skip to content

Commit 58f679c

Browse files
committed
fixup! [clang] Add builtins for add with nuw and/or nsw
Rework non-wrapping add builtins to be generic
1 parent 4664008 commit 58f679c

File tree

6 files changed

+113
-133
lines changed

6 files changed

+113
-133
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 12 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5037,64 +5037,22 @@ 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)";
5040+
def AddNUW : Builtin {
5041+
let Spellings = ["__builtin_add_nuw"];
5042+
let Attributes = [CustomTypeChecking, NoThrow];
5043+
let Prototype = "void(...)";
50865044
}
50875045

5088-
def UAddNSW : Builtin, UNSWTemplate {
5089-
let Spellings = ["__builtin_uadd"];
5090-
let Attributes = [NoThrow];
5091-
let Prototype = "T(T const, T const)";
5046+
def AddNSW : Builtin {
5047+
let Spellings = ["__builtin_add_nsw"];
5048+
let Attributes = [CustomTypeChecking, NoThrow];
5049+
let Prototype = "void(...)";
50925050
}
50935051

5094-
def UAddNXW : Builtin, UNXWTemplate {
5095-
let Spellings = ["__builtin_uadd"];
5096-
let Attributes = [NoThrow];
5097-
let Prototype = "T(T const, T const)";
5052+
def AddNW : Builtin {
5053+
let Spellings = ["__builtin_add_nuw_nsw"];
5054+
let Attributes = [CustomTypeChecking, NoThrow];
5055+
let Prototype = "void(...)";
50985056
}
50995057

51005058
def CountedByRef : Builtin {

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12527,6 +12527,9 @@ def err_builtin_matrix_stride_too_small: Error<
1252712527
def err_builtin_matrix_invalid_dimension: Error<
1252812528
"%0 dimension is outside the allowed range [1, %1]">;
1252912529

12530+
def err_builtin_add_nxw_invalid_arg : Error<
12531+
"both arguments must be of integral type but %ordinal0 argument is %1">;
12532+
1253012533
def warn_mismatched_import : Warning<
1253112534
"import %select{module|name}0 (%1) does not match the import %select{module|name}0 (%2) of the "
1253212535
"previous declaration">,

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6617,49 +6617,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
66176617
return RValue::get(Str.getPointer());
66186618
}
66196619

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-
}
6620+
case Builtin::BI__builtin_add_nuw:
6621+
case Builtin::BI__builtin_add_nsw:
6622+
case Builtin::BI__builtin_add_nuw_nsw: {
6623+
bool NXW = BuiltinIDIfNoAsmLabel == Builtin::BI__builtin_add_nuw_nsw;
6624+
bool NUW = BuiltinIDIfNoAsmLabel == Builtin::BI__builtin_add_nuw || NXW;
6625+
bool NSW = BuiltinIDIfNoAsmLabel == Builtin::BI__builtin_add_nsw || NXW;
66636626
llvm::Value *X = EmitScalarExpr(E->getArg(0));
66646627
llvm::Value *Y = EmitScalarExpr(E->getArg(1));
66656628
return RValue::get(Builder.CreateAdd(X, Y, "add", NUW, NSW));

clang/lib/Sema/SemaChecking.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,6 +2105,34 @@ static bool BuiltinCountZeroBitsGeneric(Sema &S, CallExpr *TheCall) {
21052105
return false;
21062106
}
21072107

2108+
static bool BuiltinAddNoWrap(Sema &S, CallExpr *TheCall) {
2109+
if (S.checkArgCount(TheCall, 2))
2110+
return true;
2111+
ExprResult OrigArg0 = TheCall->getArg(0);
2112+
ExprResult OrigArg1 = TheCall->getArg(1);
2113+
ExprResult Arg0 = OrigArg0;
2114+
ExprResult Arg1 = OrigArg1;
2115+
2116+
QualType Res = S.UsualArithmeticConversions(Arg0, Arg1, TheCall->getExprLoc(),
2117+
Sema::ACK_Arithmetic);
2118+
if (Arg0.isInvalid() || Arg1.isInvalid())
2119+
return true;
2120+
2121+
if (Res.isNull() || !Res->isIntegralType(S.Context)) {
2122+
Expr *E0 = OrigArg0.get();
2123+
Expr *E1 = OrigArg1.get();
2124+
auto BadArg = !E0->getType()->isIntegralType(S.Context) ? E0 : E1;
2125+
return S.Diag(BadArg->getBeginLoc(), diag::err_builtin_add_nxw_invalid_arg)
2126+
<< (BadArg == E0 ? 1 : 2) << BadArg->getType()
2127+
<< BadArg->getSourceRange();
2128+
}
2129+
2130+
TheCall->setArg(0, Arg0.get());
2131+
TheCall->setArg(1, Arg1.get());
2132+
TheCall->setType(Res);
2133+
return false;
2134+
}
2135+
21082136
ExprResult
21092137
Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
21102138
CallExpr *TheCall) {
@@ -2975,6 +3003,12 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
29753003
if (BuiltinCountedByRef(TheCall))
29763004
return ExprError();
29773005
break;
3006+
case Builtin::BI__builtin_add_nuw:
3007+
case Builtin::BI__builtin_add_nsw:
3008+
case Builtin::BI__builtin_add_nuw_nsw:
3009+
if (BuiltinAddNoWrap(*this, TheCall))
3010+
return ExprError();
3011+
break;
29783012
}
29793013

29803014
if (getLangOpts().HLSL && HLSL().CheckBuiltinFunctionCall(BuiltinID, TheCall))

clang/test/CodeGen/builtins-int-wrap.c

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,107 +5,107 @@
55
//------------------------------------------------------------------------------
66
// int
77
//------------------------------------------------------------------------------
8-
int test_sadd_nuw(int x, int y) { return __builtin_sadd_nuw(x, y); }
9-
// CHECK-LABEL: @test_sadd_nuw
8+
int test_add_nuw(int x, int y) { return __builtin_add_nuw(x, y); }
9+
// CHECK-LABEL: @test_add_nuw
1010
// CHECK: [[RV:%.+]] = add nuw i32
1111
// CHECK: ret i32 [[RV]]
1212

13-
int test_sadd_nsw(int x, int y) { return __builtin_sadd_nsw(x, y); }
14-
// CHECK-LABEL: @test_sadd_nsw
13+
int test_add_nsw(int x, int y) { return __builtin_add_nsw(x, y); }
14+
// CHECK-LABEL: @test_add_nsw
1515
// CHECK: [[RV:%.+]] = add nsw i32
1616
// CHECK: ret i32 [[RV]]
1717

18-
int test_sadd_nuw_nsw(int x, int y) { return __builtin_sadd_nuw_nsw(x, y); }
19-
// CHECK-LABEL: @test_sadd_nuw_nsw
18+
int test_add_nuw_nsw(int x, int y) { return __builtin_add_nuw_nsw(x, y); }
19+
// CHECK-LABEL: @test_add_nuw_nsw
2020
// CHECK: [[RV:%.+]] = add nuw nsw i32
2121
// CHECK: ret i32 [[RV]]
2222

2323
//------------------------------------------------------------------------------
2424
// long int
2525
//------------------------------------------------------------------------------
26-
long int test_saddl_nuw(long int x, long int y) { return __builtin_saddl_nuw(x, y); }
27-
// CHECK-LABEL: @test_saddl_nuw
26+
long int test_add_nuw_l(long int x, long int y) { return __builtin_add_nuw(x, y); }
27+
// CHECK-LABEL: @test_add_nuw_l
2828
// CHECK: [[RV:%.+]] = add nuw i64
2929
// CHECK: ret i64 [[RV]]
3030

31-
long int test_saddl_nsw(long int x, long int y) { return __builtin_saddl_nsw(x, y); }
32-
// CHECK-LABEL: @test_saddl_nsw
31+
long int test_add_nsw_l(long int x, long int y) { return __builtin_add_nsw(x, y); }
32+
// CHECK-LABEL: @test_add_nsw_l
3333
// CHECK: [[RV:%.+]] = add nsw i64
3434
// CHECK: ret i64 [[RV]]
3535

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
36+
long int test_add_nuw_nsw_l(long int x, long int y) { return __builtin_add_nuw_nsw(x, y); }
37+
// CHECK-LABEL: @test_add_nuw_nsw_l
3838
// CHECK: [[RV:%.+]] = add nuw nsw i64
3939
// CHECK: ret i64 [[RV]]
4040

4141
//------------------------------------------------------------------------------
4242
// long int
4343
//------------------------------------------------------------------------------
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
44+
long long int test_add_nuw_ll(long long int x, long long int y) { return __builtin_add_nuw(x, y); }
45+
// CHECK-LABEL: @test_add_nuw_ll
4646
// CHECK: [[RV:%.+]] = add nuw i64
4747
// CHECK: ret i64 [[RV]]
4848

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
49+
long long int test_add_nsw_ll(long long int x, long long int y) { return __builtin_add_nsw(x, y); }
50+
// CHECK-LABEL: @test_add_nsw_ll
5151
// CHECK: [[RV:%.+]] = add nsw i64
5252
// CHECK: ret i64 [[RV]]
5353

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
54+
long long int test_add_nuw_nsw_ll(long long int x, long long int y) { return __builtin_add_nuw_nsw(x, y); }
55+
// CHECK-LABEL: @test_add_nuw_nsw_ll
5656
// CHECK: [[RV:%.+]] = add nuw nsw i64
5757
// CHECK: ret i64 [[RV]]
5858

5959
//------------------------------------------------------------------------------
6060
// unsigned int
6161
//------------------------------------------------------------------------------
62-
unsigned int test_uadd_nuw(unsigned int x, unsigned int y) { return __builtin_uadd_nuw(x, y); }
63-
// CHECK-LABEL: @test_uadd_nuw
62+
unsigned int test_add_nuw_u(unsigned int x, unsigned int y) { return __builtin_add_nuw(x, y); }
63+
// CHECK-LABEL: @test_add_nuw_u
6464
// CHECK: [[RV:%.+]] = add nuw i32
6565
// CHECK: ret i32 [[RV]]
6666

67-
unsigned int test_uadd_nsw(unsigned int x, unsigned int y) { return __builtin_uadd_nsw(x, y); }
68-
// CHECK-LABEL: @test_uadd_nsw
67+
unsigned int test_add_nsw_u(unsigned int x, unsigned int y) { return __builtin_add_nsw(x, y); }
68+
// CHECK-LABEL: @test_add_nsw_u
6969
// CHECK: [[RV:%.+]] = add nsw i32
7070
// CHECK: ret i32 [[RV]]
7171

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
72+
unsigned int test_add_nuw_nsw_u(unsigned int x, unsigned int y) { return __builtin_add_nuw_nsw(x, y); }
73+
// CHECK-LABEL: @test_add_nuw_nsw_u
7474
// CHECK: [[RV:%.+]] = add nuw nsw i32
7575
// CHECK: ret i32 [[RV]]
7676

7777
//------------------------------------------------------------------------------
7878
// unsigned long int
7979
//------------------------------------------------------------------------------
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
80+
unsigned long int test_add_nuw_ul(unsigned long int x, unsigned long int y) { return __builtin_add_nuw(x, y); }
81+
// CHECK-LABEL: @test_add_nuw_ul
8282
// CHECK: [[RV:%.+]] = add nuw i64
8383
// CHECK: ret i64 [[RV]]
8484

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
85+
unsigned long int test_add_nsw_ul(unsigned long int x, unsigned long int y) { return __builtin_add_nsw(x, y); }
86+
// CHECK-LABEL: @test_add_nsw_ul
8787
// CHECK: [[RV:%.+]] = add nsw i64
8888
// CHECK: ret i64 [[RV]]
8989

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
90+
unsigned long int test_add_nuw_nsw_ul(unsigned long int x, unsigned long int y) { return __builtin_add_nuw_nsw(x, y); }
91+
// CHECK-LABEL: @test_add_nuw_nsw_ul
9292
// CHECK: [[RV:%.+]] = add nuw nsw i64
9393
// CHECK: ret i64 [[RV]]
9494

9595
//------------------------------------------------------------------------------
9696
// unsigned long long int
9797
//------------------------------------------------------------------------------
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
98+
unsigned long long int test_add_nuw_ull(unsigned long long int x, unsigned long long int y) { return __builtin_add_nuw(x, y); }
99+
// CHECK-LABEL: @test_add_nuw_ull
100100
// CHECK: [[RV:%.+]] = add nuw i64
101101
// CHECK: ret i64 [[RV]]
102102

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
103+
unsigned long long int test_add_nsw_ull(unsigned long long int x, unsigned long long int y) { return __builtin_add_nsw(x, y); }
104+
// CHECK-LABEL: @test_add_nsw_ull
105105
// CHECK: [[RV:%.+]] = add nsw i64
106106
// CHECK: ret i64 [[RV]]
107107

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
108+
unsigned long long int test_add_nuw_nsw_ull(unsigned long long int x, unsigned long long int y) { return __builtin_add_nuw_nsw(x, y); }
109+
// CHECK-LABEL: @test_add_nuw_nsw_ull
110110
// CHECK: [[RV:%.+]] = add nuw nsw i64
111111
// CHECK: ret i64 [[RV]]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-unknown-unknown %s
2+
3+
4+
struct Foo { int x; };
5+
6+
int test_add_nuw(int x, double y, struct Foo z) {
7+
__builtin_add_nuw(x, y); // expected-error {{both arguments must be of integral type but 2nd argument is 'double'}}
8+
__builtin_add_nuw(y, x); // expected-error {{both arguments must be of integral type but 1st argument is 'double'}}
9+
__builtin_add_nuw(x, z); // expected-error {{both arguments must be of integral type but 2nd argument is 'struct Foo'}}
10+
}
11+
12+
int test_add_nsw(int x, double y, struct Foo z) {
13+
__builtin_add_nsw(x, y); // expected-error {{both arguments must be of integral type but 2nd argument is 'double'}}
14+
__builtin_add_nsw(y, x); // expected-error {{both arguments must be of integral type but 1st argument is 'double'}}
15+
__builtin_add_nsw(x, z); // expected-error {{both arguments must be of integral type but 2nd argument is 'struct Foo'}}
16+
}
17+
18+
int test_add_nuw_nsw(int x, double y, struct Foo z) {
19+
__builtin_add_nuw_nsw(x, y); // expected-error {{both arguments must be of integral type but 2nd argument is 'double'}}
20+
__builtin_add_nuw_nsw(y, x); // expected-error {{both arguments must be of integral type but 1st argument is 'double'}}
21+
__builtin_add_nuw_nsw(x, z); // expected-error {{both arguments must be of integral type but 2nd argument is 'struct Foo'}}
22+
}

0 commit comments

Comments
 (0)