Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 58 additions & 29 deletions lib/HLSL/DxilNoops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ using namespace llvm;
namespace {
StringRef kNoopName = "dx.noop";
StringRef kPreservePrefix = "dx.preserve.";
StringRef kNothingName = "dx.nothing";
StringRef kPreserveName = "dx.preserve.value";
StringRef kNothingName = "dx.nothing.a";
StringRef kPreserveName = "dx.preserve.value.a";
}

static Function *GetOrCreateNoopF(Module &M) {
Expand All @@ -115,6 +115,12 @@ static Function *GetOrCreateNoopF(Module &M) {
return NoopF;
}

static Constant *GetConstGep(Constant *Ptr, unsigned Idx0, unsigned Idx1) {
Type *i32Ty = Type::getInt32Ty(Ptr->getContext());
Constant *Indices[] = { ConstantInt::get(i32Ty, Idx0), ConstantInt::get(i32Ty, Idx1) };
return ConstantExpr::getGetElementPtr(nullptr, Ptr, Indices);
}

static bool ShouldPreserve(Value *V) {
if (isa<Constant>(V)) return true;
if (isa<Argument>(V)) return true;
Expand Down Expand Up @@ -190,26 +196,39 @@ static void FindAllStores(Value *Ptr, std::vector<Store_Info> *Stores, std::vect
}
}

static User *GetUniqueUser(Value *V) {
if (V->user_begin() != V->user_end()) {
if (std::next(V->user_begin()) == V->user_end())
return *V->user_begin();
}
return nullptr;
}

static Value *GetOrCreatePreserveCond(Function *F) {
assert(!F->isDeclaration());

Module *M = F->getParent();
GlobalVariable *GV = M->getGlobalVariable(kPreserveName, true);
if (!GV) {
Type *i32Ty = Type::getInt32Ty(M->getContext());
Type *i32ArrayTy = ArrayType::get(i32Ty, 1);

unsigned int Values[1] = { 0 };
Constant *InitialValue = llvm::ConstantDataArray::get(M->getContext(), Values);

GV = new GlobalVariable(*M,
i32Ty, true,
i32ArrayTy, true,
llvm::GlobalValue::InternalLinkage,
llvm::ConstantInt::get(i32Ty, 0), kPreserveName);
InitialValue, kPreserveName);
}

for (User *U : GV->users()) {
LoadInst *LI = cast<LoadInst>(U);
if (LI->getParent()->getParent() == F) {
assert(LI->user_begin() != LI->user_end() &&
std::next(LI->user_begin()) == LI->user_end());

return *LI->user_begin();
GEPOperator *Gep = Gep = cast<GEPOperator>(U);
for (User *GepU : Gep->users()) {
LoadInst *LI = cast<LoadInst>(GepU);
if (LI->getParent()->getParent() == F) {
return GetUniqueUser(LI);
}
}
}

Expand All @@ -220,7 +239,8 @@ static Value *GetOrCreatePreserveCond(Function *F) {

IRBuilder<> B(InsertPt);

LoadInst *Load = B.CreateLoad(GV);
Constant *Gep = GetConstGep(GV, 0, 0);
LoadInst *Load = B.CreateLoad(Gep);
return B.CreateTrunc(Load, B.getInt1Ty());
}

Expand Down Expand Up @@ -461,18 +481,24 @@ class DxilFinalizePreserves : public ModulePass {
}

Instruction *GetFinalNoopInst(Module &M, Instruction *InsertBefore) {
Type *i32Ty = Type::getInt32Ty(M.getContext());
if (!NothingGV) {
NothingGV = M.getGlobalVariable(kNothingName);
if (!NothingGV) {
Type *i32Ty = Type::getInt32Ty(M.getContext());
Type *i32ArrayTy = ArrayType::get(i32Ty, 1);

unsigned int Values[1] = { 0 };
Constant *InitialValue = llvm::ConstantDataArray::get(M.getContext(), Values);

NothingGV = new GlobalVariable(M,
i32Ty, true,
i32ArrayTy, true,
llvm::GlobalValue::InternalLinkage,
llvm::ConstantInt::get(i32Ty, 0), kNothingName);
InitialValue, kNothingName);
}
}

return new llvm::LoadInst(NothingGV, nullptr, InsertBefore);
Constant *Gep = GetConstGep(NothingGV, 0, 0);
return new llvm::LoadInst(Gep, nullptr, InsertBefore);
}

bool LowerPreserves(Module &M);
Expand All @@ -491,20 +517,23 @@ bool DxilFinalizePreserves::LowerPreserves(Module &M) {
GlobalVariable *GV = M.getGlobalVariable(kPreserveName, true);
if (GV) {
for (User *U : GV->users()) {
LoadInst *LI = cast<LoadInst>(U);
assert(LI->user_begin() != LI->user_end() &&
std::next(LI->user_begin()) == LI->user_end());
Instruction *I = cast<Instruction>(*LI->user_begin());

for (User *UU : I->users()) {

SelectInst *P = cast<SelectInst>(UU);
Value *PrevV = P->getTrueValue();
Value *CurV = P->getFalseValue();

if (isa<UndefValue>(PrevV) || isa<Constant>(PrevV)) {
P->setOperand(1, CurV);
Changed = true;
GEPOperator *Gep = cast<GEPOperator>(U);
for (User *GepU : Gep->users()) {
LoadInst *LI = cast<LoadInst>(GepU);
assert(LI->user_begin() != LI->user_end() &&
std::next(LI->user_begin()) == LI->user_end());
Instruction *I = cast<Instruction>(*LI->user_begin());

for (User *UU : I->users()) {

SelectInst *P = cast<SelectInst>(UU);
Value *PrevV = P->getTrueValue();
Value *CurV = P->getFalseValue();

if (isa<UndefValue>(PrevV) || isa<Constant>(PrevV)) {
P->setOperand(1, CurV);
Changed = true;
}
}
}
}
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ Texture2D tex1 : register(t1);

[RootSignature("DescriptorTable(SRV(t0), SRV(t1))")]
float4 main() : SV_Target {
// CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
// CHECK: %[[p_load:[0-9]+]] = load i32, i32*
// CHECK-SAME: @dx.preserve.value
// CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1

double x = 10;
Expand All @@ -26,12 +27,14 @@ float4 main() : SV_Target {
// select i1 %[[p]], double [[c1]], double [[c1]]

Texture2D tex = tex0;
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing

// CHECK: br i1
if (w >= 0) {
tex = tex1;
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// CHECK: br
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ Texture2D tex1 : register(t1);

[RootSignature("DescriptorTable(SRV(t0), SRV(t1))")]
float4 main() : SV_Target {
// CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
// CHECK: %[[p_load:[0-9]+]] = load i32, i32*
// CHECK-SAME: @dx.preserve.value
// CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1

int x = 10;
Expand All @@ -28,12 +29,14 @@ float4 main() : SV_Target {
// select i1 %[[p]], i32 [[c1]], i32 [[c1]]

Texture2D tex = tex0;
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing

// CHECK: br i1
if (w >= 0) {
tex = tex1;
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// CHECK: br
}

Expand Down
21 changes: 14 additions & 7 deletions tools/clang/test/HLSLFileCheck/dxil/debug/noop_out_args.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,35 @@ void baz(inout float x, inout float y) {

[RootSignature("")]
float main() : SV_Target {
// CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
// CHECK: %[[p_load:[0-9]+]] = load i32, i32*
// CHECK-SAME: @dx.preserve.value
// CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1

S s;

// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK: @dx.nothing
foo(s);
// CHECK: select i1 %[[p]]
// CHECK: select i1 %[[p]]
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK: @dx.nothing

// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK: @dx.nothing
bar(s);
// CHECK: fmul
// CHECK: fmul
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK: @dx.nothing

// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK: @dx.nothing
baz(s.x, s.y);
// CHECK: fmul
// CHECK: fmul
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK: @dx.nothing

// CHECK: fadd
return s.x + s.y;
Expand Down
15 changes: 10 additions & 5 deletions tools/clang/test/HLSLFileCheck/dxil/debug/noop_resource_var.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,25 @@ void store_things() {
[numthreads(1, 1, 1)]
[RootSignature("CBV(b0), DescriptorTable(UAV(u0))")]
void main() {
// CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
// CHECK: %[[p_load:[0-9]+]] = load i32, i32*
// CHECK-SAME: @dx.preserve.value
// CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1

// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK: @dx.nothing
my_uav = uav;

// select i1 [[p]],
float ret = foo;

// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK: @dx.nothing
store_things();
// CHECK: unary.f32(i32 13
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK: @dx.nothing
// CHECK: load i32, i32*
// CHECK: @dx.nothing
// CHECK: call void @dx.op.bufferStore.f32(

// CHECK: call void @dx.op.bufferStore.f32(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ void foo() {

[RootSignature("")]
float main() : SV_Target {
// CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
// CHECK: %[[p_load:[0-9]+]] = load i32, i32*
// CHECK-SAME: @dx.preserve.value
// CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1

// CHECK: select i1 %[[p]]
my_glob = 0;

// Function call
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK: @dx.nothing
foo();
// CHECK: select i1 %[[p]]
// void return
Expand Down
35 changes: 22 additions & 13 deletions tools/clang/test/HLSLFileCheck/dxil/debug/noops_call.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,16 @@ float4 depth2(float4 val)
return val;
}

// CHECK: @dx.nothing = internal constant i32 0

[RootSignature("")]
float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target
{
// CHECK: %[[p_load:[0-9]+]] = load i32, i32* @dx.preserve.value
// CHECK: %[[p_load:[0-9]+]] = load i32, i32*
// CHECK-SAME: @dx.preserve.value
// CHECK: %[[p:[0-9]+]] = trunc i32 %[[p_load]] to i1
float4 ret1 = localScopeVar_func(color);
// ** call **
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// CHECK: %[[v1:.+]] = fmul
// CHECK: %[[v2:.+]] = fmul
// CHECK: %[[v3:.+]] = fmul
Expand All @@ -82,7 +82,8 @@ float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target

float4 ret2 = localRegVar_func(ret1);
// ** call **
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// ** copy **
// CHECK: select i1 %[[p]],
// CHECK: select i1 %[[p]],
Expand All @@ -92,7 +93,8 @@ float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target

float4 ret3 = array_func(ret2);
// ** call **
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// CHECK: store
// CHECK: store
// CHECK: store
Expand All @@ -105,7 +107,8 @@ float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target

float4 ret4 = typedef_func(ret3);
// ** call **
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// ** copy **
// CHECK: select i1 %[[p]], float %{{.+}}
// CHECK: select i1 %[[p]], float %{{.+}}
Expand All @@ -115,7 +118,8 @@ float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target

float4 ret5 = global_func(ret4);
// ** call **
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// CHECK: %[[a1:.+]] = fmul
// CHECK: %[[a2:.+]] = fmul
// CHECK: %[[a3:.+]] = fmul
Expand All @@ -128,25 +132,30 @@ float4 main( float4 unused : SV_POSITION, float4 color : COLOR ) : SV_Target

float4 ret6 = depth2(ret5);
// ** call **
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// depth2() {
// ** call **
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// depth3() {
// ** call **
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// depth4() {
// CHECK: %[[b1:.+]] = fmul
// CHECK: %[[b2:.+]] = fmul
// CHECK: %[[b3:.+]] = fmul
// CHECK: %[[b4:.+]] = fmul
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// }
// CHECK: %[[c1:.+]] = fmul
// CHECK: %[[c2:.+]] = fmul
// CHECK: %[[c3:.+]] = fmul
// CHECK: %[[c4:.+]] = fmul
// CHECK: load i32, i32* @dx.nothing
// CHECK: load i32, i32*
// CHECK-SAME: @dx.nothing
// }
// CHECK: %[[d1:.+]] = fmul
// CHECK: %[[d2:.+]] = fmul
Expand Down
Loading