|
@@ -428,10 +428,123 @@ ModulePass *llvm::createDxilCondenseResourcesPass() {
|
|
|
|
|
|
INITIALIZE_PASS(DxilCondenseResources, "hlsl-dxil-condense", "DXIL Condense Resources", false, false)
|
|
|
|
|
|
-static
|
|
|
-bool LegalizeResourcesPHIs(Module &M, DxilValueCache *DVC) {
|
|
|
+static bool GetConstantLegalGepForSplitAlloca(GetElementPtrInst *gep, DxilValueCache *DVC, int64_t *ret) {
|
|
|
+ if (gep->getNumIndices() != 2) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ConstantInt *Index0 = dyn_cast<ConstantInt>(gep->getOperand(1))) {
|
|
|
+ if (Index0->getLimitedValue() != 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ConstantInt *C = DVC->GetConstInt(gep->getOperand(2))) {
|
|
|
+ int64_t index = C->getSExtValue();
|
|
|
+ *ret = index;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+static bool LegalizeResourceArrays(Module &M, DxilValueCache *DVC) {
|
|
|
+ SmallVector<AllocaInst *,16> Allocas;
|
|
|
+
|
|
|
+ bool Changed = false;
|
|
|
+
|
|
|
+ // Find all allocas
|
|
|
+ for (Function &F : M) {
|
|
|
+ if (F.empty())
|
|
|
+ continue;
|
|
|
+
|
|
|
+ BasicBlock &BB = F.getEntryBlock();
|
|
|
+ for (Instruction &I : BB) {
|
|
|
+ if (AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
|
|
|
+ Type *ty = AI->getAllocatedType();
|
|
|
+ // Only handle single dimentional array. Since this pass runs after MultiDimArrayToOneDimArray,
|
|
|
+ // it should handle all arrays.
|
|
|
+ if (ty->isArrayTy() && hlsl::dxilutil::IsHLSLResourceType(ty->getArrayElementType()))
|
|
|
+ Allocas.push_back(AI);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ SmallVector<AllocaInst *,16> ScalarAllocas;
|
|
|
+ std::unordered_map<GetElementPtrInst *, int64_t> ConstIndices;
|
|
|
+
|
|
|
+ for (AllocaInst *AI : Allocas) {
|
|
|
+ Type *ty = AI->getAllocatedType();
|
|
|
+ Type *resType = ty->getArrayElementType();
|
|
|
+
|
|
|
+ ScalarAllocas.clear();
|
|
|
+ ConstIndices.clear();
|
|
|
+
|
|
|
+ bool SplitAlloca = true;
|
|
|
+
|
|
|
+ for (User *U : AI->users()) {
|
|
|
+ if (GetElementPtrInst *gep = dyn_cast<GetElementPtrInst>(U)) {
|
|
|
+ int64_t index = 0;
|
|
|
+ if (!GetConstantLegalGepForSplitAlloca(gep, DVC, &index)) {
|
|
|
+ SplitAlloca = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Out of bounds. Out of bounds GEP's will trigger and error later.
|
|
|
+ if (index < 0 || index >= (int64_t)ty->getArrayNumElements()) {
|
|
|
+ SplitAlloca = false;
|
|
|
+ Changed = true;
|
|
|
+ dxilutil::EmitErrorOnInstruction(gep, "Accessing resource array with out-out-bounds index.");
|
|
|
+ }
|
|
|
+ ConstIndices[gep] = index;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ SplitAlloca = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (SplitAlloca) {
|
|
|
+
|
|
|
+ IRBuilder<> B(AI);
|
|
|
+ ScalarAllocas.resize(ty->getArrayNumElements());
|
|
|
+
|
|
|
+ for (auto it = AI->user_begin(),end = AI->user_end(); it != end;) {
|
|
|
+ GetElementPtrInst *gep = cast<GetElementPtrInst>(*(it++));
|
|
|
+ assert(ConstIndices.count(gep));
|
|
|
+ int64_t idx = ConstIndices[gep];
|
|
|
+
|
|
|
+ AllocaInst *ScalarAI = ScalarAllocas[idx];
|
|
|
+ if (!ScalarAI) {
|
|
|
+ ScalarAI = B.CreateAlloca(resType);
|
|
|
+ ScalarAllocas[idx] = ScalarAI;
|
|
|
+ }
|
|
|
+
|
|
|
+ gep->replaceAllUsesWith(ScalarAI);
|
|
|
+ gep->eraseFromParent();
|
|
|
+ }
|
|
|
+
|
|
|
+ AI->eraseFromParent();
|
|
|
+
|
|
|
+ Changed = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return Changed;
|
|
|
+}
|
|
|
+
|
|
|
+static bool LegalizeResources(Module &M, DxilValueCache *DVC) {
|
|
|
+
|
|
|
+ bool Changed = false;
|
|
|
+
|
|
|
+ Changed |= LegalizeResourceArrays(M, DVC);
|
|
|
+
|
|
|
// Simple pass to collect resource PHI's
|
|
|
SmallVector<PHINode *, 8> PHIs;
|
|
|
+
|
|
|
for (Function &F : M) {
|
|
|
for (BasicBlock &BB : F) {
|
|
|
for (Instruction &I : BB) {
|
|
@@ -443,12 +556,10 @@ bool LegalizeResourcesPHIs(Module &M, DxilValueCache *DVC) {
|
|
|
else {
|
|
|
break;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- bool Changed = false;
|
|
|
|
|
|
SmallVector<Instruction *, 8> DCEWorklist;
|
|
|
|
|
@@ -572,7 +683,7 @@ public:
|
|
|
|
|
|
{
|
|
|
DxilValueCache *DVC = &getAnalysis<DxilValueCache>();
|
|
|
- bool bLocalChanged = LegalizeResourcesPHIs(M, DVC);
|
|
|
+ bool bLocalChanged = LegalizeResources(M, DVC);
|
|
|
if (bLocalChanged) {
|
|
|
// Remove unused resources.
|
|
|
DM.RemoveResourcesWithUnusedSymbols();
|