SIAnnotateControlFlow.cpp revision cd81d94322a39503e4a3e87b6ee03d4fcb3465fb
1//===-- SIAnnotateControlFlow.cpp - ------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10/// \file 11/// Annotates the control flow with hardware specific intrinsics. 12// 13//===----------------------------------------------------------------------===// 14 15#include "AMDGPU.h" 16#include "llvm/ADT/DepthFirstIterator.h" 17#include "llvm/IR/Constants.h" 18#include "llvm/IR/Dominators.h" 19#include "llvm/IR/Instructions.h" 20#include "llvm/IR/Module.h" 21#include "llvm/Pass.h" 22#include "llvm/Transforms/Utils/BasicBlockUtils.h" 23#include "llvm/Transforms/Utils/SSAUpdater.h" 24 25using namespace llvm; 26 27#define DEBUG_TYPE "si-annotate-control-flow" 28 29namespace { 30 31// Complex types used in this pass 32typedef std::pair<BasicBlock *, Value *> StackEntry; 33typedef SmallVector<StackEntry, 16> StackVector; 34 35// Intrinsic names the control flow is annotated with 36static const char *const IfIntrinsic = "llvm.SI.if"; 37static const char *const ElseIntrinsic = "llvm.SI.else"; 38static const char *const BreakIntrinsic = "llvm.SI.break"; 39static const char *const IfBreakIntrinsic = "llvm.SI.if.break"; 40static const char *const ElseBreakIntrinsic = "llvm.SI.else.break"; 41static const char *const LoopIntrinsic = "llvm.SI.loop"; 42static const char *const EndCfIntrinsic = "llvm.SI.end.cf"; 43 44class SIAnnotateControlFlow : public FunctionPass { 45 46 static char ID; 47 48 Type *Boolean; 49 Type *Void; 50 Type *Int64; 51 Type *ReturnStruct; 52 53 ConstantInt *BoolTrue; 54 ConstantInt *BoolFalse; 55 UndefValue *BoolUndef; 56 Constant *Int64Zero; 57 58 Constant *If; 59 Constant *Else; 60 Constant *Break; 61 Constant *IfBreak; 62 Constant *ElseBreak; 63 Constant *Loop; 64 Constant *EndCf; 65 66 DominatorTree *DT; 67 StackVector Stack; 68 69 bool isTopOfStack(BasicBlock *BB); 70 71 Value *popSaved(); 72 73 void push(BasicBlock *BB, Value *Saved); 74 75 bool isElse(PHINode *Phi); 76 77 void eraseIfUnused(PHINode *Phi); 78 79 void openIf(BranchInst *Term); 80 81 void insertElse(BranchInst *Term); 82 83 Value *handleLoopCondition(Value *Cond, PHINode *Broken); 84 85 void handleLoop(BranchInst *Term); 86 87 void closeControlFlow(BasicBlock *BB); 88 89public: 90 SIAnnotateControlFlow(): 91 FunctionPass(ID) { } 92 93 bool doInitialization(Module &M) override; 94 95 bool runOnFunction(Function &F) override; 96 97 const char *getPassName() const override { 98 return "SI annotate control flow"; 99 } 100 101 void getAnalysisUsage(AnalysisUsage &AU) const override { 102 AU.addRequired<DominatorTreeWrapperPass>(); 103 AU.addPreserved<DominatorTreeWrapperPass>(); 104 FunctionPass::getAnalysisUsage(AU); 105 } 106 107}; 108 109} // end anonymous namespace 110 111char SIAnnotateControlFlow::ID = 0; 112 113/// \brief Initialize all the types and constants used in the pass 114bool SIAnnotateControlFlow::doInitialization(Module &M) { 115 LLVMContext &Context = M.getContext(); 116 117 Void = Type::getVoidTy(Context); 118 Boolean = Type::getInt1Ty(Context); 119 Int64 = Type::getInt64Ty(Context); 120 ReturnStruct = StructType::get(Boolean, Int64, (Type *)nullptr); 121 122 BoolTrue = ConstantInt::getTrue(Context); 123 BoolFalse = ConstantInt::getFalse(Context); 124 BoolUndef = UndefValue::get(Boolean); 125 Int64Zero = ConstantInt::get(Int64, 0); 126 127 If = M.getOrInsertFunction( 128 IfIntrinsic, ReturnStruct, Boolean, (Type *)nullptr); 129 130 Else = M.getOrInsertFunction( 131 ElseIntrinsic, ReturnStruct, Int64, (Type *)nullptr); 132 133 Break = M.getOrInsertFunction( 134 BreakIntrinsic, Int64, Int64, (Type *)nullptr); 135 136 IfBreak = M.getOrInsertFunction( 137 IfBreakIntrinsic, Int64, Boolean, Int64, (Type *)nullptr); 138 139 ElseBreak = M.getOrInsertFunction( 140 ElseBreakIntrinsic, Int64, Int64, Int64, (Type *)nullptr); 141 142 Loop = M.getOrInsertFunction( 143 LoopIntrinsic, Boolean, Int64, (Type *)nullptr); 144 145 EndCf = M.getOrInsertFunction( 146 EndCfIntrinsic, Void, Int64, (Type *)nullptr); 147 148 return false; 149} 150 151/// \brief Is BB the last block saved on the stack ? 152bool SIAnnotateControlFlow::isTopOfStack(BasicBlock *BB) { 153 return !Stack.empty() && Stack.back().first == BB; 154} 155 156/// \brief Pop the last saved value from the control flow stack 157Value *SIAnnotateControlFlow::popSaved() { 158 return Stack.pop_back_val().second; 159} 160 161/// \brief Push a BB and saved value to the control flow stack 162void SIAnnotateControlFlow::push(BasicBlock *BB, Value *Saved) { 163 Stack.push_back(std::make_pair(BB, Saved)); 164} 165 166/// \brief Can the condition represented by this PHI node treated like 167/// an "Else" block? 168bool SIAnnotateControlFlow::isElse(PHINode *Phi) { 169 BasicBlock *IDom = DT->getNode(Phi->getParent())->getIDom()->getBlock(); 170 for (unsigned i = 0, e = Phi->getNumIncomingValues(); i != e; ++i) { 171 if (Phi->getIncomingBlock(i) == IDom) { 172 173 if (Phi->getIncomingValue(i) != BoolTrue) 174 return false; 175 176 } else { 177 if (Phi->getIncomingValue(i) != BoolFalse) 178 return false; 179 180 } 181 } 182 return true; 183} 184 185// \brief Erase "Phi" if it is not used any more 186void SIAnnotateControlFlow::eraseIfUnused(PHINode *Phi) { 187 if (!Phi->hasNUsesOrMore(1)) 188 Phi->eraseFromParent(); 189} 190 191/// \brief Open a new "If" block 192void SIAnnotateControlFlow::openIf(BranchInst *Term) { 193 Value *Ret = CallInst::Create(If, Term->getCondition(), "", Term); 194 Term->setCondition(ExtractValueInst::Create(Ret, 0, "", Term)); 195 push(Term->getSuccessor(1), ExtractValueInst::Create(Ret, 1, "", Term)); 196} 197 198/// \brief Close the last "If" block and open a new "Else" block 199void SIAnnotateControlFlow::insertElse(BranchInst *Term) { 200 Value *Ret = CallInst::Create(Else, popSaved(), "", Term); 201 Term->setCondition(ExtractValueInst::Create(Ret, 0, "", Term)); 202 push(Term->getSuccessor(1), ExtractValueInst::Create(Ret, 1, "", Term)); 203} 204 205/// \brief Recursively handle the condition leading to a loop 206Value *SIAnnotateControlFlow::handleLoopCondition(Value *Cond, PHINode *Broken) { 207 if (PHINode *Phi = dyn_cast<PHINode>(Cond)) { 208 BasicBlock *Parent = Phi->getParent(); 209 PHINode *NewPhi = PHINode::Create(Int64, 0, "", &Parent->front()); 210 Value *Ret = NewPhi; 211 212 // Handle all non-constant incoming values first 213 for (unsigned i = 0, e = Phi->getNumIncomingValues(); i != e; ++i) { 214 Value *Incoming = Phi->getIncomingValue(i); 215 BasicBlock *From = Phi->getIncomingBlock(i); 216 if (isa<ConstantInt>(Incoming)) { 217 NewPhi->addIncoming(Broken, From); 218 continue; 219 } 220 221 Phi->setIncomingValue(i, BoolFalse); 222 Value *PhiArg = handleLoopCondition(Incoming, Broken); 223 NewPhi->addIncoming(PhiArg, From); 224 } 225 226 BasicBlock *IDom = DT->getNode(Parent)->getIDom()->getBlock(); 227 228 for (unsigned i = 0, e = Phi->getNumIncomingValues(); i != e; ++i) { 229 230 Value *Incoming = Phi->getIncomingValue(i); 231 if (Incoming != BoolTrue) 232 continue; 233 234 BasicBlock *From = Phi->getIncomingBlock(i); 235 if (From == IDom) { 236 CallInst *OldEnd = dyn_cast<CallInst>(Parent->getFirstInsertionPt()); 237 if (OldEnd && OldEnd->getCalledFunction() == EndCf) { 238 Value *Args[] = { OldEnd->getArgOperand(0), NewPhi }; 239 Ret = CallInst::Create(ElseBreak, Args, "", OldEnd); 240 continue; 241 } 242 } 243 TerminatorInst *Insert = From->getTerminator(); 244 Value *PhiArg = CallInst::Create(Break, Broken, "", Insert); 245 NewPhi->setIncomingValue(i, PhiArg); 246 } 247 eraseIfUnused(Phi); 248 return Ret; 249 250 } else if (Instruction *Inst = dyn_cast<Instruction>(Cond)) { 251 BasicBlock *Parent = Inst->getParent(); 252 TerminatorInst *Insert = Parent->getTerminator(); 253 Value *Args[] = { Cond, Broken }; 254 return CallInst::Create(IfBreak, Args, "", Insert); 255 256 } else { 257 llvm_unreachable("Unhandled loop condition!"); 258 } 259 return 0; 260} 261 262/// \brief Handle a back edge (loop) 263void SIAnnotateControlFlow::handleLoop(BranchInst *Term) { 264 BasicBlock *Target = Term->getSuccessor(1); 265 PHINode *Broken = PHINode::Create(Int64, 0, "", &Target->front()); 266 267 Value *Cond = Term->getCondition(); 268 Term->setCondition(BoolTrue); 269 Value *Arg = handleLoopCondition(Cond, Broken); 270 271 BasicBlock *BB = Term->getParent(); 272 for (pred_iterator PI = pred_begin(Target), PE = pred_end(Target); 273 PI != PE; ++PI) { 274 275 Broken->addIncoming(*PI == BB ? Arg : Int64Zero, *PI); 276 } 277 278 Term->setCondition(CallInst::Create(Loop, Arg, "", Term)); 279 push(Term->getSuccessor(0), Arg); 280} 281 282/// \brief Close the last opened control flow 283void SIAnnotateControlFlow::closeControlFlow(BasicBlock *BB) { 284 CallInst::Create(EndCf, popSaved(), "", BB->getFirstInsertionPt()); 285} 286 287/// \brief Annotate the control flow with intrinsics so the backend can 288/// recognize if/then/else and loops. 289bool SIAnnotateControlFlow::runOnFunction(Function &F) { 290 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 291 292 for (df_iterator<BasicBlock *> I = df_begin(&F.getEntryBlock()), 293 E = df_end(&F.getEntryBlock()); I != E; ++I) { 294 295 BranchInst *Term = dyn_cast<BranchInst>((*I)->getTerminator()); 296 297 if (!Term || Term->isUnconditional()) { 298 if (isTopOfStack(*I)) 299 closeControlFlow(*I); 300 continue; 301 } 302 303 if (I.nodeVisited(Term->getSuccessor(1))) { 304 if (isTopOfStack(*I)) 305 closeControlFlow(*I); 306 handleLoop(Term); 307 continue; 308 } 309 310 if (isTopOfStack(*I)) { 311 PHINode *Phi = dyn_cast<PHINode>(Term->getCondition()); 312 if (Phi && Phi->getParent() == *I && isElse(Phi)) { 313 insertElse(Term); 314 eraseIfUnused(Phi); 315 continue; 316 } 317 closeControlFlow(*I); 318 } 319 openIf(Term); 320 } 321 322 assert(Stack.empty()); 323 return true; 324} 325 326/// \brief Create the annotation pass 327FunctionPass *llvm::createSIAnnotateControlFlowPass() { 328 return new SIAnnotateControlFlow(); 329} 330