Skip to content

Commit 9a8d477

Browse files
committed
[OpenCL] Add builtin function attribute handling
Add handling for the "pure", "const" and "convergent" function attributes for OpenCL builtin functions. Patch by Pierre Gondois and Sven van Haastregt. Differential Revision: https://reviews.llvm.org/D64319
1 parent 4ecff91 commit 9a8d477

File tree

4 files changed

+97
-43
lines changed

4 files changed

+97
-43
lines changed

clang/lib/Sema/OpenCLBuiltins.td

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,18 @@ class GenericType<string _Ty, TypeList _TypeList, IntList _VectorList> :
180180
let VecWidth = 0;
181181
}
182182

183+
// Builtin function attributes.
184+
def Attr {
185+
list<bit> None = [0, 0, 0];
186+
list<bit> Pure = [1, 0, 0];
187+
list<bit> Const = [0, 1, 0];
188+
list<bit> Convergent = [0, 0, 1];
189+
}
190+
183191
//===----------------------------------------------------------------------===//
184192
// OpenCL C class for builtin functions
185193
//===----------------------------------------------------------------------===//
186-
class Builtin<string _Name, list<Type> _Signature> {
194+
class Builtin<string _Name, list<Type> _Signature, list<bit> _Attributes = Attr.None> {
187195
// Name of the builtin function
188196
string Name = _Name;
189197
// List of types used by the function. The first one is the return type and
@@ -192,6 +200,12 @@ class Builtin<string _Name, list<Type> _Signature> {
192200
list<Type> Signature = _Signature;
193201
// OpenCL Extension to which the function belongs (cl_khr_subgroups, ...)
194202
string Extension = "";
203+
// Function attribute __attribute__((pure))
204+
bit IsPure = _Attributes[0];
205+
// Function attribute __attribute__((const))
206+
bit IsConst = _Attributes[1];
207+
// Function attribute __attribute__((convergent))
208+
bit IsConv = _Attributes[2];
195209
// Version of OpenCL from which the function is available (e.g.: CL10).
196210
// MinVersion is inclusive.
197211
Version MinVersion = CL10;
@@ -307,11 +321,12 @@ foreach RType = [Float, Double, Half, Char, UChar, Short,
307321
UShort, Int, UInt, Long, ULong] in {
308322
foreach sat = ["", "_sat"] in {
309323
foreach rnd = ["", "_rte", "_rtn", "_rtp", "_rtz"] in {
310-
def : Builtin<"convert_" # RType.Name # sat # rnd, [RType, IType]>;
324+
def : Builtin<"convert_" # RType.Name # sat # rnd, [RType, IType],
325+
Attr.Const>;
311326
foreach v = [2, 3, 4, 8, 16] in {
312327
def : Builtin<"convert_" # RType.Name # v # sat # rnd,
313-
[VectorType<RType, v>,
314-
VectorType<IType, v>]>;
328+
[VectorType<RType, v>, VectorType<IType, v>],
329+
Attr.Const>;
315330
}
316331
}
317332
}
@@ -321,11 +336,11 @@ foreach RType = [Float, Double, Half, Char, UChar, Short,
321336
//--------------------------------------------------------------------
322337
// OpenCL v1.1 s6.11.1, v1.2 s6.12.1, v2.0 s6.13.1 - Work-item Functions
323338
// --- Table 7 ---
324-
def : Builtin<"get_work_dim", [UInt]>;
339+
def : Builtin<"get_work_dim", [UInt], Attr.Const>;
325340
foreach name = ["get_global_size", "get_global_id", "get_local_size",
326341
"get_local_id", "get_num_groups", "get_group_id",
327342
"get_global_offset"] in {
328-
def : Builtin<name, [Size, UInt]>;
343+
def : Builtin<name, [Size, UInt], Attr.Const>;
329344
}
330345

331346
let MinVersion = CL20 in {
@@ -491,24 +506,24 @@ foreach Type = [Int, UInt] in {
491506
foreach name = ["acos", "acosh", "acospi",
492507
"asin", "asinh", "asinpi",
493508
"atan", "atanh", "atanpi"] in {
494-
def : Builtin<name, [FGenTypeN, FGenTypeN]>;
509+
def : Builtin<name, [FGenTypeN, FGenTypeN], Attr.Const>;
495510
}
496511

497512
foreach name = ["atan2", "atan2pi"] in {
498-
def : Builtin<name, [FGenTypeN, FGenTypeN, FGenTypeN]>;
513+
def : Builtin<name, [FGenTypeN, FGenTypeN,FGenTypeN], Attr.Const>;
499514
}
500515

501516
foreach name = ["fmax", "fmin"] in {
502517
def : Builtin<name, [FGenTypeN, FGenTypeN, FGenTypeN]>;
503-
def : Builtin<name, [GenTypeFloatVecNoScalar, GenTypeFloatVecNoScalar, Float]>;
504-
def : Builtin<name, [GenTypeDoubleVecNoScalar, GenTypeDoubleVecNoScalar, Double]>;
505-
def : Builtin<name, [GenTypeHalfVecNoScalar, GenTypeHalfVecNoScalar, Half]>;
518+
def : Builtin<name, [GenTypeFloatVecNoScalar, GenTypeFloatVecNoScalar, Float], Attr.Const>;
519+
def : Builtin<name, [GenTypeDoubleVecNoScalar, GenTypeDoubleVecNoScalar, Double], Attr.Const>;
520+
def : Builtin<name, [GenTypeHalfVecNoScalar, GenTypeHalfVecNoScalar, Half], Attr.Const>;
506521
}
507522

508523
// OpenCL v1.1 s6.11.3, v1.2 s6.12.3, v2.0 s6.13.3 - Integer Functions
509524
foreach name = ["max", "min"] in {
510-
def : Builtin<name, [AIGenTypeN, AIGenTypeN, AIGenTypeN]>;
511-
def : Builtin<name, [AIGenTypeNNoScalar, AIGenTypeNNoScalar, AIGenType1]>;
525+
def : Builtin<name, [AIGenTypeN, AIGenTypeN, AIGenTypeN], Attr.Const>;
526+
def : Builtin<name, [AIGenTypeNNoScalar, AIGenTypeNNoScalar, AIGenType1], Attr.Const>;
512527
}
513528

514529
//--------------------------------------------------------------------
@@ -517,49 +532,49 @@ foreach name = ["max", "min"] in {
517532
// --- Table 22: Image Read Functions with Samplers ---
518533
foreach imgTy = [Image1d] in {
519534
foreach coordTy = [Int, Float] in {
520-
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, coordTy]>;
521-
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, coordTy]>;
522-
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, coordTy]>;
535+
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, coordTy], Attr.Pure>;
536+
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, coordTy], Attr.Pure>;
537+
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, coordTy], Attr.Pure>;
523538
}
524539
}
525540
foreach imgTy = [Image2d, Image1dArray] in {
526541
foreach coordTy = [Int, Float] in {
527-
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>]>;
528-
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>]>;
529-
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>]>;
542+
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>], Attr.Pure>;
543+
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>], Attr.Pure>;
544+
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>], Attr.Pure>;
530545
}
531546
}
532547
foreach imgTy = [Image3d, Image2dArray] in {
533548
foreach coordTy = [Int, Float] in {
534-
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>]>;
535-
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>]>;
536-
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>]>;
549+
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>], Attr.Pure>;
550+
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>], Attr.Pure>;
551+
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>], Attr.Pure>;
537552
}
538553
}
539554
foreach coordTy = [Int, Float] in {
540-
def : Builtin<"read_imagef", [Float, ImageType<Image2dDepth, "RO">, Sampler, VectorType<coordTy, 2>]>;
541-
def : Builtin<"read_imagef", [Float, ImageType<Image2dArrayDepth, "RO">, Sampler, VectorType<coordTy, 4>]>;
555+
def : Builtin<"read_imagef", [Float, ImageType<Image2dDepth, "RO">, Sampler, VectorType<coordTy, 2>], Attr.Pure>;
556+
def : Builtin<"read_imagef", [Float, ImageType<Image2dArrayDepth, "RO">, Sampler, VectorType<coordTy, 4>], Attr.Pure>;
542557
}
543558

