-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Adjust bit cast instruction filter for DXIL Prepare pass #142678
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-backend-directx Author: Joshua Batista (bob80905) ChangesThis PR addresses a specific edge case when deciding whether or not to produce a bitcast instruction. Fixes #139013 Full diff: https://github.com/llvm/llvm-project/pull/142678.diff 2 Files Affected:
diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp
index e0068787f5e5a..54e4499830ff0 100644
--- a/llvm/lib/Target/DirectX/DXILPrepare.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp
@@ -148,9 +148,42 @@ class DXILPrepareModule : public ModulePass {
Type *Ty) {
// Omit bitcasts if the incoming value matches the instruction type.
auto It = PointerTypes.find(Operand);
- if (It != PointerTypes.end())
- if (cast<TypedPointerType>(It->second)->getElementType() == Ty)
+ if (It != PointerTypes.end()) {
+ auto OpTy = cast<TypedPointerType>(It->second)->getElementType();
+ if (OpTy == Ty)
return nullptr;
+ }
+
+ // Also omit the bitcast for matching global array types
+ if (auto *GlobalVar = llvm::dyn_cast<llvm::GlobalVariable>(Operand)) {
+ llvm::Type *ValTy = GlobalVar->getValueType();
+
+ if (auto *ArrTy = llvm::dyn_cast<llvm::ArrayType>(ValTy)) {
+ llvm::Type *ElTy = ArrTy->getElementType();
+ if (ElTy == Ty)
+ return nullptr;
+ }
+ }
+
+ // finally, drill down GEP instructions until we get the array
+ // that is being accessed, and compare element types
+ if (auto *GEPInstr = llvm::dyn_cast<llvm::ConstantExpr>(Operand)) {
+ while (GEPInstr->getOpcode() == llvm::Instruction::GetElementPtr) {
+ llvm::Value *OpArg = GEPInstr->getOperand(0);
+
+ if (auto *GlobalVar = llvm::dyn_cast<llvm::GlobalVariable>(OpArg)) {
+ llvm::Constant *initializer = GlobalVar->getInitializer();
+
+ llvm::Type *ValTy = GlobalVar->getValueType();
+ if (auto *ArrTy = llvm::dyn_cast<llvm::ArrayType>(ValTy)) {
+ llvm::Type *ElTy = ArrTy->getElementType();
+ if (ElTy == 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
diff --git a/llvm/test/CodeGen/DirectX/noop_bitcast_global_array_type.ll b/llvm/test/CodeGen/DirectX/noop_bitcast_global_array_type.ll
new file mode 100644
index 0000000000000..4cca76efcf461
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/noop_bitcast_global_array_type.ll
@@ -0,0 +1,39 @@
+; RUN: opt -S --dxil-prepare %s | FileCheck %s
+
+; Test that global arrays do not get a bitcast instruction
+; after the dxil-prepare pass.
+
+target triple = "dxilv1.2-unknown-shadermodel6.2-compute"
+
+@inputTile.1dim = local_unnamed_addr addrspace(3) global [3 x float] zeroinitializer, align 2
+
+define float @testload() local_unnamed_addr {
+ ; NOTE: this would be "bitcast ptr addrspace(3)..." before the change that introduced this test,
+ ; after the dxil-prepare pass is run
+ ; CHECK: load float, ptr addrspace(3) @inputTile.1dim, align 2
+ %v = load float, ptr addrspace(3) @inputTile.1dim, align 2
+
+ ret float %v
+}
+
+define void @teststore() local_unnamed_addr {
+ ; CHECK: store float 2.000000e+00, ptr addrspace(3) @inputTile.1dim, align 2
+ store float 2.000000e+00, ptr addrspace(3) @inputTile.1dim, align 2
+
+ ret void
+}
+
+define float @testGEPConst() local_unnamed_addr {
+ ; CHECK: load float, ptr addrspace(3) getelementptr (float, ptr addrspace(3) @inputTile.1dim, i32 1), align 4
+ %v = load float, ptr addrspace(3) getelementptr (float, ptr addrspace(3) @inputTile.1dim, i32 1), align 4
+
+ ret float %v
+}
+
+define float @testGEPNonConst(i32 %i) local_unnamed_addr {
+ ; CHECK: getelementptr float, ptr addrspace(3) @inputTile.1dim, i32 %i
+ %gep = getelementptr float, ptr addrspace(3) @inputTile.1dim, i32 %i
+ %v = load float, ptr addrspace(3) %gep
+
+ ret float %v
+}
|
define float @testload() local_unnamed_addr { | ||
; NOTE: this would be "bitcast ptr addrspace(3)..." before the change that introduced this test, | ||
; after the dxil-prepare pass is run | ||
; CHECK: load float, ptr addrspace(3) @inputTile.1dim, align 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add check labels and since you are doing that mayve theese should all be CHECK-NEXT
?
} | ||
|
||
// Also omit the bitcast for matching global array types | ||
if (auto *GlobalVar = llvm::dyn_cast<llvm::GlobalVariable>(Operand)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we sure this is just globals? We can have alloca arrays
should we add if (auto *AI = dyn_cast<AllocaInst>(Operand))
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea I think we should add a case for Alloca
} | ||
|
||
// Also omit the bitcast for matching global array types | ||
if (auto *GlobalVar = llvm::dyn_cast<llvm::GlobalVariable>(Operand)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (auto *GlobalVar = llvm::dyn_cast<llvm::GlobalVariable>(Operand)) { | |
if (auto *GlobalVar = dyn_cast<GlobalVariable>(Operand)) { |
if (auto *GlobalVar = llvm::dyn_cast<llvm::GlobalVariable>(Operand)) { | ||
llvm::Type *ValTy = GlobalVar->getValueType(); | ||
|
||
if (auto *ArrTy = llvm::dyn_cast<llvm::ArrayType>(ValTy)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (auto *ArrTy = llvm::dyn_cast<llvm::ArrayType>(ValTy)) { | |
if (auto *ArrTy = dyn_cast<ArrayType>(ValTy)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of commenting on everything single one of these just remove the llvm::
from all these Types and function calls. we have using namespace llvm;
defined on line 34.
2fbbbbe
to
3d1ab27
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alloca case not handled the way I was expecting.
} | ||
|
||
// Also omit the bitcast for alloca instructions | ||
if (auto *AI = dyn_cast<AllocaInst>(Operand)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no what I mean was you see how you are casting ValTy
to ArrTy
? So before that do
if (auto *AI = dyn_cast<AllocaInst>(Operand))
ValTy = AI->getAllocatedType();
ie
Type *ValTy = Operand->getType();
if (auto *GlobalVar = dyn_cast<GlobalVariable>(Operand))
Type *ValTy = GlobalVar->getValueType();
if (auto *AI = dyn_cast<AllocaInst>(Operand))
ValTy = AI->getAllocatedType();
if (auto *ArrTy = dyn_cast<ArrayType>(ValTy)) {
Type *ElTy = ArrTy->getElementType();
if (ElTy == Ty)
return nullptr;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is pseudo code so adjust it to something that works.
Will re-review once the Alloca handling is complete
be91577
to
b143548
Compare
…bit cast instruction filter for DXIL Prepare pass (#142678)" (#143043) - This reverts commit 9ab4c16. - This reverts commit 1d6e8ec. Noticed a really weird behavior where release and debug builds have different codegen for loads with geps after this PR. This is going to take a minute to debug and figure out why so revert seems to make the most sense. ```diff diff --git a/llvm/test/CodeGen/DirectX/flatten-array.ll b/llvm/test/CodeGen/DirectX/flatten-array.ll index 47d7b50..efa9efeff13a 100644 --- a/llvm/test/CodeGen/DirectX/flatten-array.ll +++ b/llvm/test/CodeGen/DirectX/flatten-array.ll @@ -123,7 +123,8 @@ define void @gep_4d_test () { @b = internal global [2 x [3 x [4 x i32]]] zeroinitializer, align 16 define void @global_gep_load() { - ; CHECK: load i32, ptr getelementptr inbounds ([24 x i32], ptr @a.1dim, i32 0, i32 6), align 4 + ; CHECK: %1 = getelementptr inbounds [24 x i32], ptr @a.1dim, i32 0, i32 6 + ; CHECK-NEXT: %2 = load i32, ptr %1, align 4 ; CHECK-NEXT: ret void %1 = getelementptr inbounds [2 x [3 x [4 x i32]]], [2 x [3 x [4 x i32]]]* @A, i32 0, i32 0 %2 = getelementptr inbounds [3 x [4 x i32]], [3 x [4 x i32]]* %1, i32 0, i32 1 @@ -176,7 +177,8 @@ define void @global_incomplete_gep_chain(i32 %row, i32 %col) { } define void @global_gep_store() { - ; CHECK: store i32 1, ptr getelementptr inbounds ([24 x i32], ptr @b.1dim, i32 0, i32 13), align 4 + ; CHECK: %1 = getelementptr inbounds [24 x i32], ptr @b.1dim, i32 0, i32 13 + ; CHECK-NEXT: store i32 1, ptr %1, align 4 ; CHECK-NEXT: ret void ```
This PR addresses a specific edge case when deciding whether or not to produce a bitcast instruction.
Specifically, when the given instruction is a global array, the element type of the array wasn't correctly compared to the return type. In this specific case, if the types are equal, a bitcast shouldn't be created, but it was.
This PR checks to see if the element type of the array is the same as the return type, and if it is, it doesn't create a bitcast instruction.
Fixes #139013