Skip to content

Commit 07a59be

Browse files
jsjiAlexeySachkov
authored andcommitted
Add translation for llvm.modf.* (#3100)
Cherry-pick of KhronosGroup/SPIRV-LLVM-Translator#3100
1 parent d98946f commit 07a59be

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3976,6 +3976,7 @@ bool LLVMToSPIRVBase::isKnownIntrinsic(Intrinsic::ID Id) {
39763976
case Intrinsic::arithmetic_fence:
39773977
case Intrinsic::masked_gather:
39783978
case Intrinsic::masked_scatter:
3979+
case Intrinsic::modf:
39793980
return true;
39803981
default:
39813982
// Unknown intrinsics' declarations should always be translated
@@ -4076,6 +4077,8 @@ static SPIRVWord getBuiltinIdForIntrinsic(Intrinsic::ID IID) {
40764077
return OpenCLLIB::Tanh;
40774078
case Intrinsic::trunc:
40784079
return OpenCLLIB::Trunc;
4080+
case Intrinsic::modf:
4081+
return OpenCLLIB::Modf;
40794082
default:
40804083
assert(false && "Builtin ID requested for Unhandled intrinsic!");
40814084
return 0;
@@ -4273,6 +4276,50 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
42734276
return BM->addExtInst(FTy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
42744277
BB);
42754278
}
4279+
case Intrinsic::modf: {
4280+
// llvm.modf has a single arg --the number to be decomposed-- and returns a
4281+
// struct { double, double }, while OpenCLLIB::modf has two args --the
4282+
// number to be decomposed and a pointer--, returns the fractional part and
4283+
// the integral part is stored in the pointer argument. Therefore, we can't
4284+
// use directly the OpenCLLIB::modf intrinsic. However, we can do some
4285+
// scaffolding to make it work. The idea is to create an alloca instruction
4286+
// to get a ptr, pass this ptr to OpenCLLIB::modf, and then load the value
4287+
// from this ptr to place it in the struct.
4288+
4289+
// llvm.modf returns the fractional part as the first element of the result,
4290+
// and the integral part as the second element of the result. Therefore, the
4291+
// first element is the return value of OpenCLLIB::modf, and the second
4292+
// element is the value loaded from the ptr of the alloca we created.
4293+
4294+
// Create the alloca instruction.
4295+
SPIRVType *IntegralTy = transType(II->getType()->getStructElementType(1));
4296+
// IntegralTy is the type of the result. We want to create a pointer to this
4297+
// that we can pass to OpenCLLIB::modf to store the integral part.
4298+
SPIRVTypePointer *IntegralPtrTy =
4299+
BM->addPointerType(StorageClassFunction, IntegralTy);
4300+
// We need to use the entry BB of the function calling llvm.modf.*, instead
4301+
// of the current BB. For that, we'll find current BB's parent and get its
4302+
// first BB, which is the entry BB of the function.
4303+
SPIRVBasicBlock *EntryBB = BB->getParent()->getBasicBlock(0);
4304+
SPIRVValue *Ptr = BM->addVariable(
4305+
IntegralPtrTy, nullptr, false, spv::internal::LinkageTypeInternal,
4306+
nullptr, "", StorageClassFunction, EntryBB);
4307+
4308+
// Create the OpenCLLIB::modf instruction.
4309+
SPIRVType *FTy = transType(II->getType()->getStructElementType(0));
4310+
SPIRVValue *Arg = transValue(II->getArgOperand(0), BB);
4311+
std::vector<SPIRVValue *> Ops{Arg, Ptr};
4312+
SPIRVValue *Modf = BM->addExtInst(FTy, BM->getExtInstSetId(SPIRVEIS_OpenCL),
4313+
OpenCLLIB::Modf, Ops, BB);
4314+
4315+
// Load the value from the ptr.
4316+
SPIRVValue *IntegralVal = BM->addLoadInst(Ptr, {}, BB, IntegralTy);
4317+
4318+
// Create the struct.
4319+
SPIRVType *STy = transType(II->getType());
4320+
std::vector<SPIRVId> StructVals{Modf->getId(), IntegralVal->getId()};
4321+
return BM->addCompositeConstructInst(STy, StructVals, BB);
4322+
}
42764323
// Binary FP intrinsics
42774324
case Intrinsic::atan2:
42784325
case Intrinsic::copysign:

llvm-spirv/test/llvm-intrinsics/fp-intrinsics.ll

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,21 @@ entry:
436436
}
437437

438438
declare float @llvm.atan2.f32(float, float)
439+
440+
; CHECK: Function [[ResTy:[0-9]+]]
441+
; CHECK: FunctionParameter {{[0-9]+}} [[x:[0-9]+]]
442+
; CHECK: Variable [[PtrTy:[0-9]+]] [[Ptr:[0-9]+]] 7
443+
; CHECK: ExtInst [[var2]] [[ResFirstElem:[0-9]+]] [[extinst_id]] modf [[x]] [[Ptr]]
444+
; CHECK: Load [[var2]] [[ResSecondElem:[0-9]+]] [[Ptr]]
445+
; CHECK: CompositeConstruct [[ResTy]] [[RetVal:[0-9]+]] [[ResFirstElem]] [[ResSecondElem]]
446+
; CHECK: ReturnValue [[RetVal]]
447+
; CHECK: FunctionEnd
448+
449+
450+
define spir_func {double, double} @TestModf(double %x) {
451+
entry:
452+
%t = tail call {double, double} @llvm.modf.f64(double %x)
453+
ret {double, double} %t
454+
}
455+
456+
declare {double, double} @llvm.modf.f64(double)

0 commit comments

Comments
 (0)