diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp --- a/llvm/lib/Target/DirectX/DXILPrepare.cpp +++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "DirectX.h" +#include "PointerTypeAnalysis.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/Passes.h" @@ -25,6 +26,7 @@ #define DEBUG_TYPE "dxil-prepare" using namespace llvm; +using namespace llvm::dxil; namespace { @@ -78,8 +80,27 @@ } class DXILPrepareModule : public ModulePass { + + static Value *maybeGenerateBitcast(IRBuilder<> &Builder, + PointerTypeMap &PointerTypes, + Instruction &Inst, Value *Operand, + Type *Ty) { + // Omit bitcasts if the incoming value matches the instruction type. + auto It = PointerTypes.find(Operand); + if (It != PointerTypes.end()) + if (cast(It->second)->getElementType() == Ty) + return nullptr; + // Insert bitcasts where we are removing the instruction. + Builder.SetInsertPoint(&Inst); + // This code only gets hit in opaque-pointer mode, so the type of the + // pointer doesn't matter. + return Builder.Insert(CastInst::Create(Instruction::BitCast, Operand, + Builder.getInt8PtrTy())); + } + public: bool runOnModule(Module &M) override { + PointerTypeMap PointerTypes = PointerTypeAnalysis::run(M); AttributeMask AttrMask; for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; I = Attribute::AttrKind(I + 1)) { @@ -89,7 +110,7 @@ for (auto &F : M.functions()) { F.removeFnAttrs(AttrMask); F.removeRetAttrs(AttrMask); - for (size_t Idx = 0; Idx < F.arg_size(); ++Idx) + for (size_t Idx = 0, End = F.arg_size(); Idx < End; ++Idx) F.removeParamAttrs(Idx, AttrMask); for (auto &BB : F) { @@ -101,6 +122,41 @@ Value *Zero = ConstantFP::get(In->getType(), -0.0); I.replaceAllUsesWith(Builder.CreateFSub(Zero, In)); I.eraseFromParent(); + continue; + } + // Only insert bitcasts if the IR is using opaque pointers. + if (!M.getContext().hasSetOpaquePointersValue()) + continue; + + // Emtting NoOp bitcast instructions allows the ValueEnumerator to be + // unmodified as it reserves instruction IDs during contruction. + if (auto LI = dyn_cast(&I)) { + if (Value *NoOpBitcast = maybeGenerateBitcast( + Builder, PointerTypes, I, LI->getPointerOperand(), + LI->getType())) { + LI->replaceAllUsesWith( + Builder.CreateLoad(LI->getType(), NoOpBitcast)); + LI->eraseFromParent(); + } + continue; + } + if (auto SI = dyn_cast(&I)) { + if (Value *NoOpBitcast = maybeGenerateBitcast( + Builder, PointerTypes, I, SI->getPointerOperand(), + SI->getValueOperand()->getType())) { + + SI->replaceAllUsesWith( + Builder.CreateStore(SI->getValueOperand(), NoOpBitcast)); + SI->eraseFromParent(); + } + continue; + } + if (auto GEP = dyn_cast(&I)) { + if (Value *NoOpBitcast = maybeGenerateBitcast( + Builder, PointerTypes, I, GEP->getPointerOperand(), + GEP->getResultElementType())) + GEP->setOperand(0, NoOpBitcast); + continue; } } } diff --git a/llvm/test/CodeGen/DirectX/conflicting-bitcast-insert.ll b/llvm/test/CodeGen/DirectX/conflicting-bitcast-insert.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/conflicting-bitcast-insert.ll @@ -0,0 +1,26 @@ +; RUN: llc --filetype=asm %s -o - | FileCheck %s +target triple = "dxil-unknown-unknown" + +define i64 @test(ptr %p) { + store i32 0, ptr %p + %v = load i64, ptr %p + ret i64 %v +} + +; CHECK: define i64 @test(ptr %p) { +; CHECK-NEXT: %1 = bitcast ptr %p to ptr +; CHECK-NEXT: store i32 0, ptr %1, align 4 +; CHECK-NEXT: %2 = bitcast ptr %p to ptr +; CHECK-NEXT: %3 = load i64, ptr %2, align 8 + +define i64 @testGEP(ptr %p) { + %ptr = getelementptr i32, ptr %p, i32 4 + %val = load i64, ptr %p + ret i64 %val +} + +; CHECK: define i64 @testGEP(ptr %p) { +; CHECK-NEXT: %1 = bitcast ptr %p to ptr +; CHECK-NEXT: %ptr = getelementptr i32, ptr %1, i32 4 +; CHECK-NEXT: %2 = bitcast ptr %p to ptr +; CHECK-NEXT: %3 = load i64, ptr %2, align 8 diff --git a/llvm/test/CodeGen/DirectX/omit-bitcast-insert.ll b/llvm/test/CodeGen/DirectX/omit-bitcast-insert.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/omit-bitcast-insert.ll @@ -0,0 +1,32 @@ +; RUN: llc --filetype=asm %s -o - | FileCheck %s +target triple = "dxil-unknown-unknown" + +define i64 @test(ptr %p) { + %v = load i64, ptr %p + ret i64 %v +} + +; CHECK: define i64 @test(ptr %p) { +; CHECK-NEXT: %v = load i64, ptr %p, align 8 +; CHECK-NEXT: ret i64 %v + +define i64 @test2(ptr %p) { + store i64 0, ptr %p + %v = load i64, ptr %p + ret i64 %v +} + +; CHECK: define i64 @test2(ptr %p) { +; CHECK-NEXT: store i64 0, ptr %p +; CHECK-NEXT: %v = load i64, ptr %p, align 8 +; CHECK-NEXT: ret i64 %v + +define i32 @test3(ptr %0) { + %2 = getelementptr i32, ptr %0, i32 4 + %3 = load i32, ptr %2 + ret i32 %3 +} + +; CHECK: define i32 @test3(ptr %0) { +; CHECK-NEXT: %2 = getelementptr i32, ptr %0, i32 4 +; CHECK-NEXT: %3 = load i32, ptr %2