diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-04-14 21:41:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-06-22 18:20:56 +0000 |
commit | bdd1243df58e60e85101c09001d9812a789b6bc4 (patch) | |
tree | a1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp | |
parent | 781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff) | |
parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp | 73 |
1 files changed, 70 insertions, 3 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp index 13c3c12c1b41..20f32ffeba3b 100644 --- a/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp +++ b/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp @@ -18,6 +18,7 @@ #include "SPIRV.h" #include "SPIRVTargetMachine.h" #include "SPIRVUtils.h" +#include "llvm/CodeGen/IntrinsicLowering.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/Transforms/Utils/Cloning.h" @@ -141,6 +142,69 @@ static Function *getOrCreateFunction(Module *M, Type *RetTy, return NewF; } +static void lowerIntrinsicToFunction(Module *M, IntrinsicInst *Intrinsic) { + // For @llvm.memset.* intrinsic cases with constant value and length arguments + // are emulated via "storing" a constant array to the destination. For other + // cases we wrap the intrinsic in @spirv.llvm_memset_* function and expand the + // intrinsic to a loop via expandMemSetAsLoop(). + if (auto *MSI = dyn_cast<MemSetInst>(Intrinsic)) + if (isa<Constant>(MSI->getValue()) && isa<ConstantInt>(MSI->getLength())) + return; // It is handled later using OpCopyMemorySized. + + std::string FuncName = lowerLLVMIntrinsicName(Intrinsic); + if (Intrinsic->isVolatile()) + FuncName += ".volatile"; + // Redirect @llvm.intrinsic.* call to @spirv.llvm_intrinsic_* + Function *F = M->getFunction(FuncName); + if (F) { + Intrinsic->setCalledFunction(F); + return; + } + // TODO copy arguments attributes: nocapture writeonly. + FunctionCallee FC = + M->getOrInsertFunction(FuncName, Intrinsic->getFunctionType()); + auto IntrinsicID = Intrinsic->getIntrinsicID(); + Intrinsic->setCalledFunction(FC); + + F = dyn_cast<Function>(FC.getCallee()); + assert(F && "Callee must be a function"); + + switch (IntrinsicID) { + case Intrinsic::memset: { + auto *MSI = static_cast<MemSetInst *>(Intrinsic); + Argument *Dest = F->getArg(0); + Argument *Val = F->getArg(1); + Argument *Len = F->getArg(2); + Argument *IsVolatile = F->getArg(3); + Dest->setName("dest"); + Val->setName("val"); + Len->setName("len"); + IsVolatile->setName("isvolatile"); + BasicBlock *EntryBB = BasicBlock::Create(M->getContext(), "entry", F); + IRBuilder<> IRB(EntryBB); + auto *MemSet = IRB.CreateMemSet(Dest, Val, Len, MSI->getDestAlign(), + MSI->isVolatile()); + IRB.CreateRetVoid(); + expandMemSetAsLoop(cast<MemSetInst>(MemSet)); + MemSet->eraseFromParent(); + break; + } + case Intrinsic::bswap: { + BasicBlock *EntryBB = BasicBlock::Create(M->getContext(), "entry", F); + IRBuilder<> IRB(EntryBB); + auto *BSwap = IRB.CreateIntrinsic(Intrinsic::bswap, Intrinsic->getType(), + F->getArg(0)); + IRB.CreateRet(BSwap); + IntrinsicLowering IL(M->getDataLayout()); + IL.LowerIntrinsicCall(BSwap); + break; + } + default: + break; + } + return; +} + static void lowerFunnelShifts(Module *M, IntrinsicInst *FSHIntrinsic) { // Get a separate function - otherwise, we'd have to rework the CFG of the // current one. Then simply replace the intrinsic uses with a call to the new @@ -219,7 +283,7 @@ static void buildUMulWithOverflowFunc(Module *M, Function *UMulFunc) { // umul.with.overflow intrinsic return a structure, where the first element // is the multiplication result, and the second is an overflow bit. Type *StructTy = UMulFunc->getReturnType(); - Value *Agg = IRB.CreateInsertValue(UndefValue::get(StructTy), Mul, {0}); + Value *Agg = IRB.CreateInsertValue(PoisonValue::get(StructTy), Mul, {0}); Value *Res = IRB.CreateInsertValue(Agg, Overflow, {1}); IRB.CreateRet(Res); } @@ -248,8 +312,11 @@ static void substituteIntrinsicCalls(Module *M, Function *F) { if (!CF || !CF->isIntrinsic()) continue; auto *II = cast<IntrinsicInst>(Call); - if (II->getIntrinsicID() == Intrinsic::fshl || - II->getIntrinsicID() == Intrinsic::fshr) + if (II->getIntrinsicID() == Intrinsic::memset || + II->getIntrinsicID() == Intrinsic::bswap) + lowerIntrinsicToFunction(M, II); + else if (II->getIntrinsicID() == Intrinsic::fshl || + II->getIntrinsicID() == Intrinsic::fshr) lowerFunnelShifts(M, II); else if (II->getIntrinsicID() == Intrinsic::umul_with_overflow) lowerUMulWithOverflow(M, II); |