|
8 | 8 |
|
9 | 9 | #include "DXILLegalizePass.h" |
10 | 10 | #include "DirectX.h" |
| 11 | +#include "llvm/Analysis/ValueTracking.h" |
11 | 12 | #include "llvm/IR/Function.h" |
12 | 13 | #include "llvm/IR/IRBuilder.h" |
13 | 14 | #include "llvm/IR/InstIterator.h" |
|
20 | 21 |
|
21 | 22 | using namespace llvm; |
22 | 23 |
|
| 24 | +// The goal here will be to emulate freeze by Forcing SSA materialization. |
| 25 | +// We will do this by making the input bound to a real SSA value, |
| 26 | +// not a symbolic poison or undef. The implementation creates a dummy |
| 27 | +// control-flow split that always takes PathA and forces the inputs |
| 28 | +// through a phi node. Creating a dimond CFG makes the compiler |
| 29 | +// commit to one value for the input. |
| 30 | +// entry(%x) |
| 31 | +// | |
| 32 | +// +---+---+ |
| 33 | +// | | |
| 34 | +// pathA(%x) pathB(%x) |
| 35 | +// | | |
| 36 | +// \______/ |
| 37 | +// | |
| 38 | +// merge |
| 39 | +// %frozen = phi [ %x, %pathA ], [ %x, %pathB ] |
| 40 | + |
| 41 | +static void lowerFreeze(FreezeInst *FI) { |
| 42 | + Type *Ty = FI->getType(); |
| 43 | + LLVMContext &Ctx = FI->getContext(); |
| 44 | + BasicBlock *OrigBB = FI->getParent(); |
| 45 | + Value *Input = FI->getOperand(0); |
| 46 | + Function *F = FI->getFunction(); |
| 47 | + |
| 48 | + // Split the block to isolate the freeze instruction |
| 49 | + BasicBlock *MergeBB = OrigBB->splitBasicBlock(FI->getNextNode(), "merge"); |
| 50 | + |
| 51 | + // Remove the unconditional branch inserted by splitBasicBlock |
| 52 | + OrigBB->getTerminator()->eraseFromParent(); |
| 53 | + BasicBlock *PathA = BasicBlock::Create(Ctx, "pathA", F, MergeBB); |
| 54 | + BasicBlock *PathB = BasicBlock::Create(Ctx, "pathB", F, MergeBB); |
| 55 | + |
| 56 | + IRBuilder<> Builder(OrigBB); |
| 57 | + Builder.CreateCondBr(ConstantInt::getTrue(Ctx), PathA, PathB); |
| 58 | + |
| 59 | + IRBuilder<> BuilderA(PathA); |
| 60 | + BuilderA.CreateBr(MergeBB); |
| 61 | + IRBuilder<> BuilderB(PathB); |
| 62 | + BuilderB.CreateBr(MergeBB); |
| 63 | + |
| 64 | + IRBuilder<> BuilderMerge(&MergeBB->front()); |
| 65 | + PHINode *Phi = BuilderMerge.CreatePHI(Ty, 2, "frozen"); |
| 66 | + Phi->addIncoming(Input, PathA); |
| 67 | + Phi->addIncoming(Input, PathB); |
| 68 | + |
| 69 | + FI->replaceAllUsesWith(Phi); |
| 70 | +} |
| 71 | + |
| 72 | +static void legalizeFreeze(Instruction &I, |
| 73 | + SmallVectorImpl<Instruction *> &ToRemove, |
| 74 | + DenseMap<Value *, Value *>) { |
| 75 | + auto *FI = dyn_cast<FreezeInst>(&I); |
| 76 | + if (!FI) |
| 77 | + return; |
| 78 | + |
| 79 | + Value *Input = FI->getOperand(0); |
| 80 | + |
| 81 | + if (isGuaranteedNotToBeUndefOrPoison(Input)) |
| 82 | + FI->replaceAllUsesWith(Input); |
| 83 | + else |
| 84 | + lowerFreeze(FI); |
| 85 | + |
| 86 | + ToRemove.push_back(FI); |
| 87 | +} |
| 88 | + |
23 | 89 | static void fixI8TruncUseChain(Instruction &I, |
24 | 90 | SmallVectorImpl<Instruction *> &ToRemove, |
25 | 91 | DenseMap<Value *, Value *> &ReplacedValues) { |
@@ -169,6 +235,7 @@ class DXILLegalizationPipeline { |
169 | 235 | void initializeLegalizationPipeline() { |
170 | 236 | LegalizationPipeline.push_back(fixI8TruncUseChain); |
171 | 237 | LegalizationPipeline.push_back(downcastI64toI32InsertExtractElements); |
| 238 | + LegalizationPipeline.push_back(legalizeFreeze); |
172 | 239 | } |
173 | 240 | }; |
174 | 241 |
|
|
0 commit comments