[llvm] [DirectX] Undo SimplifyCFG by reversing select into if else basic blocks (PR #153858)

Joshua Batista via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 15 16:26:53 PDT 2025


================
@@ -622,6 +625,92 @@ legalizeScalarLoadStoreOnArrays(Instruction &I,
   return true;
 }
 
+// Note: Legalization to undo SimplifyCFG. Ideally, SimplifyCFG's
+// TargetTransformInfo would ignore our resource intrinsics, but
+// it doesn't. This Works for a single select; multiple selects on
+// raw buffer loads won’t be legalized. The hasOneUser for ExtractValueInst
+// of dx_resource_load_rawbuffer is enforced in DXILOpLowering,
+// so checking it here is fine.
+static bool
+legalizeBuffLoadSelectCalls(Instruction &I,
+                            SmallVectorImpl<Instruction *> &ToRemove,
+                            DenseMap<Value *, Value *> &) {
+  // Check if this is a dx_resource_load_rawbuffer intrinsic
+  auto *II = dyn_cast<IntrinsicInst>(&I);
+  if (!II || II->getIntrinsicID() != Intrinsic::dx_resource_load_rawbuffer)
+    return false;
+
+  // Check if the first argument is a select instruction
+  Value *Arg0 = II->getArgOperand(0);
+  auto *Sel = dyn_cast<SelectInst>(Arg0);
+  if (!Sel)
+    return false;
+
+  if (!II->hasOneUser())
+    return false;
+  ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(*II->user_begin());
+  if (!EVI->hasOneUser())
+    return false;
+  auto *StoreII = dyn_cast<IntrinsicInst>(*EVI->user_begin());
+  if (!StoreII ||
+      StoreII->getIntrinsicID() != Intrinsic::dx_resource_store_rawbuffer)
+    return false;
+
+  BasicBlock *BB = II->getParent();
+  Function *F = BB->getParent();
+  IRBuilder<> Builder(StoreII);
+
+  // Create new basic blocks
+  BasicBlock *ThenBB = BasicBlock::Create(F->getContext(), "rawbuf.if", F);
+  BasicBlock *ElseBB = BasicBlock::Create(F->getContext(), "rawbuf.else", F);
+  BasicBlock *ContinueBB =
+      BB->splitBasicBlock(std::next(II->getIterator()), "rawbuf.continue");
+
+  // Remove the unconditional branch
+  BB->getTerminator()->eraseFromParent();
+
+  // Create a conditional branch based on the select condition
+  Builder.SetInsertPoint(BB);
+  Builder.CreateCondBr(Sel->getCondition(), ThenBB, ElseBB);
+
+  // Create the true path
+  Builder.SetInsertPoint(ThenBB);
+  Instruction *TrueResourceLoad = II->clone();
+  Instruction *TrueExtract = EVI->clone();
+  Instruction *TrueResourceStore = StoreII->clone();
+  TrueResourceLoad->setOperand(0, Sel->getTrueValue());
+  TrueExtract->setOperand(0, TrueResourceLoad);
+  TrueResourceStore->setOperand(3, TrueExtract);
+  Builder.Insert(TrueResourceLoad);
+  Builder.Insert(TrueExtract);
+  Builder.Insert(TrueResourceStore);
+  Builder.CreateBr(ContinueBB);
+
+  // Create the false path
+  Builder.SetInsertPoint(ElseBB);
+  Instruction *FalseResourceLoad = II->clone();
+  Instruction *FalseExtract = EVI->clone();
+  Instruction *FalseResourceStore = StoreII->clone();
+  FalseResourceLoad->setOperand(0, Sel->getFalseValue());
+  FalseExtract->setOperand(0, FalseResourceLoad);
+  FalseResourceStore->setOperand(3, FalseExtract);
+  Builder.Insert(FalseResourceLoad);
+  Builder.Insert(FalseExtract);
+  Builder.Insert(FalseResourceStore);
+  Builder.CreateBr(ContinueBB);
+
+  // Set up the merge block
+  Builder.SetInsertPoint(ContinueBB);
----------------
bob80905 wrote:

I understand that we want to set the insert point at the continue BB. But the position of the continue BB is before that of the If and Then BB's. Why, was this deliberate?
I'd expect the Continue BB to be positioned after the if and then BBs.
I had also thought that this wouldn't be possible since labels need to be declared ahead of time, but the select instruction references the if / then labels without forward declaration, so it should be possible to put the continue block after the then / else blocks, no?

https://github.com/llvm/llvm-project/pull/153858


More information about the llvm-commits mailing list