aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-04-14 21:41:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-06-22 18:20:56 +0000
commitbdd1243df58e60e85101c09001d9812a789b6bc4 (patch)
treea1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
parent781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff)
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp73
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);