544559
// --- Table 23: Sampler-less Read Functions ---
545560
foreach aQual = ["RO", "RW"] in {
546561
foreach imgTy = [Image2d, Image1dArray] in {
547-
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>]>;
548-
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>]>;
549-
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>]>;
562+
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
563+
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
564+
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
550565
}
551566
foreach imgTy = [Image3d, Image2dArray] in {
552-
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>]>;
553-
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>]>;
554-
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>]>;
567+
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
568+
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
569+
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
555570
}
556571
foreach imgTy = [Image1d, Image1dBuffer] in {
557-
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, Int]>;
558-
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, Int]>;
559-
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, Int]>;
572+
def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
573+
def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
574+
def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
560575
}
561-
def : Builtin<"read_imagef", [Float, ImageType<Image2dDepth, aQual>, VectorType<Int, 2>]>;
562-
def : Builtin<"read_imagef", [Float, ImageType<Image2dArrayDepth, aQual>, VectorType<Int, 4>]>;
576+
def : Builtin<"read_imagef", [Float, ImageType<Image2dDepth, aQual>, VectorType<Int, 2>], Attr.Pure>;
577+
def : Builtin<"read_imagef", [Float, ImageType<Image2dArrayDepth, aQual>, VectorType<Int, 4>], Attr.Pure>;
563578
}
564579

