Skip to content

Commit b80f10f

Browse files
committed
Support LLVM FP intrinsic in llvm-spirv and enable the corresponding builtin in FE
Signed-off-by: gejin <[email protected]>
1 parent 7867089 commit b80f10f

File tree

7 files changed

+538
-90
lines changed

7 files changed

+538
-90
lines changed

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -165,38 +165,14 @@ static bool IsSyclMathFunc(unsigned BuiltinID) {
165165
case Builtin::BI__builtin_truncl:
166166
case Builtin::BIlroundl:
167167
case Builtin::BI__builtin_lroundl:
168-
case Builtin::BIcopysign:
169-
case Builtin::BI__builtin_copysign:
170-
case Builtin::BIfloor:
171-
case Builtin::BI__builtin_floor:
172168
case Builtin::BIfmax:
173169
case Builtin::BI__builtin_fmax:
174170
case Builtin::BIfmin:
175171
case Builtin::BI__builtin_fmin:
176-
case Builtin::BInearbyint:
177-
case Builtin::BI__builtin_nearbyint:
178-
case Builtin::BIrint:
179-
case Builtin::BI__builtin_rint:
180-
case Builtin::BIround:
181-
case Builtin::BI__builtin_round:
182-
case Builtin::BItrunc:
183-
case Builtin::BI__builtin_trunc:
184-
case Builtin::BIcopysignf:
185-
case Builtin::BI__builtin_copysignf:
186-
case Builtin::BIfloorf:
187-
case Builtin::BI__builtin_floorf:
188172
case Builtin::BIfmaxf:
189173
case Builtin::BI__builtin_fmaxf:
190174
case Builtin::BIfminf:
191175
case Builtin::BI__builtin_fminf:
192-
case Builtin::BInearbyintf:
193-
case Builtin::BI__builtin_nearbyintf:
194-
case Builtin::BIrintf:
195-
case Builtin::BI__builtin_rintf:
196-
case Builtin::BIroundf:
197-
case Builtin::BI__builtin_roundf:
198-
case Builtin::BItruncf:
199-
case Builtin::BI__builtin_truncf:
200176
case Builtin::BIlroundf:
201177
case Builtin::BI__builtin_lroundf:
202178
case Builtin::BI__builtin_fpclassify:
Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsyntax-only -Wno-sycl-2017-compat -verify %s
22
extern "C" float sinf(float);
33
extern "C" float cosf(float);
4+
extern "C" float floorf(float);
45
extern "C" float logf(float);
6+
extern "C" float nearbyintf(float);
7+
extern "C" float rintf(float);
8+
extern "C" float roundf(float);
9+
extern "C" float truncf(float);
10+
extern "C" float copysignf(float, float);
511
extern "C" double sin(double);
612
extern "C" double cos(double);
13+
extern "C" double floor(double);
714
extern "C" double log(double);
15+
extern "C" double nearbyint(double);
16+
extern "C" double rint(double);
17+
extern "C" double round(double);
18+
extern "C" double trunc(double);
19+
extern "C" double copysign(double, double);
820
template <typename name, typename Func>
921
__attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) {
1022
kernelFunc();
@@ -14,21 +26,42 @@ int main() {
1426
kernel<class kernel_function>([=]() {
1527
int acc[1] = {5};
1628
acc[0] *= 2;
17-
acc[0] += (int)sinf(1.0f); // expected-no-error
18-
acc[0] += (int)sin(1.0); // expected-no-error
19-
acc[0] += (int)__builtin_sinf(1.0f); // expected-no-error
20-
acc[0] += (int)__builtin_sin(1.0); // expected-no-error
21-
acc[0] += (int)cosf(1.0f); // expected-no-error
22-
acc[0] += (int)cos(1.0); // expected-no-error
23-
acc[0] += (int)__builtin_cosf(1.0f); // expected-no-error
24-
acc[0] += (int)__builtin_cos(1.0); // expected-no-error
25-
acc[0] += (int)logf(1.0f); // expected-no-error
26-
acc[0] += (int)log(1.0); // expected-no-error
27-
acc[0] += (int)__builtin_logf(1.0f); // expected-no-error
28-
acc[0] += (int)__builtin_log(1.0); // expected-no-error
29-
acc[0] += (int)__builtin_fabsl(-1.0); // expected-error{{builtin is not supported on this target}}
30-
acc[0] += (int)__builtin_cosl(-1.0); // expected-error{{builtin is not supported on this target}}
31-
acc[0] += (int)__builtin_powl(-1.0, 10.0); // expected-error{{builtin is not supported on this target}}
29+
acc[0] += (int)truncf(1.0f); // expected-no-error
30+
acc[0] += (int)trunc(1.0); // expected-no-error
31+
acc[0] += (int)roundf(1.0f); // expected-no-error
32+
acc[0] += (int)round(1.0); // expected-no-error
33+
acc[0] += (int)rintf(1.0f); // expected-no-error
34+
acc[0] += (int)rint(1.0); // expected-no-error
35+
acc[0] += (int)nearbyintf(0.5f); // expected-no-error
36+
acc[0] += (int)nearbyint(0.5); // expected-no-error
37+
acc[0] += (int)floorf(0.5f); // expected-no-error
38+
acc[0] += (int)floor(0.5); // expected-no-error
39+
acc[0] += (int)copysignf(1.0f, -0.5f); // expected-no-error
40+
acc[0] += (int)copysign(1.0, -0.5); // expected-no-error
41+
acc[0] += (int)sinf(1.0f); // expected-no-error
42+
acc[0] += (int)sin(1.0); // expected-no-error
43+
acc[0] += (int)__builtin_sinf(1.0f); // expected-no-error
44+
acc[0] += (int)__builtin_sin(1.0); // expected-no-error
45+
acc[0] += (int)cosf(1.0f); // expected-no-error
46+
acc[0] += (int)cos(1.0); // expected-no-error
47+
acc[0] += (int)__builtin_cosf(1.0f); // expected-no-error
48+
acc[0] += (int)__builtin_cos(1.0); // expected-no-error
49+
acc[0] += (int)logf(1.0f); // expected-no-error
50+
acc[0] += (int)log(1.0); // expected-no-error
51+
acc[0] += (int)__builtin_truncf(1.0f); // expected-no-error
52+
acc[0] += (int)__builtin_trunc(1.0); // expected-no-error
53+
acc[0] += (int)__builtin_rintf(1.0f); // expected-no-error
54+
acc[0] += (int)__builtin_rint(1.0); // expected-no-error
55+
acc[0] += (int)__builtin_nearbyintf(0.5f); // expected-no-error
56+
acc[0] += (int)__builtin_nearbyint(0.5); // expected-no-error
57+
acc[0] += (int)__builtin_floorf(0.5f); // expected-no-error
58+
acc[0] += (int)__builtin_floor(0.5); // expected-no-error
59+
acc[0] += (int)__builtin_copysignf(1.0f, -0.5f); // expected-no-error
60+
acc[0] += (int)__builtin_logf(1.0f); // expected-no-error
61+
acc[0] += (int)__builtin_log(1.0); // expected-no-error
62+
acc[0] += (int)__builtin_fabsl(-1.0); // expected-error{{builtin is not supported on this target}}
63+
acc[0] += (int)__builtin_cosl(-1.0); // expected-error{{builtin is not supported on this target}}
64+
acc[0] += (int)__builtin_powl(-1.0, 10.0); // expected-error{{builtin is not supported on this target}}
3265
});
3366
return 0;
3467
}

llvm-spirv/lib/SPIRV/SPIRVUtil.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,10 +1531,34 @@ bool hasLoopMetadata(const Module *M) {
15311531
// Returns true if type(s) and number of elements (if vector) is valid
15321532
bool checkTypeForSPIRVExtendedInstLowering(IntrinsicInst *II, SPIRVModule *BM) {
15331533
switch (II->getIntrinsicID()) {
1534-
case Intrinsic::fabs:
15351534
case Intrinsic::ceil:
1535+
case Intrinsic::copysign:
1536+
case Intrinsic::cos:
1537+
case Intrinsic::exp:
1538+
case Intrinsic::exp2:
1539+
case Intrinsic::fabs:
1540+
case Intrinsic::floor:
1541+
case Intrinsic::fma:
1542+
case Intrinsic::log:
1543+
case Intrinsic::log10:
1544+
case Intrinsic::log2:
1545+
case Intrinsic::maximum:
15361546
case Intrinsic::maxnum:
1537-
case Intrinsic::nearbyint: {
1547+
case Intrinsic::minimum:
1548+
case Intrinsic::minnum:
1549+
case Intrinsic::nearbyint:
1550+
case Intrinsic::pow:
1551+
case Intrinsic::powi:
1552+
case Intrinsic::rint:
1553+
case Intrinsic::round:
1554+
case Intrinsic::roundeven:
1555+
case Intrinsic::sin:
1556+
case Intrinsic::sqrt:
1557+
case Intrinsic::trunc: {
1558+
// Although some of the intrinsics above take multiple arguments, it is
1559+
// sufficient to check arg 0 because the LLVM Verifier will have checked
1560+
// that all floating point operands have the same type and the second
1561+
// argument of powi is i32.
15381562
Type *Ty = II->getType();
15391563
if (II->getArgOperand(0)->getType() != Ty)
15401564
return false;

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 107 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,12 +2032,33 @@ void addIntelFPGADecorationsForStructMember(SPIRVEntry *E,
20322032
bool LLVMToSPIRV::isKnownIntrinsic(Intrinsic::ID Id) {
20332033
// Known intrinsics usually do not need translation of their declaration
20342034
switch (Id) {
2035+
case Intrinsic::abs:
20352036
case Intrinsic::assume:
20362037
case Intrinsic::bitreverse:
2037-
case Intrinsic::sqrt:
2038-
case Intrinsic::fabs:
2039-
case Intrinsic::abs:
20402038
case Intrinsic::ceil:
2039+
case Intrinsic::copysign:
2040+
case Intrinsic::cos:
2041+
case Intrinsic::exp:
2042+
case Intrinsic::exp2:
2043+
case Intrinsic::fabs:
2044+
case Intrinsic::floor:
2045+
case Intrinsic::fma:
2046+
case Intrinsic::log:
2047+
case Intrinsic::log10:
2048+
case Intrinsic::log2:
2049+
case Intrinsic::maximum:
2050+
case Intrinsic::maxnum:
2051+
case Intrinsic::minimum:
2052+
case Intrinsic::minnum:
2053+
case Intrinsic::nearbyint:
2054+
case Intrinsic::pow:
2055+
case Intrinsic::powi:
2056+
case Intrinsic::rint:
2057+
case Intrinsic::round:
2058+
case Intrinsic::roundeven:
2059+
case Intrinsic::sin:
2060+
case Intrinsic::sqrt:
2061+
case Intrinsic::trunc:
20412062
case Intrinsic::ctpop:
20422063
case Intrinsic::ctlz:
20432064
case Intrinsic::cttz:
@@ -2060,7 +2081,6 @@ bool LLVMToSPIRV::isKnownIntrinsic(Intrinsic::ID Id) {
20602081
case Intrinsic::fmuladd:
20612082
case Intrinsic::memset:
20622083
case Intrinsic::memcpy:
2063-
case Intrinsic::nearbyint:
20642084
case Intrinsic::lifetime_start:
20652085
case Intrinsic::lifetime_end:
20662086
case Intrinsic::dbg_declare:
@@ -2097,6 +2117,45 @@ LLVMToSPIRV::applyRoundingModeConstraint(Value *V, SPIRVInstruction *I) {
20972117
return I;
20982118
}
20992119

2120+
static SPIRVWord getBuiltinIdForIntrinsic(Intrinsic::ID IID) {
2121+
switch (IID) {
2122+
// Note: In some cases the semantics of the OpenCL builtin are not identical
2123+
// to the semantics of the corresponding LLVM IR intrinsic. The LLVM
2124+
// intrinsics handled here assume the default floating point environment
2125+
// (no unmasked exceptions, round-to-nearest-ties-even rounding mode)
2126+
// and assume that the operations have no side effects (FP status flags
2127+
// aren't maintained), so the OpenCL builtin behavior should be
2128+
// acceptable.
2129+
case Intrinsic::ceil: return OpenCLLIB::Ceil;
2130+
case Intrinsic::copysign: return OpenCLLIB::Copysign;
2131+
case Intrinsic::cos: return OpenCLLIB::Cos;
2132+
case Intrinsic::exp: return OpenCLLIB::Exp;
2133+
case Intrinsic::exp2: return OpenCLLIB::Exp2;
2134+
case Intrinsic::fabs: return OpenCLLIB::Fabs;
2135+
case Intrinsic::floor: return OpenCLLIB::Floor;
2136+
case Intrinsic::fma: return OpenCLLIB::Fma;
2137+
case Intrinsic::log: return OpenCLLIB::Log;
2138+
case Intrinsic::log10: return OpenCLLIB::Log10;
2139+
case Intrinsic::log2: return OpenCLLIB::Log2;
2140+
case Intrinsic::maximum: return OpenCLLIB::Fmax;
2141+
case Intrinsic::maxnum: return OpenCLLIB::Fmax;
2142+
case Intrinsic::minimum: return OpenCLLIB::Fmin;
2143+
case Intrinsic::minnum: return OpenCLLIB::Fmin;
2144+
case Intrinsic::nearbyint: return OpenCLLIB::Rint;
2145+
case Intrinsic::pow: return OpenCLLIB::Pow;
2146+
case Intrinsic::powi: return OpenCLLIB::Pown;
2147+
case Intrinsic::rint: return OpenCLLIB::Rint;
2148+
case Intrinsic::round: return OpenCLLIB::Round;
2149+
case Intrinsic::roundeven: return OpenCLLIB::Rint;
2150+
case Intrinsic::sin: return OpenCLLIB::Sin;
2151+
case Intrinsic::sqrt: return OpenCLLIB::Sqrt;
2152+
case Intrinsic::trunc: return OpenCLLIB::Trunc;
2153+
default:
2154+
assert(false && "Builtin ID requested for Unhandled intrinsic!");
2155+
return 0;
2156+
}
2157+
}
2158+
21002159
SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
21012160
SPIRVBasicBlock *BB) {
21022161
auto GetMemoryAccess = [](MemIntrinsic *MI) -> std::vector<SPIRVWord> {
@@ -2139,35 +2198,65 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
21392198
SPIRVValue *Op = transValue(II->getArgOperand(0), BB);
21402199
return BM->addUnaryInst(OpBitReverse, Ty, Op, BB);
21412200
}
2142-
case Intrinsic::sqrt: {
2143-
return BM->addExtInst(transType(II->getType()),
2144-
BM->getExtInstSetId(SPIRVEIS_OpenCL), OpenCLLIB::Sqrt,
2145-
{transValue(II->getOperand(0), BB)}, BB);
2146-
}
2147-
case Intrinsic::fabs: {
2201+
// Unary FP intrinsic
2202+
case Intrinsic::ceil:
2203+
case Intrinsic::cos:
2204+
case Intrinsic::exp:
2205+
case Intrinsic::exp2:
2206+
case Intrinsic::fabs:
2207+
case Intrinsic::floor:
2208+
case Intrinsic::log:
2209+
case Intrinsic::log10:
2210+
case Intrinsic::log2:
2211+
case Intrinsic::nearbyint:
2212+
case Intrinsic::rint:
2213+
case Intrinsic::round:
2214+
case Intrinsic::roundeven:
2215+
case Intrinsic::sin:
2216+
case Intrinsic::sqrt:
2217+
case Intrinsic::trunc: {
21482218
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
21492219
break;
2150-
SPIRVWord ExtOp = OpenCLLIB::Fabs;
2220+
SPIRVWord ExtOp = getBuiltinIdForIntrinsic(II->getIntrinsicID());
21512221
SPIRVType *STy = transType(II->getType());
21522222
std::vector<SPIRVValue *> Ops(1, transValue(II->getArgOperand(0), BB));
21532223
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
21542224
BB);
21552225
}
2156-
case Intrinsic::abs: {
2226+
// Binary FP intrinsics
2227+
case Intrinsic::copysign:
2228+
case Intrinsic::pow:
2229+
case Intrinsic::powi:
2230+
case Intrinsic::maximum:
2231+
case Intrinsic::maxnum:
2232+
case Intrinsic::minimum:
2233+
case Intrinsic::minnum: {
21572234
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
21582235
break;
2159-
// LLVM has only one version of abs and it is only for signed integers. We
2160-
// unconditionally choose SAbs here
2161-
SPIRVWord ExtOp = OpenCLLIB::SAbs;
2236+
SPIRVWord ExtOp = getBuiltinIdForIntrinsic(II->getIntrinsicID());
21622237
SPIRVType *STy = transType(II->getType());
2163-
std::vector<SPIRVValue *> Ops(1, transValue(II->getArgOperand(0), BB));
2238+
std::vector<SPIRVValue *> Ops{transValue(II->getArgOperand(0), BB),
2239+
transValue(II->getArgOperand(1), BB)};
2240+
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
2241+
BB);
2242+
}
2243+
case Intrinsic::fma: {
2244+
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
2245+
break;
2246+
SPIRVWord ExtOp = OpenCLLIB::Fma;
2247+
SPIRVType *STy = transType(II->getType());
2248+
std::vector<SPIRVValue *> Ops{transValue(II->getArgOperand(0), BB),
2249+
transValue(II->getArgOperand(1), BB),
2250+
transValue(II->getArgOperand(2), BB)};
21642251
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
21652252
BB);
21662253
}
2167-
case Intrinsic::ceil: {
2254+
case Intrinsic::abs: {
21682255
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
21692256
break;
2170-
SPIRVWord ExtOp = OpenCLLIB::Ceil;
2257+
// LLVM has only one version of abs and it is only for signed integers. We
2258+
// unconditionally choose SAbs here
2259+
SPIRVWord ExtOp = OpenCLLIB::SAbs;
21712260
SPIRVType *STy = transType(II->getType());
21722261
std::vector<SPIRVValue *> Ops(1, transValue(II->getArgOperand(0), BB));
21732262
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
@@ -2309,16 +2398,6 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
23092398
return BM->addBinaryInst(OpFAdd, Ty, Mul,
23102399
transValue(II->getArgOperand(2), BB), BB);
23112400
}
2312-
case Intrinsic::maxnum: {
2313-
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
2314-
break;
2315-
SPIRVWord ExtOp = OpenCLLIB::Fmax;
2316-
SPIRVType *STy = transType(II->getType());
2317-
std::vector<SPIRVValue *> Ops{transValue(II->getArgOperand(0), BB),
2318-
transValue(II->getArgOperand(1), BB)};
2319-
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
2320-
BB);
2321-
}
23222401
case Intrinsic::usub_sat: {
23232402
// usub.sat(a, b) -> (a > b) ? a - b : 0
23242403
SPIRVType *Ty = transType(II->getType());
@@ -2391,13 +2470,6 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
23912470
Size = 0;
23922471
return BM->addLifetimeInst(OC, transValue(II->getOperand(1), BB), Size, BB);
23932472
}
2394-
case Intrinsic::nearbyint: {
2395-
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
2396-
break;
2397-
return BM->addExtInst(transType(II->getType()),
2398-
BM->getExtInstSetId(SPIRVEIS_OpenCL), OpenCLLIB::Rint,
2399-
{transValue(II->getOperand(0), BB)}, BB);
2400-
}
24012473
// We don't want to mix translation of regular code and debug info, because
24022474
// it creates a mess, therefore translation of debug intrinsics is
24032475
// postponed until LLVMToSPIRVDbgTran::finalizeDebug...() methods.

0 commit comments

Comments
 (0)