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,8 +12,9 @@ //===----------------------------------------------------------------------===// #include "DirectX.h" -#include "llvm/ADT/SmallVector.h" +#include "PointerTypeAnalysis.h" #include "llvm/ADT/EnumMatcher.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" @@ -29,28 +30,30 @@ namespace { LLVM_ATTRIBUTE_ALWAYS_INLINE bool isValidForDXIL(Attribute::AttrKind Attr) { - return isInEnumSet(Attr); + return isInEnumSet< + Attribute::AttrKind, Attribute::Alignment, Attribute::AlwaysInline, + Attribute::Builtin, Attribute::ByVal, Attribute::InAlloca, + Attribute::Cold, Attribute::Convergent, Attribute::InlineHint, + Attribute::InReg, Attribute::JumpTable, Attribute::MinSize, + Attribute::Naked, Attribute::Nest, Attribute::NoAlias, + Attribute::NoBuiltin, Attribute::NoCapture, Attribute::NoDuplicate, + Attribute::NoImplicitFloat, Attribute::NoInline, Attribute::NonLazyBind, + Attribute::NonNull, Attribute::Dereferenceable, + Attribute::DereferenceableOrNull, Attribute::NoRedZone, + Attribute::NoReturn, Attribute::NoUnwind, Attribute::OptimizeForSize, + Attribute::OptimizeNone, Attribute::ReadNone, Attribute::ReadOnly, + Attribute::ArgMemOnly, Attribute::Returned, Attribute::ReturnsTwice, + Attribute::SExt, Attribute::StackAlignment, Attribute::StackProtect, + Attribute::StackProtectReq, Attribute::StackProtectStrong, + Attribute::SafeStack, Attribute::StructRet, Attribute::SanitizeAddress, + Attribute::SanitizeThread, Attribute::SanitizeMemory, Attribute::UWTable, + Attribute::ZExt>(Attr); } class DXILPrepareModule : public ModulePass { public: bool runOnModule(Module &M) override { + PointerTypeMap PointerTypes = PointerTypeAnalysis::run(M); for (auto &F : M.functions()) { #define GET_ATTR_NAMES #define ATTRIBUTE_ENUM(First, Second) \ @@ -64,9 +67,15 @@ for (auto &BB : F) { IRBuilder<> Builder(&BB); SmallVector FNegs; + SmallVector Loads; + SmallVector Stores; for (auto &I : BB) { if (I.getOpcode() == Instruction::FNeg) FNegs.push_back(&I); + if (I.getOpcode() == Instruction::Load) + Loads.push_back(cast(&I)); + if (I.getOpcode() == Instruction::Store) + Stores.push_back(cast(&I)); } for (auto I : FNegs) { Builder.SetInsertPoint(I); @@ -75,6 +84,44 @@ I->replaceAllUsesWith(Builder.CreateFSub(Zero, In)); I->eraseFromParent(); } + // Emtting NoOp bitcast instructions allows the ValueEnumerator to be + // unmodified as it reserves instruction IDs during contruction. + for (auto I : Loads) { + // Omit bitcasts if we only have one type + auto It = PointerTypes.find(I->getPointerOperand()); + if (It != PointerTypes.end()) { + if (It->second->getPointerElementType() == I->getType()) + continue; + } + // Insert bitcasts at the top of the block... + Builder.SetInsertPoint(I->getParent(), I->getParent()->begin()); + Value *NoOpBitcast = Builder.Insert( + CastInst::Create(Instruction::BitCast, I->getPointerOperand(), + I->getPointerOperandType()), + ""); + Builder.SetInsertPoint(I); + I->replaceAllUsesWith(Builder.CreateLoad(I->getType(), NoOpBitcast)); + I->eraseFromParent(); + } + for (auto I : Stores) { + // Omit bitcasts if we only have one type + auto It = PointerTypes.find(I->getPointerOperand()); + if (It != PointerTypes.end()) { + if (It->second->getPointerElementType() == + I->getPointerOperandType()) + continue; + } + // Insert bitcasts at the top of the block... + Builder.SetInsertPoint(I->getParent(), I->getParent()->begin()); + Value *NoOpBitcast = Builder.Insert( + CastInst::Create(Instruction::BitCast, I->getPointerOperand(), + I->getPointerOperandType()), + ""); + Builder.SetInsertPoint(I); + I->replaceAllUsesWith( + Builder.CreateStore(I->getValueOperand(), NoOpBitcast)); + I->eraseFromParent(); + } } } return true; 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,14 @@ +; 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: %2 = bitcast ptr %p to ptr +; CHECK-NEXT: store i32 0, ptr %1, align 4 +; 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,11 @@ +; 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