1*a1c712faSKit Barton //===- PPCBoolRetToInt.cpp - Convert bool literals to i32 if they are returned ==// 2*a1c712faSKit Barton // 3*a1c712faSKit Barton // The LLVM Compiler Infrastructure 4*a1c712faSKit Barton // 5*a1c712faSKit Barton // This file is distributed under the University of Illinois Open Source 6*a1c712faSKit Barton // License. See LICENSE.TXT for details. 7*a1c712faSKit Barton // 8*a1c712faSKit Barton //===----------------------------------------------------------------------===// 9*a1c712faSKit Barton // 10*a1c712faSKit Barton // This file implements converting i1 values to i32 if they could be more 11*a1c712faSKit Barton // profitably allocated as GPRs rather than CRs. This pass will become totally 12*a1c712faSKit Barton // unnecessary if Register Bank Allocation and Global Instruction Selection ever 13*a1c712faSKit Barton // go upstream. 14*a1c712faSKit Barton // 15*a1c712faSKit Barton // Presently, the pass converts i1 Constants, and Arguments to i32 if the 16*a1c712faSKit Barton // transitive closure of their uses includes only PHINodes, CallInsts, and 17*a1c712faSKit Barton // ReturnInsts. The rational is that arguments are generally passed and returned 18*a1c712faSKit Barton // in GPRs rather than CRs, so casting them to i32 at the LLVM IR level will 19*a1c712faSKit Barton // actually save casts at the Machine Instruction level. 20*a1c712faSKit Barton // 21*a1c712faSKit Barton // It might be useful to expand this pass to add bit-wise operations to the list 22*a1c712faSKit Barton // of safe transitive closure types. Also, we miss some opportunities when LLVM 23*a1c712faSKit Barton // represents logical AND and OR operations with control flow rather than data 24*a1c712faSKit Barton // flow. For example by lowering the expression: return (A && B && C) 25*a1c712faSKit Barton // 26*a1c712faSKit Barton // as: return A ? true : B && C. 27*a1c712faSKit Barton // 28*a1c712faSKit Barton // There's code in SimplifyCFG that code be used to turn control flow in data 29*a1c712faSKit Barton // flow using SelectInsts. Selects are slow on some architectures (P7/P8), so 30*a1c712faSKit Barton // this probably isn't good in general, but for the special case of i1, the 31*a1c712faSKit Barton // Selects could be further lowered to bit operations that are fast everywhere. 32*a1c712faSKit Barton // 33*a1c712faSKit Barton //===----------------------------------------------------------------------===// 34*a1c712faSKit Barton 35*a1c712faSKit Barton #include "PPC.h" 36*a1c712faSKit Barton #include "llvm/Transforms/Scalar.h" 37*a1c712faSKit Barton #include "llvm/ADT/SmallPtrSet.h" 38*a1c712faSKit Barton #include "llvm/ADT/Statistic.h" 39*a1c712faSKit Barton #include "llvm/IR/Constants.h" 40*a1c712faSKit Barton #include "llvm/IR/Dominators.h" 41*a1c712faSKit Barton #include "llvm/IR/Instructions.h" 42*a1c712faSKit Barton #include "llvm/IR/IntrinsicInst.h" 43*a1c712faSKit Barton #include "llvm/Support/raw_ostream.h" 44*a1c712faSKit Barton #include "llvm/Pass.h" 45*a1c712faSKit Barton 46*a1c712faSKit Barton using namespace llvm; 47*a1c712faSKit Barton 48*a1c712faSKit Barton namespace { 49*a1c712faSKit Barton 50*a1c712faSKit Barton #define DEBUG_TYPE "bool-ret-to-int" 51*a1c712faSKit Barton 52*a1c712faSKit Barton STATISTIC(NumBoolRetPromotion, 53*a1c712faSKit Barton "Number of times a bool feeding a RetInst was promoted to an int"); 54*a1c712faSKit Barton STATISTIC(NumBoolCallPromotion, 55*a1c712faSKit Barton "Number of times a bool feeding a CallInst was promoted to an int"); 56*a1c712faSKit Barton STATISTIC(NumBoolToIntPromotion, 57*a1c712faSKit Barton "Total number of times a bool was promoted to an int"); 58*a1c712faSKit Barton 59*a1c712faSKit Barton class PPCBoolRetToInt : public FunctionPass { 60*a1c712faSKit Barton 61*a1c712faSKit Barton static SmallPtrSet<Value *, 8> findAllDefs(Value *V) { 62*a1c712faSKit Barton SmallPtrSet<Value *, 8> Defs; 63*a1c712faSKit Barton SmallVector<Value *, 8> WorkList; 64*a1c712faSKit Barton WorkList.push_back(V); 65*a1c712faSKit Barton Defs.insert(V); 66*a1c712faSKit Barton while (!WorkList.empty()) { 67*a1c712faSKit Barton Value *Curr = WorkList.back(); 68*a1c712faSKit Barton WorkList.pop_back(); 69*a1c712faSKit Barton if (User *CurrUser = dyn_cast<User>(Curr)) 70*a1c712faSKit Barton for (auto &Op : CurrUser->operands()) 71*a1c712faSKit Barton if (Defs.insert(Op).second) 72*a1c712faSKit Barton WorkList.push_back(Op); 73*a1c712faSKit Barton } 74*a1c712faSKit Barton return Defs; 75*a1c712faSKit Barton } 76*a1c712faSKit Barton 77*a1c712faSKit Barton // Translate a i1 value to an equivalent i32 value: 78*a1c712faSKit Barton static Value *translate(Value *V) { 79*a1c712faSKit Barton Type *Int32Ty = Type::getInt32Ty(V->getContext()); 80*a1c712faSKit Barton if (Constant *C = dyn_cast<Constant>(V)) 81*a1c712faSKit Barton return ConstantExpr::getZExt(C, Int32Ty); 82*a1c712faSKit Barton if (PHINode *P = dyn_cast<PHINode>(V)) { 83*a1c712faSKit Barton // Temporarily set the operands to 0. We'll fix this later in 84*a1c712faSKit Barton // runOnUse. 85*a1c712faSKit Barton Value *Zero = Constant::getNullValue(Int32Ty); 86*a1c712faSKit Barton PHINode *Q = 87*a1c712faSKit Barton PHINode::Create(Int32Ty, P->getNumIncomingValues(), P->getName(), P); 88*a1c712faSKit Barton for (unsigned i = 0; i < P->getNumOperands(); ++i) 89*a1c712faSKit Barton Q->addIncoming(Zero, P->getIncomingBlock(i)); 90*a1c712faSKit Barton return Q; 91*a1c712faSKit Barton } 92*a1c712faSKit Barton 93*a1c712faSKit Barton Argument *A = dyn_cast<Argument>(V); 94*a1c712faSKit Barton Instruction *I = dyn_cast<Instruction>(V); 95*a1c712faSKit Barton assert((A || I) && "Unknown value type"); 96*a1c712faSKit Barton 97*a1c712faSKit Barton auto InstPt = 98*a1c712faSKit Barton A ? &*A->getParent()->getEntryBlock().begin() : I->getNextNode(); 99*a1c712faSKit Barton return new ZExtInst(V, Int32Ty, "", InstPt); 100*a1c712faSKit Barton } 101*a1c712faSKit Barton 102*a1c712faSKit Barton typedef SmallPtrSet<const PHINode *, 8> PHINodeSet; 103*a1c712faSKit Barton 104*a1c712faSKit Barton // A PHINode is Promotable if: 105*a1c712faSKit Barton // 1. Its type is i1 AND 106*a1c712faSKit Barton // 2. All of its uses are ReturnInt, CallInst, PHINode, or DbgInfoIntrinsic 107*a1c712faSKit Barton // AND 108*a1c712faSKit Barton // 3. All of its operands are Constant or Argument or 109*a1c712faSKit Barton // CallInst or PHINode AND 110*a1c712faSKit Barton // 4. All of its PHINode uses are Promotable AND 111*a1c712faSKit Barton // 5. All of its PHINode operands are Promotable 112*a1c712faSKit Barton static PHINodeSet getPromotablePHINodes(const Function &F) { 113*a1c712faSKit Barton PHINodeSet Promotable; 114*a1c712faSKit Barton // Condition 1 115*a1c712faSKit Barton for (auto &BB : F) 116*a1c712faSKit Barton for (auto &I : BB) 117*a1c712faSKit Barton if (const PHINode *P = dyn_cast<PHINode>(&I)) 118*a1c712faSKit Barton if (P->getType()->isIntegerTy(1)) 119*a1c712faSKit Barton Promotable.insert(P); 120*a1c712faSKit Barton 121*a1c712faSKit Barton SmallVector<const PHINode *, 8> ToRemove; 122*a1c712faSKit Barton for (const auto &P : Promotable) { 123*a1c712faSKit Barton // Condition 2 and 3 124*a1c712faSKit Barton auto IsValidUser = [] (const Value *V) -> bool { 125*a1c712faSKit Barton return isa<ReturnInst>(V) || isa<CallInst>(V) || isa<PHINode>(V) || 126*a1c712faSKit Barton isa<DbgInfoIntrinsic>(V); 127*a1c712faSKit Barton }; 128*a1c712faSKit Barton auto IsValidOperand = [] (const Value *V) -> bool { 129*a1c712faSKit Barton return isa<Constant>(V) || isa<Argument>(V) || isa<CallInst>(V) || 130*a1c712faSKit Barton isa<PHINode>(V); 131*a1c712faSKit Barton }; 132*a1c712faSKit Barton const auto &Users = P->users(); 133*a1c712faSKit Barton const auto &Operands = P->operands(); 134*a1c712faSKit Barton if (!std::all_of(Users.begin(), Users.end(), IsValidUser) || 135*a1c712faSKit Barton !std::all_of(Operands.begin(), Operands.end(), IsValidOperand)) 136*a1c712faSKit Barton ToRemove.push_back(P); 137*a1c712faSKit Barton } 138*a1c712faSKit Barton 139*a1c712faSKit Barton // Iterate to convergence 140*a1c712faSKit Barton auto IsPromotable = [&Promotable] (const Value *V) -> bool { 141*a1c712faSKit Barton const PHINode *Phi = dyn_cast<PHINode>(V); 142*a1c712faSKit Barton return !Phi || Promotable.count(Phi); 143*a1c712faSKit Barton }; 144*a1c712faSKit Barton while (!ToRemove.empty()) { 145*a1c712faSKit Barton for (auto &User : ToRemove) 146*a1c712faSKit Barton Promotable.erase(User); 147*a1c712faSKit Barton ToRemove.clear(); 148*a1c712faSKit Barton 149*a1c712faSKit Barton for (const auto &P : Promotable) { 150*a1c712faSKit Barton // Condition 4 and 5 151*a1c712faSKit Barton const auto &Users = P->users(); 152*a1c712faSKit Barton const auto &Operands = P->operands(); 153*a1c712faSKit Barton if (!std::all_of(Users.begin(), Users.end(), IsPromotable) || 154*a1c712faSKit Barton !std::all_of(Operands.begin(), Operands.end(), IsPromotable)) 155*a1c712faSKit Barton ToRemove.push_back(P); 156*a1c712faSKit Barton } 157*a1c712faSKit Barton } 158*a1c712faSKit Barton 159*a1c712faSKit Barton return Promotable; 160*a1c712faSKit Barton } 161*a1c712faSKit Barton 162*a1c712faSKit Barton typedef DenseMap<Value *, Value *> B2IMap; 163*a1c712faSKit Barton 164*a1c712faSKit Barton public: 165*a1c712faSKit Barton static char ID; 166*a1c712faSKit Barton PPCBoolRetToInt() : FunctionPass(ID) { 167*a1c712faSKit Barton initializePPCBoolRetToIntPass(*PassRegistry::getPassRegistry()); 168*a1c712faSKit Barton } 169*a1c712faSKit Barton 170*a1c712faSKit Barton bool runOnFunction(Function &F) { 171*a1c712faSKit Barton PHINodeSet PromotablePHINodes = getPromotablePHINodes(F); 172*a1c712faSKit Barton B2IMap Bool2IntMap; 173*a1c712faSKit Barton bool Changed = false; 174*a1c712faSKit Barton for (auto &BB : F) { 175*a1c712faSKit Barton for (auto &I : BB) { 176*a1c712faSKit Barton if (ReturnInst *R = dyn_cast<ReturnInst>(&I)) 177*a1c712faSKit Barton if (F.getReturnType()->isIntegerTy(1)) 178*a1c712faSKit Barton Changed |= 179*a1c712faSKit Barton runOnUse(R->getOperandUse(0), PromotablePHINodes, Bool2IntMap); 180*a1c712faSKit Barton 181*a1c712faSKit Barton if (CallInst *CI = dyn_cast<CallInst>(&I)) 182*a1c712faSKit Barton for (auto &U : CI->operands()) 183*a1c712faSKit Barton if (U->getType()->isIntegerTy(1)) 184*a1c712faSKit Barton Changed |= runOnUse(U, PromotablePHINodes, Bool2IntMap); 185*a1c712faSKit Barton } 186*a1c712faSKit Barton } 187*a1c712faSKit Barton 188*a1c712faSKit Barton return Changed; 189*a1c712faSKit Barton } 190*a1c712faSKit Barton 191*a1c712faSKit Barton static bool runOnUse(Use &U, const PHINodeSet &PromotablePHINodes, 192*a1c712faSKit Barton B2IMap &BoolToIntMap) { 193*a1c712faSKit Barton auto Defs = findAllDefs(U); 194*a1c712faSKit Barton 195*a1c712faSKit Barton // If the values are all Constants or Arguments, don't bother 196*a1c712faSKit Barton if (!std::any_of(Defs.begin(), Defs.end(), isa<Instruction, Value *>)) 197*a1c712faSKit Barton return false; 198*a1c712faSKit Barton 199*a1c712faSKit Barton // Presently, we only know how to handle PHINode, Constant, and Arguments. 200*a1c712faSKit Barton // Potentially, bitwise operations (AND, OR, XOR, NOT) and sign extension 201*a1c712faSKit Barton // could also be handled in the future. 202*a1c712faSKit Barton for (const auto &V : Defs) 203*a1c712faSKit Barton if (!isa<PHINode>(V) && !isa<Constant>(V) && !isa<Argument>(V)) 204*a1c712faSKit Barton return false; 205*a1c712faSKit Barton 206*a1c712faSKit Barton for (const auto &V : Defs) 207*a1c712faSKit Barton if (const PHINode *P = dyn_cast<PHINode>(V)) 208*a1c712faSKit Barton if (!PromotablePHINodes.count(P)) 209*a1c712faSKit Barton return false; 210*a1c712faSKit Barton 211*a1c712faSKit Barton if (isa<ReturnInst>(U.getUser())) 212*a1c712faSKit Barton ++NumBoolRetPromotion; 213*a1c712faSKit Barton if (isa<CallInst>(U.getUser())) 214*a1c712faSKit Barton ++NumBoolCallPromotion; 215*a1c712faSKit Barton ++NumBoolToIntPromotion; 216*a1c712faSKit Barton 217*a1c712faSKit Barton for (const auto &V : Defs) 218*a1c712faSKit Barton if (!BoolToIntMap.count(V)) 219*a1c712faSKit Barton BoolToIntMap[V] = translate(V); 220*a1c712faSKit Barton 221*a1c712faSKit Barton // Replace the operands of the translated instructions. There were set to 222*a1c712faSKit Barton // zero in the translate function. 223*a1c712faSKit Barton for (auto &Pair : BoolToIntMap) { 224*a1c712faSKit Barton User *First = dyn_cast<User>(Pair.first); 225*a1c712faSKit Barton User *Second = dyn_cast<User>(Pair.second); 226*a1c712faSKit Barton assert((!First || Second) && "translated from user to non-user!?"); 227*a1c712faSKit Barton if (First) 228*a1c712faSKit Barton for (unsigned i = 0; i < First->getNumOperands(); ++i) 229*a1c712faSKit Barton Second->setOperand(i, BoolToIntMap[First->getOperand(i)]); 230*a1c712faSKit Barton } 231*a1c712faSKit Barton 232*a1c712faSKit Barton Value *IntRetVal = BoolToIntMap[U]; 233*a1c712faSKit Barton Type *Int1Ty = Type::getInt1Ty(U->getContext()); 234*a1c712faSKit Barton Instruction *I = cast<Instruction>(U.getUser()); 235*a1c712faSKit Barton Value *BackToBool = new TruncInst(IntRetVal, Int1Ty, "backToBool", I); 236*a1c712faSKit Barton U.set(BackToBool); 237*a1c712faSKit Barton 238*a1c712faSKit Barton return true; 239*a1c712faSKit Barton } 240*a1c712faSKit Barton 241*a1c712faSKit Barton void getAnalysisUsage(AnalysisUsage &AU) const { 242*a1c712faSKit Barton AU.addPreserved<DominatorTreeWrapperPass>(); 243*a1c712faSKit Barton FunctionPass::getAnalysisUsage(AU); 244*a1c712faSKit Barton } 245*a1c712faSKit Barton }; 246*a1c712faSKit Barton } 247*a1c712faSKit Barton 248*a1c712faSKit Barton char PPCBoolRetToInt::ID = 0; 249*a1c712faSKit Barton INITIALIZE_PASS(PPCBoolRetToInt, "bool-ret-to-int", 250*a1c712faSKit Barton "Convert i1 constants to i32 if they are returned", 251*a1c712faSKit Barton false, false) 252*a1c712faSKit Barton 253*a1c712faSKit Barton FunctionPass *llvm::createPPCBoolRetToIntPass() { return new PPCBoolRetToInt(); } 254