565580
// --- Table 24: Image Write Functions ---
@@ -624,13 +639,13 @@ foreach aQual = ["RO"] in {
624639
foreach name = ["read_imageh"] in {
625640
foreach coordTy = [Int, Float] in {
626641
foreach imgTy = [Image2d, Image1dArray] in {
627-
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<coordTy, 2>]>;
642+
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<coordTy, 2>], Attr.Pure>;
628643
}
629644
foreach imgTy = [Image3d, Image2dArray] in {
630-
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<coordTy, 4>]>;
645+
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<coordTy, 4>], Attr.Pure>;
631646
}
632647
foreach imgTy = [Image1d] in {
633-
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, coordTy]>;
648+
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, coordTy], Attr.Pure>;
634649
}
635650
}
636651
}
@@ -640,13 +655,13 @@ foreach aQual = ["RO"] in {
640655
foreach aQual = ["RO", "RW"] in {
641656
foreach name = ["read_imageh"] in {
642657
foreach imgTy = [Image2d, Image1dArray] in {
643-
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>]>;
658+
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
644659
}
645660
foreach imgTy = [Image3d, Image2dArray] in {
646-
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>]>;
661+
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
647662
}
648663
foreach imgTy = [Image1d, Image1dBuffer] in {
649-
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Int]>;
664+
def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
650665
}
651666
}
652667
}

clang/lib/Sema/SemaLookup.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,17 @@ static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR,
815815
}
816816
NewOpenCLBuiltin->setParams(ParmList);
817817
}
818-
if (!S.getLangOpts().OpenCLCPlusPlus) {
818+
819+
// Add function attributes.
820+
if (OpenCLBuiltin.IsPure)
821+
NewOpenCLBuiltin->addAttr(PureAttr::CreateImplicit(Context));
822+
if (OpenCLBuiltin.IsConst)
823+
NewOpenCLBuiltin->addAttr(ConstAttr::CreateImplicit(Context));
824+
if (OpenCLBuiltin.IsConv)
825+
NewOpenCLBuiltin->addAttr(ConvergentAttr::CreateImplicit(Context));
826+
if ((GenTypeMaxCnt > 1 || Len > 1) && !S.getLangOpts().OpenCLCPlusPlus)
819827
NewOpenCLBuiltin->addAttr(OverloadableAttr::CreateImplicit(Context));
820-
}
828+
821829
LR.addDecl(NewOpenCLBuiltin);
822830
}
823831
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %clang_cc1 -emit-llvm -o - -O0 -triple spir-unknown-unknown -fdeclare-opencl-builtins -finclude-default-header %s | FileCheck %s
2+
3+
// Test that Attr.Const from OpenCLBuiltins.td is lowered to a readnone attribute.
4+
// CHECK-LABEL: @test_const_attr
5+
// CHECK: call i32 @_Z3maxii({{.*}}) [[ATTR_CONST:#[0-9]]]
6+
// CHECK: ret
7+
int test_const_attr(int a) {
8+
return max(a, 2);
9+
}
10+
11+
// Test that Attr.Pure from OpenCLBuiltins.td is lowered to a readonly attribute.
12+
// CHECK-LABEL: @test_pure_attr
13+
// CHECK: call <4 x float> @_Z11read_imagef{{.*}} [[ATTR_PURE:#[0-9]]]
14+
// CHECK: ret
15+
kernel void test_pure_attr(read_only image1d_t img) {
16+
float4 resf = read_imagef(img, 42);
17+
}
18+
19+
// CHECK: attributes [[ATTR_CONST]] =
20+
// CHECK-SAME: readnone
21+
// CHECK: attributes [[ATTR_PURE]] =
22+
// CHECK-SAME: readonly

clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,12 @@ struct OpenCLBuiltinStruct {
271271
// the SignatureTable represent the complete signature. The first type at
272272
// index SigTableIndex is the return type.
273273
const unsigned NumTypes;
274+
// Function attribute __attribute__((pure))
275+
const bool IsPure;
276+
// Function attribute __attribute__((const))
277+
const bool IsConst;
278+
// Function attribute __attribute__((convergent))
279+
const bool IsConv;
274280
// First OpenCL version in which this overload was introduced (e.g. CL20).
275281
const unsigned short MinVersion;
276282
// First OpenCL version in which this overload was removed (e.g. CL20).
@@ -409,6 +415,9 @@ void BuiltinNameEmitter::EmitBuiltinTable() {
409415
for (const auto &Overload : FOM.second) {
410416
OS << " { " << Overload.second << ", "
411417
<< Overload.first->getValueAsListOfDefs("Signature").size() << ", "
418+
<< (Overload.first->getValueAsBit("IsPure")) << ", "
419+
<< (Overload.first->getValueAsBit("IsConst")) << ", "
420+
<< (Overload.first->getValueAsBit("IsConv")) << ", "
412421
<< Overload.first->getValueAsDef("MinVersion")->getValueAsInt("ID")
413422
<< ", "
414423
<< Overload.first->getValueAsDef("MaxVersion")->getValueAsInt("ID")

0 commit comments

Comments
 (0)