-
Notifications
You must be signed in to change notification settings - Fork 721
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
Allow native vectors for LLVM operations #7155
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -113,13 +113,13 @@ class MatrixBitcastLowerPass : public FunctionPass { | |
|
||
// Lower matrix first. | ||
for (BitCastInst *BCI : matCastSet) { | ||
lowerMatrix(BCI, BCI->getOperand(0)); | ||
lowerMatrix(DM, BCI, BCI->getOperand(0)); | ||
} | ||
return bUpdated; | ||
} | ||
|
||
private: | ||
void lowerMatrix(Instruction *M, Value *A); | ||
void lowerMatrix(DxilModule &DM, Instruction *M, Value *A); | ||
bool hasCallUser(Instruction *M); | ||
}; | ||
|
||
|
@@ -180,7 +180,8 @@ Value *CreateEltGEP(Value *A, unsigned i, Value *zeroIdx, | |
} | ||
} // namespace | ||
|
||
void MatrixBitcastLowerPass::lowerMatrix(Instruction *M, Value *A) { | ||
void MatrixBitcastLowerPass::lowerMatrix(DxilModule &DM, Instruction *M, | ||
Value *A) { | ||
for (auto it = M->user_begin(); it != M->user_end();) { | ||
User *U = *(it++); | ||
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) { | ||
|
@@ -193,31 +194,42 @@ void MatrixBitcastLowerPass::lowerMatrix(Instruction *M, Value *A) { | |
SmallVector<Value *, 2> idxList(GEP->idx_begin(), GEP->idx_end()); | ||
DXASSERT(idxList.size() == 2, | ||
"else not one dim matrix array index to matrix"); | ||
|
||
HLMatrixType MatTy = HLMatrixType::cast(EltTy); | ||
Value *matSize = Builder.getInt32(MatTy.getNumElements()); | ||
idxList.back() = Builder.CreateMul(idxList.back(), matSize); | ||
if (!DM.GetShaderModel()->IsSM69Plus()) { | ||
HLMatrixType MatTy = HLMatrixType::cast(EltTy); | ||
Value *matSize = Builder.getInt32(MatTy.getNumElements()); | ||
idxList.back() = Builder.CreateMul(idxList.back(), matSize); | ||
} | ||
Value *NewGEP = Builder.CreateGEP(A, idxList); | ||
lowerMatrix(GEP, NewGEP); | ||
lowerMatrix(DM, GEP, NewGEP); | ||
DXASSERT(GEP->user_empty(), "else lower matrix fail"); | ||
GEP->eraseFromParent(); | ||
} else { | ||
DXASSERT(0, "invalid GEP for matrix"); | ||
} | ||
} else if (BitCastInst *BCI = dyn_cast<BitCastInst>(U)) { | ||
lowerMatrix(BCI, A); | ||
lowerMatrix(DM, BCI, A); | ||
DXASSERT(BCI->user_empty(), "else lower matrix fail"); | ||
BCI->eraseFromParent(); | ||
} else if (LoadInst *LI = dyn_cast<LoadInst>(U)) { | ||
if (VectorType *Ty = dyn_cast<VectorType>(LI->getType())) { | ||
IRBuilder<> Builder(LI); | ||
Value *zeroIdx = Builder.getInt32(0); | ||
unsigned vecSize = Ty->getNumElements(); | ||
Value *NewVec = UndefValue::get(LI->getType()); | ||
for (unsigned i = 0; i < vecSize; i++) { | ||
Value *GEP = CreateEltGEP(A, i, zeroIdx, Builder); | ||
Value *Elt = Builder.CreateLoad(GEP); | ||
NewVec = Builder.CreateInsertElement(NewVec, Elt, i); | ||
Value *NewVec = nullptr; | ||
if (DM.GetShaderModel()->IsSM69Plus()) { | ||
// Just create a replacement load using the vector pointer. | ||
Instruction *NewLI = LI->clone(); | ||
unsigned VecIdx = NewLI->getNumOperands() - 1; | ||
NewLI->setOperand(VecIdx, A); | ||
Builder.Insert(NewLI); | ||
NewVec = NewLI; | ||
} else { | ||
Value *zeroIdx = Builder.getInt32(0); | ||
unsigned vecSize = Ty->getNumElements(); | ||
NewVec = UndefValue::get(LI->getType()); | ||
for (unsigned i = 0; i < vecSize; i++) { | ||
Value *GEP = CreateEltGEP(A, i, zeroIdx, Builder); | ||
Value *Elt = Builder.CreateLoad(GEP); | ||
NewVec = Builder.CreateInsertElement(NewVec, Elt, i); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed that below this point, there's: } else if (StoreInst *ST = dyn_cast<StoreInst>(U)) { where it still scalarizes the store for the vector. Did you mean to leave that scalarization in? |
||
} | ||
LI->replaceAllUsesWith(NewVec); | ||
LI->eraseFromParent(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,8 @@ | |
// // | ||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
#include "dxc/DXIL/DxilModule.h" | ||
|
||
#include "llvm/IR/Dominators.h" | ||
#include "llvm/IR/Instructions.h" | ||
#include "llvm/Pass.h" | ||
|
@@ -151,6 +153,10 @@ bool DxilEliminateVector::TryRewriteDebugInfoForVector(InsertElementInst *IE) { | |
|
||
bool DxilEliminateVector::runOnFunction(Function &F) { | ||
|
||
if (F.getParent()->HasDxilModule()) | ||
if (F.getParent()->GetDxilModule().GetShaderModel()->IsSM69Plus()) | ||
return false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, this is where we presumably will still want to do something different for vec1, right? |
||
|
||
auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); | ||
DxilValueCache *DVC = &getAnalysis<DxilValueCache>(); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
//===----------------------------------------------------------------------===// | ||
|
||
#include "dxc/DXIL/DxilConstants.h" | ||
#include "dxc/DXIL/DxilModule.h" | ||
#include "dxc/DXIL/DxilOperations.h" | ||
#include "dxc/DXIL/DxilUtil.h" | ||
#include "dxc/HLSL/HLModule.h" | ||
|
@@ -180,10 +181,12 @@ bool LowerTypePass::runOnModule(Module &M) { | |
namespace { | ||
class DynamicIndexingVectorToArray : public LowerTypePass { | ||
bool ReplaceAllVectors; | ||
bool SupportsVectors; | ||
|
||
public: | ||
explicit DynamicIndexingVectorToArray(bool ReplaceAll = false) | ||
: LowerTypePass(ID), ReplaceAllVectors(ReplaceAll) {} | ||
: LowerTypePass(ID), ReplaceAllVectors(ReplaceAll), | ||
SupportsVectors(false) {} | ||
static char ID; // Pass identification, replacement for typeid | ||
void applyOptions(PassOptions O) override; | ||
void dumpConfig(raw_ostream &OS) override; | ||
|
@@ -194,6 +197,7 @@ class DynamicIndexingVectorToArray : public LowerTypePass { | |
Type *lowerType(Type *Ty) override; | ||
Constant *lowerInitVal(Constant *InitVal, Type *NewTy) override; | ||
StringRef getGlobalPrefix() override { return ".v"; } | ||
void initialize(Module &M) override; | ||
|
||
private: | ||
bool HasVectorDynamicIndexing(Value *V); | ||
|
@@ -207,6 +211,11 @@ class DynamicIndexingVectorToArray : public LowerTypePass { | |
void ReplaceAddrSpaceCast(ConstantExpr *CE, Value *A, IRBuilder<> &Builder); | ||
}; | ||
|
||
void DynamicIndexingVectorToArray::initialize(Module &M) { | ||
if (M.HasHLModule()) | ||
SupportsVectors = M.GetHLModule().GetShaderModel()->IsSM69Plus(); | ||
} | ||
|
||
void DynamicIndexingVectorToArray::applyOptions(PassOptions O) { | ||
GetPassOptionBool(O, "ReplaceAllVectors", &ReplaceAllVectors, | ||
ReplaceAllVectors); | ||
|
@@ -286,7 +295,7 @@ void DynamicIndexingVectorToArray::ReplaceStaticIndexingOnVector(Value *V) { | |
StoreInst *stInst = cast<StoreInst>(GEPUser); | ||
Value *val = stInst->getValueOperand(); | ||
Value *ldVal = Builder.CreateLoad(V); | ||
ldVal = Builder.CreateInsertElement(ldVal, val, constIdx); | ||
ldVal = Builder.CreateInsertElement(ldVal, val, constIdx); // UGH | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you want to elaborate on the "UGH" comment? Is it on the general operation being performed, or something specific about this line? |
||
Builder.CreateStore(ldVal, V); | ||
stInst->eraseFromParent(); | ||
} | ||
|
@@ -306,8 +315,11 @@ void DynamicIndexingVectorToArray::ReplaceStaticIndexingOnVector(Value *V) { | |
} | ||
|
||
bool DynamicIndexingVectorToArray::needToLower(Value *V) { | ||
// Only needed where vectors aren't supported. | ||
if (SupportsVectors) | ||
return false; | ||
Type *Ty = V->getType()->getPointerElementType(); | ||
if (dyn_cast<VectorType>(Ty)) { | ||
if (isa<VectorType>(Ty)) { | ||
if (isa<GlobalVariable>(V) || ReplaceAllVectors) { | ||
return true; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1869,7 +1869,8 @@ bool SROAGlobalAndAllocas(HLModule &HLM, bool bHasDbgInfo) { | |
// if | ||
// all its users can be transformed, then split up the aggregate into its | ||
// separate elements. | ||
if (ShouldAttemptScalarRepl(AI) && isSafeAllocaToScalarRepl(AI)) { | ||
if (!HLM.GetShaderModel()->IsSM69Plus() && ShouldAttemptScalarRepl(AI) && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This pass is so complicated as it is, can we capture a bool for DXIL vector support earlier and use that instead of the individual SM 6.9 checks here as well? |
||
isSafeAllocaToScalarRepl(AI)) { | ||
std::vector<Value *> Elts; | ||
IRBuilder<> Builder(dxilutil::FindAllocaInsertionPt(AI)); | ||
bool hasPrecise = HLModule::HasPreciseAttributeWithMetadata(AI); | ||
|
@@ -1945,8 +1946,9 @@ bool SROAGlobalAndAllocas(HLModule &HLM, bool bHasDbgInfo) { | |
continue; | ||
} | ||
|
||
// Flat Global vector if no dynamic vector indexing. | ||
bool bFlatVector = !hasDynamicVectorIndexing(GV); | ||
// Flat Global vector if no dynamic vector indexing and pre-6.9. | ||
bool bFlatVector = | ||
!hasDynamicVectorIndexing(GV) && !HLM.GetShaderModel()->IsSM69Plus(); | ||
|
||
if (bFlatVector) { | ||
GVDbgOffset &dbgOffset = GVDbgOffsetMap[GV]; | ||
|
@@ -1980,10 +1982,12 @@ bool SROAGlobalAndAllocas(HLModule &HLM, bool bHasDbgInfo) { | |
} else { | ||
// SROA_Parameter_HLSL has no access to a domtree, if one is needed, | ||
// it'll be generated | ||
SROAed = SROA_Helper::DoScalarReplacement( | ||
GV, Elts, Builder, bFlatVector, | ||
// TODO: set precise. | ||
/*hasPrecise*/ false, typeSys, DL, DeadInsts, /*DT*/ nullptr); | ||
if (!HLM.GetShaderModel()->IsSM69Plus()) { | ||
SROAed = SROA_Helper::DoScalarReplacement( | ||
GV, Elts, Builder, bFlatVector, | ||
// TODO: set precise. | ||
/*hasPrecise*/ false, typeSys, DL, DeadInsts, /*DT*/ nullptr); | ||
} | ||
} | ||
|
||
if (SROAed) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,8 @@ | |
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "dxc/DXIL/DxilModule.h" | ||
|
||
#include "llvm/ADT/STLExtras.h" | ||
#include "llvm/IR/IRBuilder.h" | ||
#include "llvm/IR/InstVisitor.h" | ||
|
@@ -290,6 +292,10 @@ bool Scalarizer::doInitialization(Module &M) { | |
} | ||
|
||
bool Scalarizer::runOnFunction(Function &F) { | ||
if (F.getParent()->HasDxilModule()) | ||
if (F.getParent()->GetDxilModule().GetShaderModel()->IsSM69Plus()) | ||
return false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we actually want to turn off scalarization entirely? Maybe this is one place where we need to preserve it for vec1 only? |
||
|
||
for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) { | ||
BasicBlock *BB = BBI; | ||
for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE;) { | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -7691,8 +7691,6 @@ def err_hlsl_control_flow_cond_not_scalar : Error< | |||||
"%0 statement conditional expressions must evaluate to a scalar">; | ||||||
def err_hlsl_unsupportedvectortype : Error< | ||||||
"%0 is declared with type %1, but only primitive scalar values are supported">; | ||||||
def err_hlsl_unsupportedvectorsize : Error< | ||||||
"%0 is declared with size %1, but only values 1 through 4 are supported">; | ||||||
def err_hlsl_unsupportedmatrixsize : Error< | ||||||
"%0 is declared with size %1x%2, but only values 1 through 4 are supported">; | ||||||
def err_hlsl_norm_float_only : Error< | ||||||
|
@@ -7843,6 +7841,8 @@ def err_hlsl_load_from_mesh_out_arrays: Error< | |||||
"output arrays of a mesh shader can not be read from">; | ||||||
def err_hlsl_out_indices_array_incorrect_access: Error< | ||||||
"a vector in out indices array must be accessed as a whole">; | ||||||
def err_hlsl_unsupported_long_vector: Error< | ||||||
"Vectors of over 4 elements in %0 are not supported">; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
def err_hlsl_logical_binop_scalar : Error< | ||||||
"operands for short-circuiting logical binary operator must be scalar, for non-scalar types use '%select{and|or}0'">; | ||||||
def err_hlsl_ternary_scalar : Error< | ||||||
|
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.
Can we base the low-level decisions on a descriptively named boolean field in the
MatrixBitcastLowerPass
class, initialized based on the shader model, instead of passing the DxilModule down and checking the shader model each time?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.
Maybe even something about scalarizing operations, rather than anything to do with the native DXIL vector support?