PPCBoolRetToInt.cpp 10.0 KB

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