LCOV - code coverage report
Current view: top level - lib/Target/AArch64 - AArch64AddressTypePromotion.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 7 152 4.6 %
Date: 2017-05-05 14:46:47 Functions: 4 17 23.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- AArch64AddressTypePromotion.cpp --- Promote type for addr accesses -==//
       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             : // This pass tries to promote the computations use to obtained a sign extended
      11             : // value used into memory accesses.
      12             : // E.g.
      13             : // a = add nsw i32 b, 3
      14             : // d = sext i32 a to i64
      15             : // e = getelementptr ..., i64 d
      16             : //
      17             : // =>
      18             : // f = sext i32 b to i64
      19             : // a = add nsw i64 f, 3
      20             : // e = getelementptr ..., i64 a
      21             : //
      22             : // This is legal to do if the computations are marked with either nsw or nuw
      23             : // markers. Moreover, the current heuristic is simple: it does not create new
      24             : // sext operations, i.e., it gives up when a sext would have forked (e.g., if a
      25             : // = add i32 b, c, two sexts are required to promote the computation).
      26             : //
      27             : // FIXME: This pass may be useful for other targets too.
      28             : // ===---------------------------------------------------------------------===//
      29             : 
      30             : #include "AArch64.h"
      31             : #include "llvm/ADT/DenseMap.h"
      32             : #include "llvm/ADT/SmallPtrSet.h"
      33             : #include "llvm/ADT/SmallVector.h"
      34             : #include "llvm/ADT/StringRef.h"
      35             : #include "llvm/IR/Constants.h"
      36             : #include "llvm/IR/Dominators.h"
      37             : #include "llvm/IR/Function.h"
      38             : #include "llvm/IR/InstrTypes.h"
      39             : #include "llvm/IR/Instruction.h"
      40             : #include "llvm/IR/Instructions.h"
      41             : #include "llvm/IR/Operator.h"
      42             : #include "llvm/IR/Type.h"
      43             : #include "llvm/IR/Use.h"
      44             : #include "llvm/IR/User.h"
      45             : #include "llvm/Pass.h"
      46             : #include "llvm/Support/Casting.h"
      47             : #include "llvm/Support/CommandLine.h"
      48             : #include "llvm/Support/Debug.h"
      49             : #include "llvm/Support/raw_ostream.h"
      50             : #include <cassert>
      51             : 
      52             : using namespace llvm;
      53             : 
      54             : #define DEBUG_TYPE "aarch64-type-promotion"
      55             : 
      56             : static cl::opt<bool>
      57      131740 : EnableMerge("aarch64-type-promotion-merge", cl::Hidden,
      58      197610 :             cl::desc("Enable merging of redundant sexts when one is dominating"
      59             :                      " the other."),
      60      329350 :             cl::init(true));
      61             : 
      62             : #define AARCH64_TYPE_PROMO_NAME "AArch64 Address Type Promotion"
      63             : 
      64             : //===----------------------------------------------------------------------===//
      65             : //                       AArch64AddressTypePromotion
      66             : //===----------------------------------------------------------------------===//
      67             : 
      68             : namespace {
      69             : 
      70           0 : class AArch64AddressTypePromotion : public FunctionPass {
      71             : public:
      72             :   static char ID;
      73             : 
      74           0 :   AArch64AddressTypePromotion() : FunctionPass(ID) {
      75           0 :     initializeAArch64AddressTypePromotionPass(*PassRegistry::getPassRegistry());
      76           0 :   }
      77             : 
      78           0 :   StringRef getPassName() const override { return AARCH64_TYPE_PROMO_NAME; }
      79             : 
      80             :   /// Iterate over the functions and promote the computation of interesting
      81             :   // sext instructions.
      82             :   bool runOnFunction(Function &F) override;
      83             : 
      84             : private:
      85             :   /// The current function.
      86             :   Function *Func = nullptr;
      87             : 
      88             :   /// Filter out all sexts that does not have this type.
      89             :   /// Currently initialized with Int64Ty.
      90             :   Type *ConsideredSExtType = nullptr;
      91             : 
      92             :   // This transformation requires dominator info.
      93           0 :   void getAnalysisUsage(AnalysisUsage &AU) const override {
      94           0 :     AU.setPreservesCFG();
      95           0 :     AU.addRequired<DominatorTreeWrapperPass>();
      96           0 :     AU.addPreserved<DominatorTreeWrapperPass>();
      97           0 :     FunctionPass::getAnalysisUsage(AU);
      98           0 :   }
      99             : 
     100             :   typedef SmallPtrSet<Instruction *, 32> SetOfInstructions;
     101             :   typedef SmallVector<Instruction *, 16> Instructions;
     102             :   typedef DenseMap<Value *, Instructions> ValueToInsts;
     103             : 
     104             :   /// Check if it is profitable to move a sext through this instruction.
     105             :   /// Currently, we consider it is profitable if:
     106             :   /// - Inst is used only once (no need to insert truncate).
     107             :   /// - Inst has only one operand that will require a sext operation (we do
     108             :   ///   do not create new sext operation).
     109             :   bool shouldGetThrough(const Instruction *Inst);
     110             : 
     111             :   /// Check if it is possible and legal to move a sext through this
     112             :   /// instruction.
     113             :   /// Current heuristic considers that we can get through:
     114             :   /// - Arithmetic operation marked with the nsw or nuw flag.
     115             :   /// - Other sext operation.
     116             :   /// - Truncate operation if it was just dropping sign extended bits.
     117             :   bool canGetThrough(const Instruction *Inst);
     118             : 
     119             :   /// Move sext operations through safe to sext instructions.
     120             :   bool propagateSignExtension(Instructions &SExtInsts);
     121             : 
     122             :   /// Is this sext should be considered for code motion.
     123             :   /// We look for sext with ConsideredSExtType and uses in at least one
     124             :   // GetElementPtrInst.
     125             :   bool shouldConsiderSExt(const Instruction *SExt) const;
     126             : 
     127             :   /// Collect all interesting sext operations, i.e., the ones with the right
     128             :   /// type and used in memory accesses.
     129             :   /// More precisely, a sext instruction is considered as interesting if it
     130             :   /// is used in a "complex" getelementptr or it exits at least another
     131             :   /// sext instruction that sign extended the same initial value.
     132             :   /// A getelementptr is considered as "complex" if it has more than 2
     133             :   // operands.
     134             :   void analyzeSExtension(Instructions &SExtInsts);
     135             : 
     136             :   /// Merge redundant sign extension operations in common dominator.
     137             :   void mergeSExts(ValueToInsts &ValToSExtendedUses,
     138             :                   SetOfInstructions &ToRemove);
     139             : };
     140             : 
     141             : } // end anonymous namespace
     142             : 
     143             : char AArch64AddressTypePromotion::ID = 0;
     144             : 
     145       48292 : INITIALIZE_PASS_BEGIN(AArch64AddressTypePromotion, "aarch64-type-promotion",
     146             :                       AARCH64_TYPE_PROMO_NAME, false, false)
     147       48292 : INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
     148      286868 : INITIALIZE_PASS_END(AArch64AddressTypePromotion, "aarch64-type-promotion",
     149             :                     AARCH64_TYPE_PROMO_NAME, false, false)
     150             : 
     151           0 : FunctionPass *llvm::createAArch64AddressTypePromotionPass() {
     152           0 :   return new AArch64AddressTypePromotion();
     153             : }
     154             : 
     155           0 : bool AArch64AddressTypePromotion::canGetThrough(const Instruction *Inst) {
     156           0 :   if (isa<SExtInst>(Inst))
     157             :     return true;
     158             : 
     159           0 :   const BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Inst);
     160           0 :   if (BinOp && isa<OverflowingBinaryOperator>(BinOp) &&
     161           0 :       (BinOp->hasNoUnsignedWrap() || BinOp->hasNoSignedWrap()))
     162             :     return true;
     163             : 
     164             :   // sext(trunc(sext)) --> sext
     165           0 :   if (isa<TruncInst>(Inst) && isa<SExtInst>(Inst->getOperand(0))) {
     166           0 :     const Instruction *Opnd = cast<Instruction>(Inst->getOperand(0));
     167             :     // Check that the truncate just drop sign extended bits.
     168           0 :     if (Inst->getType()->getIntegerBitWidth() >=
     169           0 :             Opnd->getOperand(0)->getType()->getIntegerBitWidth() &&
     170           0 :         Inst->getOperand(0)->getType()->getIntegerBitWidth() <=
     171           0 :             ConsideredSExtType->getIntegerBitWidth())
     172             :       return true;
     173             :   }
     174             : 
     175             :   return false;
     176             : }
     177             : 
     178           0 : bool AArch64AddressTypePromotion::shouldGetThrough(const Instruction *Inst) {
     179             :   // If the type of the sext is the same as the considered one, this sext
     180             :   // will become useless.
     181             :   // Otherwise, we will have to do something to preserve the original value,
     182             :   // unless it is used once.
     183           0 :   if (isa<SExtInst>(Inst) &&
     184           0 :       (Inst->getType() == ConsideredSExtType || Inst->hasOneUse()))
     185             :     return true;
     186             : 
     187             :   // If the Inst is used more that once, we may need to insert truncate
     188             :   // operations and we don't do that at the moment.
     189           0 :   if (!Inst->hasOneUse())
     190             :     return false;
     191             : 
     192             :   // This truncate is used only once, thus if we can get thourgh, it will become
     193             :   // useless.
     194           0 :   if (isa<TruncInst>(Inst))
     195             :     return true;
     196             : 
     197             :   // If both operands are not constant, a new sext will be created here.
     198             :   // Current heuristic is: each step should be profitable.
     199             :   // Therefore we don't allow to increase the number of sext even if it may
     200             :   // be profitable later on.
     201           0 :   if (isa<BinaryOperator>(Inst) && isa<ConstantInt>(Inst->getOperand(1)))
     202             :     return true;
     203             : 
     204             :   return false;
     205             : }
     206             : 
     207             : static bool shouldSExtOperand(const Instruction *Inst, int OpIdx) {
     208           0 :   return !(isa<SelectInst>(Inst) && OpIdx == 0);
     209             : }
     210             : 
     211             : bool
     212           0 : AArch64AddressTypePromotion::shouldConsiderSExt(const Instruction *SExt) const {
     213           0 :   if (SExt->getType() != ConsideredSExtType)
     214             :     return false;
     215             : 
     216           0 :   for (const User *U : SExt->users()) {
     217           0 :     if (isa<GetElementPtrInst>(U))
     218             :       return true;
     219             :   }
     220             : 
     221             :   return false;
     222             : }
     223             : 
     224             : // Input:
     225             : // - SExtInsts contains all the sext instructions that are used directly in
     226             : //   GetElementPtrInst, i.e., access to memory.
     227             : // Algorithm:
     228             : // - For each sext operation in SExtInsts:
     229             : //   Let var be the operand of sext.
     230             : //   while it is profitable (see shouldGetThrough), legal, and safe
     231             : //   (see canGetThrough) to move sext through var's definition:
     232             : //   * promote the type of var's definition.
     233             : //   * fold var into sext uses.
     234             : //   * move sext above var's definition.
     235             : //   * update sext operand to use the operand of var that should be sign
     236             : //     extended (by construction there is only one).
     237             : //
     238             : //   E.g.,
     239             : //   a = ... i32 c, 3
     240             : //   b = sext i32 a to i64 <- is it legal/safe/profitable to get through 'a'
     241             : //   ...
     242             : //   = b
     243             : // => Yes, update the code
     244             : //   b = sext i32 c to i64
     245             : //   a = ... i64 b, 3
     246             : //   ...
     247             : //   = a
     248             : // Iterate on 'c'.
     249             : bool
     250           0 : AArch64AddressTypePromotion::propagateSignExtension(Instructions &SExtInsts) {
     251             :   DEBUG(dbgs() << "*** Propagate Sign Extension ***\n");
     252             : 
     253           0 :   bool LocalChange = false;
     254           0 :   SetOfInstructions ToRemove;
     255           0 :   ValueToInsts ValToSExtendedUses;
     256           0 :   while (!SExtInsts.empty()) {
     257             :     // Get through simple chain.
     258           0 :     Instruction *SExt = SExtInsts.pop_back_val();
     259             : 
     260             :     DEBUG(dbgs() << "Consider:\n" << *SExt << '\n');
     261             : 
     262             :     // If this SExt has already been merged continue.
     263           0 :     if (SExt->use_empty() && ToRemove.count(SExt)) {
     264             :       DEBUG(dbgs() << "No uses => marked as delete\n");
     265           0 :       continue;
     266             :     }
     267             : 
     268             :     // Now try to get through the chain of definitions.
     269           0 :     while (auto *Inst = dyn_cast<Instruction>(SExt->getOperand(0))) {
     270             :       DEBUG(dbgs() << "Try to get through:\n" << *Inst << '\n');
     271           0 :       if (!canGetThrough(Inst) || !shouldGetThrough(Inst)) {
     272             :         // We cannot get through something that is not an Instruction
     273             :         // or not safe to SExt.
     274             :         DEBUG(dbgs() << "Cannot get through\n");
     275             :         break;
     276             :       }
     277             : 
     278           0 :       LocalChange = true;
     279             :       // If this is a sign extend, it becomes useless.
     280           0 :       if (isa<SExtInst>(Inst) || isa<TruncInst>(Inst)) {
     281             :         DEBUG(dbgs() << "SExt or trunc, mark it as to remove\n");
     282             :         // We cannot use replaceAllUsesWith here because we may trigger some
     283             :         // assertion on the type as all involved sext operation may have not
     284             :         // been moved yet.
     285           0 :         while (!Inst->use_empty()) {
     286           0 :           Use &U = *Inst->use_begin();
     287           0 :           Instruction *User = dyn_cast<Instruction>(U.getUser());
     288             :           assert(User && "User of sext is not an Instruction!");
     289           0 :           User->setOperand(U.getOperandNo(), SExt);
     290             :         }
     291           0 :         ToRemove.insert(Inst);
     292           0 :         SExt->setOperand(0, Inst->getOperand(0));
     293           0 :         SExt->moveBefore(Inst);
     294           0 :         continue;
     295             :       }
     296             : 
     297             :       // Get through the Instruction:
     298             :       // 1. Update its type.
     299             :       // 2. Replace the uses of SExt by Inst.
     300             :       // 3. Sign extend each operand that needs to be sign extended.
     301             : 
     302             :       // Step #1.
     303           0 :       Inst->mutateType(SExt->getType());
     304             :       // Step #2.
     305           0 :       SExt->replaceAllUsesWith(Inst);
     306             :       // Step #3.
     307           0 :       Instruction *SExtForOpnd = SExt;
     308             : 
     309             :       DEBUG(dbgs() << "Propagate SExt to operands\n");
     310           0 :       for (int OpIdx = 0, EndOpIdx = Inst->getNumOperands(); OpIdx != EndOpIdx;
     311             :            ++OpIdx) {
     312             :         DEBUG(dbgs() << "Operand:\n" << *(Inst->getOperand(OpIdx)) << '\n');
     313           0 :         if (Inst->getOperand(OpIdx)->getType() == SExt->getType() ||
     314           0 :             !shouldSExtOperand(Inst, OpIdx)) {
     315             :           DEBUG(dbgs() << "No need to propagate\n");
     316             :           continue;
     317             :         }
     318             :         // Check if we can statically sign extend the operand.
     319           0 :         Value *Opnd = Inst->getOperand(OpIdx);
     320           0 :         if (const ConstantInt *Cst = dyn_cast<ConstantInt>(Opnd)) {
     321             :           DEBUG(dbgs() << "Statically sign extend\n");
     322           0 :           Inst->setOperand(OpIdx, ConstantInt::getSigned(SExt->getType(),
     323           0 :                                                          Cst->getSExtValue()));
     324           0 :           continue;
     325             :         }
     326             :         // UndefValue are typed, so we have to statically sign extend them.
     327           0 :         if (isa<UndefValue>(Opnd)) {
     328             :           DEBUG(dbgs() << "Statically sign extend\n");
     329           0 :           Inst->setOperand(OpIdx, UndefValue::get(SExt->getType()));
     330           0 :           continue;
     331             :         }
     332             : 
     333             :         // Otherwise we have to explicity sign extend it.
     334             :         assert(SExtForOpnd &&
     335             :                "Only one operand should have been sign extended");
     336             : 
     337           0 :         SExtForOpnd->setOperand(0, Opnd);
     338             : 
     339             :         DEBUG(dbgs() << "Move before:\n" << *Inst << "\nSign extend\n");
     340             :         // Move the sign extension before the insertion point.
     341           0 :         SExtForOpnd->moveBefore(Inst);
     342           0 :         Inst->setOperand(OpIdx, SExtForOpnd);
     343             :         // If more sext are required, new instructions will have to be created.
     344           0 :         SExtForOpnd = nullptr;
     345             :       }
     346           0 :       if (SExtForOpnd == SExt) {
     347             :         DEBUG(dbgs() << "Sign extension is useless now\n");
     348           0 :         ToRemove.insert(SExt);
     349           0 :         break;
     350             :       }
     351             :     }
     352             : 
     353             :     // If the use is already of the right type, connect its uses to its argument
     354             :     // and delete it.
     355             :     // This can happen for an Instruction all uses of which are sign extended.
     356           0 :     if (!ToRemove.count(SExt) &&
     357           0 :         SExt->getType() == SExt->getOperand(0)->getType()) {
     358             :       DEBUG(dbgs() << "Sign extension is useless, attach its use to "
     359             :                       "its argument\n");
     360           0 :       SExt->replaceAllUsesWith(SExt->getOperand(0));
     361           0 :       ToRemove.insert(SExt);
     362             :     } else
     363           0 :       ValToSExtendedUses[SExt->getOperand(0)].push_back(SExt);
     364             :   }
     365             : 
     366           0 :   if (EnableMerge)
     367           0 :     mergeSExts(ValToSExtendedUses, ToRemove);
     368             : 
     369             :   // Remove all instructions marked as ToRemove.
     370           0 :   for (Instruction *I: ToRemove)
     371           0 :     I->eraseFromParent();
     372           0 :   return LocalChange;
     373             : }
     374             : 
     375           0 : void AArch64AddressTypePromotion::mergeSExts(ValueToInsts &ValToSExtendedUses,
     376             :                                              SetOfInstructions &ToRemove) {
     377           0 :   DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
     378             : 
     379           0 :   for (auto &Entry : ValToSExtendedUses) {
     380           0 :     Instructions &Insts = Entry.second;
     381           0 :     Instructions CurPts;
     382           0 :     for (Instruction *Inst : Insts) {
     383           0 :       if (ToRemove.count(Inst))
     384             :         continue;
     385           0 :       bool inserted = false;
     386           0 :       for (auto &Pt : CurPts) {
     387           0 :         if (DT.dominates(Inst, Pt)) {
     388             :           DEBUG(dbgs() << "Replace all uses of:\n" << *Pt << "\nwith:\n"
     389             :                        << *Inst << '\n');
     390           0 :           Pt->replaceAllUsesWith(Inst);
     391           0 :           ToRemove.insert(Pt);
     392           0 :           Pt = Inst;
     393           0 :           inserted = true;
     394           0 :           break;
     395             :         }
     396           0 :         if (!DT.dominates(Pt, Inst))
     397             :           // Give up if we need to merge in a common dominator as the
     398             :           // expermients show it is not profitable.
     399             :           continue;
     400             : 
     401             :         DEBUG(dbgs() << "Replace all uses of:\n" << *Inst << "\nwith:\n"
     402             :                      << *Pt << '\n');
     403           0 :         Inst->replaceAllUsesWith(Pt);
     404           0 :         ToRemove.insert(Inst);
     405           0 :         inserted = true;
     406           0 :         break;
     407             :       }
     408           0 :       if (!inserted)
     409           0 :         CurPts.push_back(Inst);
     410             :     }
     411             :   }
     412           0 : }
     413             : 
     414           0 : void AArch64AddressTypePromotion::analyzeSExtension(Instructions &SExtInsts) {
     415             :   DEBUG(dbgs() << "*** Analyze Sign Extensions ***\n");
     416             : 
     417           0 :   DenseMap<Value *, Instruction *> SeenChains;
     418             : 
     419           0 :   for (auto &BB : *Func) {
     420           0 :     for (auto &II : BB) {
     421           0 :       Instruction *SExt = &II;
     422             : 
     423             :       // Collect all sext operation per type.
     424           0 :       if (!isa<SExtInst>(SExt) || !shouldConsiderSExt(SExt))
     425           0 :         continue;
     426             : 
     427             :       DEBUG(dbgs() << "Found:\n" << (*SExt) << '\n');
     428             : 
     429             :       // Cases where we actually perform the optimization:
     430             :       // 1. SExt is used in a getelementptr with more than 2 operand =>
     431             :       //    likely we can merge some computation if they are done on 64 bits.
     432             :       // 2. The beginning of the SExt chain is SExt several time. =>
     433             :       //    code sharing is possible.
     434             : 
     435           0 :       bool insert = false;
     436             :       // #1.
     437           0 :       for (const User *U : SExt->users()) {
     438           0 :         const Instruction *Inst = dyn_cast<GetElementPtrInst>(U);
     439           0 :         if (Inst && Inst->getNumOperands() > 2) {
     440             :           DEBUG(dbgs() << "Interesting use in GetElementPtrInst\n" << *Inst
     441             :                        << '\n');
     442             :           insert = true;
     443             :           break;
     444             :         }
     445             :       }
     446             : 
     447             :       // #2.
     448             :       // Check the head of the chain.
     449           0 :       Instruction *Inst = SExt;
     450             :       Value *Last;
     451           0 :       do {
     452           0 :         int OpdIdx = 0;
     453           0 :         const BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Inst);
     454           0 :         if (BinOp && isa<ConstantInt>(BinOp->getOperand(0)))
     455           0 :           OpdIdx = 1;
     456           0 :         Last = Inst->getOperand(OpdIdx);
     457           0 :         Inst = dyn_cast<Instruction>(Last);
     458           0 :       } while (Inst && canGetThrough(Inst) && shouldGetThrough(Inst));
     459             : 
     460             :       DEBUG(dbgs() << "Head of the chain:\n" << *Last << '\n');
     461             :       DenseMap<Value *, Instruction *>::iterator AlreadySeen =
     462           0 :           SeenChains.find(Last);
     463           0 :       if (insert || AlreadySeen != SeenChains.end()) {
     464             :         DEBUG(dbgs() << "Insert\n");
     465           0 :         SExtInsts.push_back(SExt);
     466           0 :         if (AlreadySeen != SeenChains.end() && AlreadySeen->second != nullptr) {
     467             :           DEBUG(dbgs() << "Insert chain member\n");
     468           0 :           SExtInsts.push_back(AlreadySeen->second);
     469           0 :           SeenChains[Last] = nullptr;
     470             :         }
     471             :       } else {
     472             :         DEBUG(dbgs() << "Record its chain membership\n");
     473           0 :         SeenChains[Last] = SExt;
     474             :       }
     475             :     }
     476             :   }
     477           0 : }
     478             : 
     479           0 : bool AArch64AddressTypePromotion::runOnFunction(Function &F) {
     480           0 :   if (skipFunction(F))
     481             :     return false;
     482             : 
     483           0 :   if (F.isDeclaration())
     484             :     return false;
     485           0 :   Func = &F;
     486           0 :   ConsideredSExtType = Type::getInt64Ty(Func->getContext());
     487             : 
     488             :   DEBUG(dbgs() << "*** " << getPassName() << ": " << Func->getName() << '\n');
     489             : 
     490           0 :   Instructions SExtInsts;
     491           0 :   analyzeSExtension(SExtInsts);
     492           0 :   return propagateSignExtension(SExtInsts);
     493      197610 : }

Generated by: LCOV version 1.13