#include DIVINE_RELAX_WARNINGS #include #include #include #include #include DIVINE_UNRELAX_WARNINGS #include using namespace llvm; char lart::LowerSelectPass::id = 0; // This pass converts SelectInst instructions into conditional branch and PHI // instructions. bool lart::LowerSelectPass::runOnFunction( Function &fn ) { auto selects = query::query( fn ).flatten() .map( query::refToPtr ) .map( query::llvmdyncast< llvm::SelectInst > ) .filter( query::notnull ) .freeze(); for ( auto sel : selects ) lower( sel ); return !selects.empty(); } void lart::LowerSelectPass::lower( SelectInst *si ) { BasicBlock * bb = si->getParent(); // Split this basic block in half right before the select instruction. BasicBlock * newCont = bb->splitBasicBlock( si, bb->getName()+".selectcont" ); // Make the true block, and make it branch to the continue block. BasicBlock * newTrue = BasicBlock::Create( bb->getContext(), bb->getName()+".selecttrue", bb->getParent(), newCont ); BranchInst::Create( newCont, newTrue ); // Make the unconditional branch in the incoming block be a // conditional branch on the select predicate. bb->getInstList().erase( bb->getTerminator() ); BranchInst::Create( newTrue, newCont, si->getCondition(), bb ); // Create a new PHI node in the cont block with the entries we need. std::string name = si->getName().str(); si->setName( "" ); PHINode *pn = PHINode::Create( si->getType(), 2, name, &*newCont->begin() ); pn->addIncoming( si->getTrueValue(), newTrue ); pn->addIncoming( si->getFalseValue(), bb ); // Use the PHI instead of the select. si->replaceAllUsesWith( pn ); newCont->getInstList().erase( si ); }