Author: Sven van Haastregt Date: 2019-11-05T10:26:47Z New Revision: 9a8d477a0e00c15d6d33a52486fa931483b7f2ea
URL: https://github.com/llvm/llvm-project/commit/9a8d477a0e00c15d6d33a52486fa931483b7f2ea DIFF: https://github.com/llvm/llvm-project/commit/9a8d477a0e00c15d6d33a52486fa931483b7f2ea.diff LOG: [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 Added: clang/test/CodeGenOpenCL/fdeclare-opencl-builtins.cl Modified: clang/lib/Sema/OpenCLBuiltins.td clang/lib/Sema/SemaLookup.cpp clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/OpenCLBuiltins.td b/clang/lib/Sema/OpenCLBuiltins.td index 298614059467..4f458652ff73 100644 --- a/clang/lib/Sema/OpenCLBuiltins.td +++ b/clang/lib/Sema/OpenCLBuiltins.td @@ -180,10 +180,18 @@ class GenericType<string _Ty, TypeList _TypeList, IntList _VectorList> : let VecWidth = 0; } +// Builtin function attributes. +def Attr { + list<bit> None = [0, 0, 0]; + list<bit> Pure = [1, 0, 0]; + list<bit> Const = [0, 1, 0]; + list<bit> Convergent = [0, 0, 1]; +} + //===----------------------------------------------------------------------===// // OpenCL C class for builtin functions //===----------------------------------------------------------------------===// -class Builtin<string _Name, list<Type> _Signature> { +class Builtin<string _Name, list<Type> _Signature, list<bit> _Attributes = Attr.None> { // Name of the builtin function string Name = _Name; // 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> { list<Type> Signature = _Signature; // OpenCL Extension to which the function belongs (cl_khr_subgroups, ...) string Extension = ""; + // Function attribute __attribute__((pure)) + bit IsPure = _Attributes[0]; + // Function attribute __attribute__((const)) + bit IsConst = _Attributes[1]; + // Function attribute __attribute__((convergent)) + bit IsConv = _Attributes[2]; // Version of OpenCL from which the function is available (e.g.: CL10). // MinVersion is inclusive. Version MinVersion = CL10; @@ -307,11 +321,12 @@ foreach RType = [Float, Double, Half, Char, UChar, Short, UShort, Int, UInt, Long, ULong] in { foreach sat = ["", "_sat"] in { foreach rnd = ["", "_rte", "_rtn", "_rtp", "_rtz"] in { - def : Builtin<"convert_" # RType.Name # sat # rnd, [RType, IType]>; + def : Builtin<"convert_" # RType.Name # sat # rnd, [RType, IType], + Attr.Const>; foreach v = [2, 3, 4, 8, 16] in { def : Builtin<"convert_" # RType.Name # v # sat # rnd, - [VectorType<RType, v>, - VectorType<IType, v>]>; + [VectorType<RType, v>, VectorType<IType, v>], + Attr.Const>; } } } @@ -321,11 +336,11 @@ foreach RType = [Float, Double, Half, Char, UChar, Short, //-------------------------------------------------------------------- // OpenCL v1.1 s6.11.1, v1.2 s6.12.1, v2.0 s6.13.1 - Work-item Functions // --- Table 7 --- -def : Builtin<"get_work_dim", [UInt]>; +def : Builtin<"get_work_dim", [UInt], Attr.Const>; foreach name = ["get_global_size", "get_global_id", "get_local_size", "get_local_id", "get_num_groups", "get_group_id", "get_global_offset"] in { - def : Builtin<name, [Size, UInt]>; + def : Builtin<name, [Size, UInt], Attr.Const>; } let MinVersion = CL20 in { @@ -491,24 +506,24 @@ foreach Type = [Int, UInt] in { foreach name = ["acos", "acosh", "acospi", "asin", "asinh", "asinpi", "atan", "atanh", "atanpi"] in { - def : Builtin<name, [FGenTypeN, FGenTypeN]>; + def : Builtin<name, [FGenTypeN, FGenTypeN], Attr.Const>; } foreach name = ["atan2", "atan2pi"] in { - def : Builtin<name, [FGenTypeN, FGenTypeN, FGenTypeN]>; + def : Builtin<name, [FGenTypeN, FGenTypeN,FGenTypeN], Attr.Const>; } foreach name = ["fmax", "fmin"] in { def : Builtin<name, [FGenTypeN, FGenTypeN, FGenTypeN]>; - def : Builtin<name, [GenTypeFloatVecNoScalar, GenTypeFloatVecNoScalar, Float]>; - def : Builtin<name, [GenTypeDoubleVecNoScalar, GenTypeDoubleVecNoScalar, Double]>; - def : Builtin<name, [GenTypeHalfVecNoScalar, GenTypeHalfVecNoScalar, Half]>; + def : Builtin<name, [GenTypeFloatVecNoScalar, GenTypeFloatVecNoScalar, Float], Attr.Const>; + def : Builtin<name, [GenTypeDoubleVecNoScalar, GenTypeDoubleVecNoScalar, Double], Attr.Const>; + def : Builtin<name, [GenTypeHalfVecNoScalar, GenTypeHalfVecNoScalar, Half], Attr.Const>; } // OpenCL v1.1 s6.11.3, v1.2 s6.12.3, v2.0 s6.13.3 - Integer Functions foreach name = ["max", "min"] in { - def : Builtin<name, [AIGenTypeN, AIGenTypeN, AIGenTypeN]>; - def : Builtin<name, [AIGenTypeNNoScalar, AIGenTypeNNoScalar, AIGenType1]>; + def : Builtin<name, [AIGenTypeN, AIGenTypeN, AIGenTypeN], Attr.Const>; + def : Builtin<name, [AIGenTypeNNoScalar, AIGenTypeNNoScalar, AIGenType1], Attr.Const>; } //-------------------------------------------------------------------- @@ -517,49 +532,49 @@ foreach name = ["max", "min"] in { // --- Table 22: Image Read Functions with Samplers --- foreach imgTy = [Image1d] in { foreach coordTy = [Int, Float] in { - def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, coordTy]>; - def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, coordTy]>; - def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, coordTy]>; + def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, coordTy], Attr.Pure>; + def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, coordTy], Attr.Pure>; + def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, coordTy], Attr.Pure>; } } foreach imgTy = [Image2d, Image1dArray] in { foreach coordTy = [Int, Float] in { - def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>]>; - def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>]>; - def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>]>; + def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>], Attr.Pure>; + def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>], Attr.Pure>; + def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 2>], Attr.Pure>; } } foreach imgTy = [Image3d, Image2dArray] in { foreach coordTy = [Int, Float] in { - def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>]>; - def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>]>; - def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>]>; + def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>], Attr.Pure>; + def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>], Attr.Pure>; + def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, "RO">, Sampler, VectorType<coordTy, 4>], Attr.Pure>; } } foreach coordTy = [Int, Float] in { - def : Builtin<"read_imagef", [Float, ImageType<Image2dDepth, "RO">, Sampler, VectorType<coordTy, 2>]>; - def : Builtin<"read_imagef", [Float, ImageType<Image2dArrayDepth, "RO">, Sampler, VectorType<coordTy, 4>]>; + def : Builtin<"read_imagef", [Float, ImageType<Image2dDepth, "RO">, Sampler, VectorType<coordTy, 2>], Attr.Pure>; + def : Builtin<"read_imagef", [Float, ImageType<Image2dArrayDepth, "RO">, Sampler, VectorType<coordTy, 4>], Attr.Pure>; } // --- Table 23: Sampler-less Read Functions --- foreach aQual = ["RO", "RW"] in { foreach imgTy = [Image2d, Image1dArray] in { - def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>]>; - def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>]>; - def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>]>; + def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>; + def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>; + def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>; } foreach imgTy = [Image3d, Image2dArray] in { - def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>]>; - def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>]>; - def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>]>; + def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>; + def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>; + def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>; } foreach imgTy = [Image1d, Image1dBuffer] in { - def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, Int]>; - def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, Int]>; - def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, Int]>; + def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>; + def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>; + def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>; } - def : Builtin<"read_imagef", [Float, ImageType<Image2dDepth, aQual>, VectorType<Int, 2>]>; - def : Builtin<"read_imagef", [Float, ImageType<Image2dArrayDepth, aQual>, VectorType<Int, 4>]>; + def : Builtin<"read_imagef", [Float, ImageType<Image2dDepth, aQual>, VectorType<Int, 2>], Attr.Pure>; + def : Builtin<"read_imagef", [Float, ImageType<Image2dArrayDepth, aQual>, VectorType<Int, 4>], Attr.Pure>; } // --- Table 24: Image Write Functions --- @@ -624,13 +639,13 @@ foreach aQual = ["RO"] in { foreach name = ["read_imageh"] in { foreach coordTy = [Int, Float] in { foreach imgTy = [Image2d, Image1dArray] in { - def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<coordTy, 2>]>; + def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<coordTy, 2>], Attr.Pure>; } foreach imgTy = [Image3d, Image2dArray] in { - def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<coordTy, 4>]>; + def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<coordTy, 4>], Attr.Pure>; } foreach imgTy = [Image1d] in { - def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, coordTy]>; + def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Sampler, coordTy], Attr.Pure>; } } } @@ -640,13 +655,13 @@ foreach aQual = ["RO"] in { foreach aQual = ["RO", "RW"] in { foreach name = ["read_imageh"] in { foreach imgTy = [Image2d, Image1dArray] in { - def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>]>; + def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>; } foreach imgTy = [Image3d, Image2dArray] in { - def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>]>; + def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>; } foreach imgTy = [Image1d, Image1dBuffer] in { - def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Int]>; + def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>; } } } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 3aedcdc66bcf..44c9d276c3e7 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -815,9 +815,17 @@ static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR, } NewOpenCLBuiltin->setParams(ParmList); } - if (!S.getLangOpts().OpenCLCPlusPlus) { + + // Add function attributes. + if (OpenCLBuiltin.IsPure) + NewOpenCLBuiltin->addAttr(PureAttr::CreateImplicit(Context)); + if (OpenCLBuiltin.IsConst) + NewOpenCLBuiltin->addAttr(ConstAttr::CreateImplicit(Context)); + if (OpenCLBuiltin.IsConv) + NewOpenCLBuiltin->addAttr(ConvergentAttr::CreateImplicit(Context)); + if ((GenTypeMaxCnt > 1 || Len > 1) && !S.getLangOpts().OpenCLCPlusPlus) NewOpenCLBuiltin->addAttr(OverloadableAttr::CreateImplicit(Context)); - } + LR.addDecl(NewOpenCLBuiltin); } } diff --git a/clang/test/CodeGenOpenCL/fdeclare-opencl-builtins.cl b/clang/test/CodeGenOpenCL/fdeclare-opencl-builtins.cl new file mode 100644 index 000000000000..7e3186b18615 --- /dev/null +++ b/clang/test/CodeGenOpenCL/fdeclare-opencl-builtins.cl @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -emit-llvm -o - -O0 -triple spir-unknown-unknown -fdeclare-opencl-builtins -finclude-default-header %s | FileCheck %s + +// Test that Attr.Const from OpenCLBuiltins.td is lowered to a readnone attribute. +// CHECK-LABEL: @test_const_attr +// CHECK: call i32 @_Z3maxii({{.*}}) [[ATTR_CONST:#[0-9]]] +// CHECK: ret +int test_const_attr(int a) { + return max(a, 2); +} + +// Test that Attr.Pure from OpenCLBuiltins.td is lowered to a readonly attribute. +// CHECK-LABEL: @test_pure_attr +// CHECK: call <4 x float> @_Z11read_imagef{{.*}} [[ATTR_PURE:#[0-9]]] +// CHECK: ret +kernel void test_pure_attr(read_only image1d_t img) { + float4 resf = read_imagef(img, 42); +} + +// CHECK: attributes [[ATTR_CONST]] = +// CHECK-SAME: readnone +// CHECK: attributes [[ATTR_PURE]] = +// CHECK-SAME: readonly diff --git a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp index c8975d7bf615..983e267ce9ac 100644 --- a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp +++ b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp @@ -271,6 +271,12 @@ struct OpenCLBuiltinStruct { // the SignatureTable represent the complete signature. The first type at // index SigTableIndex is the return type. const unsigned NumTypes; + // Function attribute __attribute__((pure)) + const bool IsPure; + // Function attribute __attribute__((const)) + const bool IsConst; + // Function attribute __attribute__((convergent)) + const bool IsConv; // First OpenCL version in which this overload was introduced (e.g. CL20). const unsigned short MinVersion; // First OpenCL version in which this overload was removed (e.g. CL20). @@ -409,6 +415,9 @@ void BuiltinNameEmitter::EmitBuiltinTable() { for (const auto &Overload : FOM.second) { OS << " { " << Overload.second << ", " << Overload.first->getValueAsListOfDefs("Signature").size() << ", " + << (Overload.first->getValueAsBit("IsPure")) << ", " + << (Overload.first->getValueAsBit("IsConst")) << ", " + << (Overload.first->getValueAsBit("IsConv")) << ", " << Overload.first->getValueAsDef("MinVersion")->getValueAsInt("ID") << ", " << Overload.first->getValueAsDef("MaxVersion")->getValueAsInt("ID") _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits