[llvm] r204389 - [Constant Hoisting] Extend coverage of the constant hoisting pass.
Juergen Ributzka
juergen at apple.com
Thu Mar 20 13:21:00 PDT 2014
Ok, I will try to break it up into sensible pieces.
-Juergen
On Mar 20, 2014, at 1:13 PM, Eric Christopher <echristo at gmail.com> wrote:
> Actually, this patch is almost impossible to review otherwise. Would
> you mind doing this? :)
>
> -eric
>
> On Thu, Mar 20, 2014 at 1:12 PM, Eric Christopher <echristo at gmail.com> wrote:
>> Is there some reason this couldn't be split out into refactoring and
>> then adding new functionality?
>>
>> -eric
>>
>> On Thu, Mar 20, 2014 at 12:55 PM, Juergen Ributzka <juergen at apple.com> wrote:
>>> Author: ributzka
>>> Date: Thu Mar 20 14:55:52 2014
>>> New Revision: 204389
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=204389&view=rev
>>> Log:
>>> [Constant Hoisting] Extend coverage of the constant hoisting pass.
>>>
>>> This commit extends the coverage of the constant hoisting pass, adds additonal
>>> debug output and updates the function names according to the style guide.
>>>
>>> Related to <rdar://problem/16381500>
>>>
>>> Modified:
>>> llvm/trunk/include/llvm/Analysis/TargetTransformInfo.h
>>> llvm/trunk/lib/Analysis/TargetTransformInfo.cpp
>>> llvm/trunk/lib/Target/X86/X86TargetTransformInfo.cpp
>>> llvm/trunk/lib/Transforms/Scalar/ConstantHoisting.cpp
>>> llvm/trunk/test/CodeGen/X86/lsr-interesting-step.ll
>>> llvm/trunk/test/CodeGen/X86/negate-add-zero.ll
>>> llvm/trunk/test/Transforms/ConstantHoisting/X86/phi.ll
>>>
>>> Modified: llvm/trunk/include/llvm/Analysis/TargetTransformInfo.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/TargetTransformInfo.h?rev=204389&r1=204388&r2=204389&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/include/llvm/Analysis/TargetTransformInfo.h (original)
>>> +++ llvm/trunk/include/llvm/Analysis/TargetTransformInfo.h Thu Mar 20 14:55:52 2014
>>> @@ -297,10 +297,10 @@ public:
>>> /// \brief Return the expected cost of materialization for the given integer
>>> /// immediate of the specified type for a given instruction. The cost can be
>>> /// zero if the immediate can be folded into the specified instruction.
>>> - virtual unsigned getIntImmCost(unsigned Opcode, const APInt &Imm,
>>> - Type *Ty) const;
>>> - virtual unsigned getIntImmCost(Intrinsic::ID IID, const APInt &Imm,
>>> + virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm,
>>> Type *Ty) const;
>>> + virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx,
>>> + const APInt &Imm, Type *Ty) const;
>>> /// @}
>>>
>>> /// \name Vector Target Information
>>>
>>> Modified: llvm/trunk/lib/Analysis/TargetTransformInfo.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/TargetTransformInfo.cpp?rev=204389&r1=204388&r2=204389&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/lib/Analysis/TargetTransformInfo.cpp (original)
>>> +++ llvm/trunk/lib/Analysis/TargetTransformInfo.cpp Thu Mar 20 14:55:52 2014
>>> @@ -148,14 +148,14 @@ unsigned TargetTransformInfo::getIntImmC
>>> return PrevTTI->getIntImmCost(Imm, Ty);
>>> }
>>>
>>> -unsigned TargetTransformInfo::getIntImmCost(unsigned Opcode, const APInt &Imm,
>>> - Type *Ty) const {
>>> - return PrevTTI->getIntImmCost(Opcode, Imm, Ty);
>>> +unsigned TargetTransformInfo::getIntImmCost(unsigned Opc, unsigned Idx,
>>> + const APInt &Imm, Type *Ty) const {
>>> + return PrevTTI->getIntImmCost(Opc, Idx, Imm, Ty);
>>> }
>>>
>>> -unsigned TargetTransformInfo::getIntImmCost(Intrinsic::ID IID, const APInt &Imm,
>>> - Type *Ty) const {
>>> - return PrevTTI->getIntImmCost(IID, Imm, Ty);
>>> +unsigned TargetTransformInfo::getIntImmCost(Intrinsic::ID IID, unsigned Idx,
>>> + const APInt &Imm, Type *Ty) const {
>>> + return PrevTTI->getIntImmCost(IID, Idx, Imm, Ty);
>>> }
>>>
>>> unsigned TargetTransformInfo::getNumberOfRegisters(bool Vector) const {
>>> @@ -539,12 +539,12 @@ struct NoTTI final : ImmutablePass, Targ
>>> return TCC_Basic;
>>> }
>>>
>>> - unsigned getIntImmCost(unsigned Opcode, const APInt &Imm,
>>> + unsigned getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm,
>>> Type *Ty) const override {
>>> return TCC_Free;
>>> }
>>>
>>> - unsigned getIntImmCost(Intrinsic::ID IID, const APInt &Imm,
>>> + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
>>> Type *Ty) const override {
>>> return TCC_Free;
>>> }
>>>
>>> Modified: llvm/trunk/lib/Target/X86/X86TargetTransformInfo.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetTransformInfo.cpp?rev=204389&r1=204388&r2=204389&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/lib/Target/X86/X86TargetTransformInfo.cpp (original)
>>> +++ llvm/trunk/lib/Target/X86/X86TargetTransformInfo.cpp Thu Mar 20 14:55:52 2014
>>> @@ -103,9 +103,9 @@ public:
>>>
>>> unsigned getIntImmCost(const APInt &Imm, Type *Ty) const override;
>>>
>>> - unsigned getIntImmCost(unsigned Opcode, const APInt &Imm,
>>> + unsigned getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm,
>>> Type *Ty) const override;
>>> - unsigned getIntImmCost(Intrinsic::ID IID, const APInt &Imm,
>>> + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
>>> Type *Ty) const override;
>>>
>>> /// @}
>>> @@ -776,6 +776,9 @@ unsigned X86TTI::getIntImmCost(const API
>>> if (BitSize == 0)
>>> return ~0U;
>>>
>>> + if (Imm == 0)
>>> + return TCC_Free;
>>> +
>>> if (Imm.getBitWidth() <= 64 &&
>>> (isInt<32>(Imm.getSExtValue()) || isUInt<32>(Imm.getZExtValue())))
>>> return TCC_Basic;
>>> @@ -783,7 +786,7 @@ unsigned X86TTI::getIntImmCost(const API
>>> return 2 * TCC_Basic;
>>> }
>>>
>>> -unsigned X86TTI::getIntImmCost(unsigned Opcode, const APInt &Imm,
>>> +unsigned X86TTI::getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm,
>>> Type *Ty) const {
>>> assert(Ty->isIntegerTy());
>>>
>>> @@ -791,7 +794,15 @@ unsigned X86TTI::getIntImmCost(unsigned
>>> if (BitSize == 0)
>>> return ~0U;
>>>
>>> + unsigned ImmIdx = ~0U;
>>> switch (Opcode) {
>>> + default: return TCC_Free;
>>> + case Instruction::GetElementPtr:
>>> + if (Idx != 0)
>>> + return TCC_Free;
>>> + case Instruction::Store:
>>> + ImmIdx = 0;
>>> + break;
>>> case Instruction::Add:
>>> case Instruction::Sub:
>>> case Instruction::Mul:
>>> @@ -806,28 +817,31 @@ unsigned X86TTI::getIntImmCost(unsigned
>>> case Instruction::Or:
>>> case Instruction::Xor:
>>> case Instruction::ICmp:
>>> - if (Imm.getBitWidth() <= 64 && isInt<32>(Imm.getSExtValue()))
>>> - return TCC_Free;
>>> - else
>>> - return X86TTI::getIntImmCost(Imm, Ty);
>>> + ImmIdx = 1;
>>> + break;
>>> case Instruction::Trunc:
>>> case Instruction::ZExt:
>>> case Instruction::SExt:
>>> case Instruction::IntToPtr:
>>> case Instruction::PtrToInt:
>>> case Instruction::BitCast:
>>> + case Instruction::PHI:
>>> case Instruction::Call:
>>> case Instruction::Select:
>>> case Instruction::Ret:
>>> case Instruction::Load:
>>> - case Instruction::Store:
>>> - return X86TTI::getIntImmCost(Imm, Ty);
>>> + break;
>>> }
>>> - return TargetTransformInfo::getIntImmCost(Opcode, Imm, Ty);
>>> +
>>> + if ((Idx == ImmIdx) &&
>>> + Imm.getBitWidth() <= 64 && isInt<32>(Imm.getSExtValue()))
>>> + return TCC_Free;
>>> +
>>> + return X86TTI::getIntImmCost(Imm, Ty);
>>> }
>>>
>>> -unsigned X86TTI::getIntImmCost(Intrinsic::ID IID, const APInt &Imm,
>>> - Type *Ty) const {
>>> +unsigned X86TTI::getIntImmCost(Intrinsic::ID IID, unsigned Idx,
>>> + const APInt &Imm, Type *Ty) const {
>>> assert(Ty->isIntegerTy());
>>>
>>> unsigned BitSize = Ty->getPrimitiveSizeInBits();
>>> @@ -835,21 +849,24 @@ unsigned X86TTI::getIntImmCost(Intrinsic
>>> return ~0U;
>>>
>>> switch (IID) {
>>> - default: return TargetTransformInfo::getIntImmCost(IID, Imm, Ty);
>>> + default: return TCC_Free;
>>> case Intrinsic::sadd_with_overflow:
>>> case Intrinsic::uadd_with_overflow:
>>> case Intrinsic::ssub_with_overflow:
>>> case Intrinsic::usub_with_overflow:
>>> case Intrinsic::smul_with_overflow:
>>> case Intrinsic::umul_with_overflow:
>>> - if (Imm.getBitWidth() <= 64 && isInt<32>(Imm.getSExtValue()))
>>> + if ((Idx == 1) && Imm.getBitWidth() <= 64 && isInt<32>(Imm.getSExtValue()))
>>> return TCC_Free;
>>> else
>>> return X86TTI::getIntImmCost(Imm, Ty);
>>> case Intrinsic::experimental_stackmap:
>>> + if (Idx < 2)
>>> + return TCC_Free;
>>> case Intrinsic::experimental_patchpoint_void:
>>> case Intrinsic::experimental_patchpoint_i64:
>>> - if (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))
>>> + if ((Idx < 4 ) ||
>>> + (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))
>>> return TCC_Free;
>>> else
>>> return X86TTI::getIntImmCost(Imm, Ty);
>>>
>>> Modified: llvm/trunk/lib/Transforms/Scalar/ConstantHoisting.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ConstantHoisting.cpp?rev=204389&r1=204388&r2=204389&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/lib/Transforms/Scalar/ConstantHoisting.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/Scalar/ConstantHoisting.cpp Thu Mar 20 14:55:52 2014
>>> @@ -35,15 +35,14 @@
>>>
>>> #define DEBUG_TYPE "consthoist"
>>> #include "llvm/Transforms/Scalar.h"
>>> -#include "llvm/ADT/MapVector.h"
>>> #include "llvm/ADT/SmallSet.h"
>>> +#include "llvm/ADT/SmallVector.h"
>>> #include "llvm/ADT/Statistic.h"
>>> #include "llvm/Analysis/TargetTransformInfo.h"
>>> #include "llvm/IR/Constants.h"
>>> #include "llvm/IR/Dominators.h"
>>> #include "llvm/IR/IntrinsicInst.h"
>>> #include "llvm/Pass.h"
>>> -#include "llvm/Support/CommandLine.h"
>>> #include "llvm/Support/Debug.h"
>>>
>>> using namespace llvm;
>>> @@ -51,42 +50,80 @@ using namespace llvm;
>>> STATISTIC(NumConstantsHoisted, "Number of constants hoisted");
>>> STATISTIC(NumConstantsRebased, "Number of constants rebased");
>>>
>>> -
>>> namespace {
>>> -typedef SmallVector<User *, 4> ConstantUseListType;
>>> +struct ConstantUser;
>>> +struct RebasedConstantInfo;
>>> +
>>> +typedef SmallVector<ConstantUser, 8> ConstantUseListType;
>>> +typedef SmallVector<RebasedConstantInfo, 4> RebasedConstantListType;
>>> +
>>> +/// \brief Keeps track of the user of a constant and the operand index where the
>>> +/// constant is used.
>>> +struct ConstantUser {
>>> + Instruction *Inst;
>>> + unsigned OpndIdx;
>>> +
>>> + ConstantUser(Instruction *Inst, unsigned Idx) : Inst(Inst), OpndIdx(Idx) { }
>>> +};
>>> +
>>> +/// \brief Keeps track of a constant candidate and its usees.
>>> struct ConstantCandidate {
>>> + ConstantUseListType Uses;
>>> + ConstantInt *ConstInt;
>>> unsigned CumulativeCost;
>>> +
>>> + ConstantCandidate(ConstantInt *ConstInt)
>>> + : ConstInt(ConstInt), CumulativeCost(0) { }
>>> +
>>> + /// \brief Add the user to the use list and update the cost.
>>> + void addUser(Instruction *Inst, unsigned Idx, unsigned Cost) {
>>> + CumulativeCost += Cost;
>>> + Uses.push_back(ConstantUser(Inst, Idx));
>>> + }
>>> +};
>>> +
>>> +/// \brief This represents a constant that has been rebased with respect to a
>>> +/// base constant. The difference to the base constant is recorded in Offset.
>>> +struct RebasedConstantInfo {
>>> ConstantUseListType Uses;
>>> + Constant *Offset;
>>> + mutable BasicBlock *IDom;
>>> +
>>> + RebasedConstantInfo(ConstantUseListType &&Uses, Constant *Offset)
>>> + : Uses(Uses), Offset(Offset), IDom(nullptr) { }
>>> };
>>>
>>> +/// \brief A base constant and all its rebased constants.
>>> struct ConstantInfo {
>>> ConstantInt *BaseConstant;
>>> - struct RebasedConstantInfo {
>>> - ConstantInt *OriginalConstant;
>>> - Constant *Offset;
>>> - ConstantUseListType Uses;
>>> - };
>>> - typedef SmallVector<RebasedConstantInfo, 4> RebasedConstantListType;
>>> RebasedConstantListType RebasedConstants;
>>> };
>>>
>>> +/// \brief The constant hoisting pass.
>>> class ConstantHoisting : public FunctionPass {
>>> + typedef DenseMap<ConstantInt *, unsigned> ConstCandMapType;
>>> + typedef std::vector<ConstantCandidate> ConstCandVecType;
>>> +
>>> const TargetTransformInfo *TTI;
>>> DominatorTree *DT;
>>> + BasicBlock *Entry;
>>> +
>>> + /// Keeps track of constant candidates found in the function.
>>> + ConstCandMapType ConstCandMap;
>>> + ConstCandVecType ConstCandVec;
>>>
>>> - /// Keeps track of expensive constants found in the function.
>>> - typedef MapVector<ConstantInt *, ConstantCandidate> ConstantMapType;
>>> - ConstantMapType ConstantMap;
>>> + /// Keep track of cast instructions we already cloned.
>>> + SmallDenseMap<Instruction *, Instruction *> ClonedCastMap;
>>>
>>> /// These are the final constants we decided to hoist.
>>> - SmallVector<ConstantInfo, 4> Constants;
>>> + SmallVector<ConstantInfo, 8> ConstantVec;
>>> public:
>>> static char ID; // Pass identification, replacement for typeid
>>> - ConstantHoisting() : FunctionPass(ID), TTI(0) {
>>> + ConstantHoisting() : FunctionPass(ID), TTI(0), DT(0), Entry(0) {
>>> initializeConstantHoistingPass(*PassRegistry::getPassRegistry());
>>> }
>>>
>>> - bool runOnFunction(Function &F) override;
>>> + bool runOnFunction(Function &Fn) override;
>>>
>>> const char *getPassName() const override { return "Constant Hoisting"; }
>>>
>>> @@ -97,19 +134,49 @@ public:
>>> }
>>>
>>> private:
>>> - void CollectConstant(User *U, unsigned Opcode, Intrinsic::ID IID,
>>> - ConstantInt *C);
>>> - void CollectConstants(Instruction *I);
>>> - void CollectConstants(Function &F);
>>> - void FindAndMakeBaseConstant(ConstantMapType::iterator S,
>>> - ConstantMapType::iterator E);
>>> - void FindBaseConstants();
>>> - Instruction *FindConstantInsertionPoint(Function &F,
>>> - const ConstantInfo &CI) const;
>>> - void EmitBaseConstants(Function &F, User *U, Instruction *Base,
>>> - Constant *Offset, ConstantInt *OriginalConstant);
>>> - bool EmitBaseConstants(Function &F);
>>> - bool OptimizeConstants(Function &F);
>>> + /// \brief Initialize the pass.
>>> + void setup(Function &Fn) {
>>> + DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
>>> + TTI = &getAnalysis<TargetTransformInfo>();
>>> + Entry = &Fn.getEntryBlock();
>>> + }
>>> +
>>> + /// \brief Cleanup.
>>> + void cleanup() {
>>> + ConstantVec.clear();
>>> + ClonedCastMap.clear();
>>> + ConstCandVec.clear();
>>> + ConstCandMap.clear();
>>> +
>>> + TTI = nullptr;
>>> + DT = nullptr;
>>> + Entry = nullptr;
>>> + }
>>> +
>>> + /// \brief Find the common dominator of all uses and cache the result for
>>> + /// future lookup.
>>> + BasicBlock *getIDom(const RebasedConstantInfo &RCI) const {
>>> + if (RCI.IDom)
>>> + return RCI.IDom;
>>> + RCI.IDom = findIDomOfAllUses(RCI.Uses);
>>> + assert(RCI.IDom && "Invalid IDom.");
>>> + return RCI.IDom;
>>> + }
>>> +
>>> + BasicBlock *findIDomOfAllUses(const ConstantUseListType &Uses) const;
>>> + Instruction *findMatInsertPt(Instruction *I, unsigned Idx = ~0U) const;
>>> + Instruction *findConstantInsertionPoint(const ConstantInfo &CI) const;
>>> + void collectConstantCandidates(Instruction *I, unsigned Idx, ConstantInt *C);
>>> + void collectConstantCandidates(Instruction *I);
>>> + void collectConstantCandidates(Function &Fn);
>>> + void findAndMakeBaseConstant(ConstCandVecType::iterator S,
>>> + ConstCandVecType::iterator E);
>>> + void findBaseConstants();
>>> + void emitBaseConstants(Instruction *Base, Constant *Offset,
>>> + const ConstantUser &CU);
>>> + bool emitBaseConstants();
>>> + void deleteDeadCastInst() const;
>>> + bool optimizeConstants(Function &F);
>>> };
>>> }
>>>
>>> @@ -126,297 +193,352 @@ FunctionPass *llvm::createConstantHoisti
>>> }
>>>
>>> /// \brief Perform the constant hoisting optimization for the given function.
>>> -bool ConstantHoisting::runOnFunction(Function &F) {
>>> - DEBUG(dbgs() << "********** Constant Hoisting **********\n");
>>> - DEBUG(dbgs() << "********** Function: " << F.getName() << '\n');
>>> +bool ConstantHoisting::runOnFunction(Function &Fn) {
>>> + DEBUG(dbgs() << "********** Begin Constant Hoisting **********\n");
>>> + DEBUG(dbgs() << "********** Function: " << Fn.getName() << '\n');
>>>
>>> - DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
>>> - TTI = &getAnalysis<TargetTransformInfo>();
>>> + setup(Fn);
>>>
>>> - return OptimizeConstants(F);
>>> + bool MadeChange = optimizeConstants(Fn);
>>> +
>>> + if (MadeChange) {
>>> + DEBUG(dbgs() << "********** Function after Constant Hoisting: "
>>> + << Fn.getName() << '\n');
>>> + DEBUG(dbgs() << Fn);
>>> + }
>>> + DEBUG(dbgs() << "********** End Constant Hoisting **********\n");
>>> +
>>> + cleanup();
>>> +
>>> + return MadeChange;
>>> }
>>>
>>> -void ConstantHoisting::CollectConstant(User * U, unsigned Opcode,
>>> - Intrinsic::ID IID, ConstantInt *C) {
>>> +/// \brief Find nearest common dominator of all uses.
>>> +/// FIXME: Replace this with NearestCommonDominator once it is in common code.
>>> +BasicBlock *
>>> +ConstantHoisting::findIDomOfAllUses(const ConstantUseListType &Uses) const {
>>> + // Collect all basic blocks.
>>> + SmallPtrSet<BasicBlock *, 8> BBs;
>>> + for (auto const &U : Uses)
>>> + BBs.insert(findMatInsertPt(U.Inst, U.OpndIdx)->getParent());
>>> +
>>> + if (BBs.count(Entry))
>>> + return Entry;
>>> +
>>> + while (BBs.size() >= 2) {
>>> + BasicBlock *BB, *BB1, *BB2;
>>> + BB1 = *BBs.begin();
>>> + BB2 = *std::next(BBs.begin());
>>> + BB = DT->findNearestCommonDominator(BB1, BB2);
>>> + if (BB == Entry)
>>> + return Entry;
>>> + BBs.erase(BB1);
>>> + BBs.erase(BB2);
>>> + BBs.insert(BB);
>>> + }
>>> + assert((BBs.size() == 1) && "Expected only one element.");
>>> + return *BBs.begin();
>>> +}
>>> +
>>> +/// \brief Find the constant materialization insertion point.
>>> +Instruction *ConstantHoisting::findMatInsertPt(Instruction *Inst,
>>> + unsigned Idx) const {
>>> + // The simple and common case.
>>> + if (!isa<PHINode>(Inst) && !isa<LandingPadInst>(Inst))
>>> + return Inst;
>>> +
>>> + // We can't insert directly before a phi node or landing pad. Insert before
>>> + // the terminator of the incoming or dominating block.
>>> + assert(Entry != Inst->getParent() && "PHI or landing pad in entry block!");
>>> + if (Idx != ~0U && isa<PHINode>(Inst))
>>> + return cast<PHINode>(Inst)->getIncomingBlock(Idx)->getTerminator();
>>> +
>>> + BasicBlock *IDom = DT->getNode(Inst->getParent())->getIDom()->getBlock();
>>> + return IDom->getTerminator();
>>> +}
>>> +
>>> +/// \brief Find an insertion point that dominates all uses.
>>> +Instruction *ConstantHoisting::
>>> +findConstantInsertionPoint(const ConstantInfo &ConstInfo) const {
>>> + assert(!ConstInfo.RebasedConstants.empty() && "Invalid constant info entry.");
>>> + // Collect all IDoms.
>>> + SmallPtrSet<BasicBlock *, 8> BBs;
>>> + for (auto const &RCI : ConstInfo.RebasedConstants)
>>> + BBs.insert(getIDom(RCI));
>>> +
>>> + assert(!BBs.empty() && "No dominators!?");
>>> +
>>> + if (BBs.count(Entry))
>>> + return &Entry->front();
>>> +
>>> + while (BBs.size() >= 2) {
>>> + BasicBlock *BB, *BB1, *BB2;
>>> + BB1 = *BBs.begin();
>>> + BB2 = *std::next(BBs.begin());
>>> + BB = DT->findNearestCommonDominator(BB1, BB2);
>>> + if (BB == Entry)
>>> + return &Entry->front();
>>> + BBs.erase(BB1);
>>> + BBs.erase(BB2);
>>> + BBs.insert(BB);
>>> + }
>>> + assert((BBs.size() == 1) && "Expected only one element.");
>>> + Instruction &FirstInst = (*BBs.begin())->front();
>>> + return findMatInsertPt(&FirstInst);
>>> +}
>>> +
>>> +
>>> +/// \brief Record constant integer ConstInt for instruction Inst at operand
>>> +/// index Idx.
>>> +///
>>> +/// The operand at index Idx is not necessarily the constant inetger itself. It
>>> +/// could also be a cast instruction or a constant expression that uses the
>>> +// constant integer.
>>> +void ConstantHoisting::collectConstantCandidates(Instruction *Inst,
>>> + unsigned Idx,
>>> + ConstantInt *ConstInt) {
>>> unsigned Cost;
>>> - if (Opcode)
>>> - Cost = TTI->getIntImmCost(Opcode, C->getValue(), C->getType());
>>> + // Ask the target about the cost of materializing the constant for the given
>>> + // instruction and operand index.
>>> + if (auto IntrInst = dyn_cast<IntrinsicInst>(Inst))
>>> + Cost = TTI->getIntImmCost(IntrInst->getIntrinsicID(), Idx,
>>> + ConstInt->getValue(), ConstInt->getType());
>>> else
>>> - Cost = TTI->getIntImmCost(IID, C->getValue(), C->getType());
>>> + Cost = TTI->getIntImmCost(Inst->getOpcode(), Idx, ConstInt->getValue(),
>>> + ConstInt->getType());
>>>
>>> + // Ignore cheap integer constants.
>>> if (Cost > TargetTransformInfo::TCC_Basic) {
>>> - ConstantCandidate &CC = ConstantMap[C];
>>> - CC.CumulativeCost += Cost;
>>> - CC.Uses.push_back(U);
>>> - DEBUG(dbgs() << "Collect constant " << *C << " with cost " << Cost
>>> - << " from " << *U << '\n');
>>> + ConstCandMapType::iterator Itr;
>>> + bool Inserted;
>>> + std::tie(Itr, Inserted) = ConstCandMap.insert(std::make_pair(ConstInt, 0));
>>> + if (Inserted) {
>>> + ConstCandVec.push_back(ConstantCandidate(ConstInt));
>>> + Itr->second = ConstCandVec.size() - 1;
>>> + }
>>> + ConstCandVec[Itr->second].addUser(Inst, Idx, Cost);
>>> + DEBUG(if (auto ConstInt = dyn_cast<ConstantInt>(Inst->getOperand(Idx)))
>>> + dbgs() << "Collect constant " << *ConstInt << " from " << *Inst
>>> + << " with cost " << Cost << '\n';
>>> + else
>>> + dbgs() << "Collect constant " << *ConstInt << " indirectly from "
>>> + << *Inst << " via " << *Inst->getOperand(Idx) << " with cost "
>>> + << Cost << '\n';
>>> + );
>>> }
>>> }
>>>
>>> -/// \brief Scan the instruction or constant expression for expensive integer
>>> -/// constants and record them in the constant map.
>>> -void ConstantHoisting::CollectConstants(Instruction *I) {
>>> - unsigned Opcode = 0;
>>> - Intrinsic::ID IID = Intrinsic::not_intrinsic;
>>> - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
>>> - IID = II->getIntrinsicID();
>>> - else
>>> - Opcode = I->getOpcode();
>>> +/// \brief Scan the instruction for expensive integer constants and record them
>>> +/// in the constant candidate vector.
>>> +void ConstantHoisting::collectConstantCandidates(Instruction *Inst) {
>>> + // Skip all cast instructions. They are visited indirectly later on.
>>> + if (Inst->isCast())
>>> + return;
>>> +
>>> + // Can't handle inline asm. Skip it.
>>> + if (auto Call = dyn_cast<CallInst>(Inst))
>>> + if (isa<InlineAsm>(Call->getCalledValue()))
>>> + return;
>>>
>>> // Scan all operands.
>>> - for (User::op_iterator O = I->op_begin(), E = I->op_end(); O != E; ++O) {
>>> - if (ConstantInt *C = dyn_cast<ConstantInt>(O)) {
>>> - CollectConstant(I, Opcode, IID, C);
>>> + for (unsigned Idx = 0, E = Inst->getNumOperands(); Idx != E; ++Idx) {
>>> + Value *Opnd = Inst->getOperand(Idx);
>>> +
>>> + // Vist constant integers.
>>> + if (auto ConstInt = dyn_cast<ConstantInt>(Opnd)) {
>>> + collectConstantCandidates(Inst, Idx, ConstInt);
>>> continue;
>>> }
>>> - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(O)) {
>>> - // We only handle constant cast expressions.
>>> - if (!CE->isCast())
>>> +
>>> + // Visit cast instructions that have constant integers.
>>> + if (auto CastInst = dyn_cast<Instruction>(Opnd)) {
>>> + // Only visit cast instructions, which have been skipped. All other
>>> + // instructions should have already been visited.
>>> + if (!CastInst->isCast())
>>> continue;
>>>
>>> - if (ConstantInt *C = dyn_cast<ConstantInt>(CE->getOperand(0))) {
>>> - // Ignore the cast expression and use the opcode of the instruction.
>>> - CollectConstant(CE, Opcode, IID, C);
>>> + if (auto *ConstInt = dyn_cast<ConstantInt>(CastInst->getOperand(0))) {
>>> + // Pretend the constant is directly used by the instruction and ignore
>>> + // the cast instruction.
>>> + collectConstantCandidates(Inst, Idx, ConstInt);
>>> continue;
>>> }
>>> }
>>> - }
>>> +
>>> + // Visit constant expressions that have constant integers.
>>> + if (auto ConstExpr = dyn_cast<ConstantExpr>(Opnd)) {
>>> + // Only visit constant cast expressions.
>>> + if (!ConstExpr->isCast())
>>> + continue;
>>> +
>>> + if (auto ConstInt = dyn_cast<ConstantInt>(ConstExpr->getOperand(0))) {
>>> + // Pretend the constant is directly used by the instruction and ignore
>>> + // the constant expression.
>>> + collectConstantCandidates(Inst, Idx, ConstInt);
>>> + continue;
>>> + }
>>> + }
>>> + } // end of for all operands
>>> }
>>>
>>> /// \brief Collect all integer constants in the function that cannot be folded
>>> /// into an instruction itself.
>>> -void ConstantHoisting::CollectConstants(Function &F) {
>>> - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
>>> - for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
>>> - CollectConstants(I);
>>> +void ConstantHoisting::collectConstantCandidates(Function &Fn) {
>>> + for (Function::iterator BB : Fn)
>>> + for (BasicBlock::iterator I : *BB)
>>> + collectConstantCandidates(I);
>>> }
>>>
>>> /// \brief Find the base constant within the given range and rebase all other
>>> /// constants with respect to the base constant.
>>> -void ConstantHoisting::FindAndMakeBaseConstant(ConstantMapType::iterator S,
>>> - ConstantMapType::iterator E) {
>>> - ConstantMapType::iterator MaxCostItr = S;
>>> +void ConstantHoisting::findAndMakeBaseConstant(ConstCandVecType::iterator S,
>>> + ConstCandVecType::iterator E) {
>>> + auto MaxCostItr = S;
>>> unsigned NumUses = 0;
>>> // Use the constant that has the maximum cost as base constant.
>>> - for (ConstantMapType::iterator I = S; I != E; ++I) {
>>> - NumUses += I->second.Uses.size();
>>> - if (I->second.CumulativeCost > MaxCostItr->second.CumulativeCost)
>>> - MaxCostItr = I;
>>> + for (auto ConstCand = S; ConstCand != E; ++ConstCand) {
>>> + NumUses += ConstCand->Uses.size();
>>> + if (ConstCand->CumulativeCost > MaxCostItr->CumulativeCost)
>>> + MaxCostItr = ConstCand;
>>> }
>>>
>>> // Don't hoist constants that have only one use.
>>> if (NumUses <= 1)
>>> return;
>>>
>>> - ConstantInfo CI;
>>> - CI.BaseConstant = MaxCostItr->first;
>>> - Type *Ty = CI.BaseConstant->getType();
>>> + ConstantInfo ConstInfo;
>>> + ConstInfo.BaseConstant = MaxCostItr->ConstInt;
>>> + Type *Ty = ConstInfo.BaseConstant->getType();
>>> +
>>> // Rebase the constants with respect to the base constant.
>>> - for (ConstantMapType::iterator I = S; I != E; ++I) {
>>> - APInt Diff = I->first->getValue() - CI.BaseConstant->getValue();
>>> - ConstantInfo::RebasedConstantInfo RCI;
>>> - RCI.OriginalConstant = I->first;
>>> - RCI.Offset = ConstantInt::get(Ty, Diff);
>>> - RCI.Uses = std::move(I->second.Uses);
>>> - CI.RebasedConstants.push_back(RCI);
>>> - }
>>> - Constants.push_back(CI);
>>> -}
>>> -
>>> -/// \brief Finds and combines constants that can be easily rematerialized with
>>> -/// an add from a common base constant.
>>> -void ConstantHoisting::FindBaseConstants() {
>>> - // Sort the constants by value and type. This invalidates the mapping.
>>> - std::sort(ConstantMap.begin(), ConstantMap.end(),
>>> - [](const std::pair<ConstantInt *, ConstantCandidate> &LHS,
>>> - const std::pair<ConstantInt *, ConstantCandidate> &RHS) {
>>> - if (LHS.first->getType() != RHS.first->getType())
>>> - return LHS.first->getType()->getBitWidth() <
>>> - RHS.first->getType()->getBitWidth();
>>> - return LHS.first->getValue().ult(RHS.first->getValue());
>>> - });
>>> -
>>> - // Simple linear scan through the sorted constant map for viable merge
>>> - // candidates.
>>> - ConstantMapType::iterator MinValItr = ConstantMap.begin();
>>> - for (ConstantMapType::iterator I = std::next(ConstantMap.begin()),
>>> - E = ConstantMap.end(); I != E; ++I) {
>>> - if (MinValItr->first->getType() == I->first->getType()) {
>>> + for (auto ConstCand = S; ConstCand != E; ++ConstCand) {
>>> + APInt Diff = ConstCand->ConstInt->getValue() -
>>> + ConstInfo.BaseConstant->getValue();
>>> + Constant *Offset = Diff == 0 ? nullptr : ConstantInt::get(Ty, Diff);
>>> + ConstInfo.RebasedConstants.push_back(
>>> + RebasedConstantInfo(std::move(ConstCand->Uses), Offset));
>>> + }
>>> + ConstantVec.push_back(ConstInfo);
>>> +}
>>> +
>>> +/// \brief Finds and combines constant candidates that can be easily
>>> +/// rematerialized with an add from a common base constant.
>>> +void ConstantHoisting::findBaseConstants() {
>>> + // Sort the constants by value and type. This invalidates the mapping!
>>> + std::sort(ConstCandVec.begin(), ConstCandVec.end(),
>>> + [](const ConstantCandidate &LHS, const ConstantCandidate &RHS) {
>>> + if (LHS.ConstInt->getType() != RHS.ConstInt->getType())
>>> + return LHS.ConstInt->getType()->getBitWidth() <
>>> + RHS.ConstInt->getType()->getBitWidth();
>>> + return LHS.ConstInt->getValue().ult(RHS.ConstInt->getValue());
>>> + });
>>> +
>>> + // Simple linear scan through the sorted constant candidate vector for viable
>>> + // merge candidates.
>>> + auto MinValItr = ConstCandVec.begin();
>>> + for (auto CC = std::next(ConstCandVec.begin()), E = ConstCandVec.end();
>>> + CC != E; ++CC) {
>>> + if (MinValItr->ConstInt->getType() == CC->ConstInt->getType()) {
>>> // Check if the constant is in range of an add with immediate.
>>> - APInt Diff = I->first->getValue() - MinValItr->first->getValue();
>>> + APInt Diff = CC->ConstInt->getValue() - MinValItr->ConstInt->getValue();
>>> if ((Diff.getBitWidth() <= 64) &&
>>> TTI->isLegalAddImmediate(Diff.getSExtValue()))
>>> continue;
>>> }
>>> // We either have now a different constant type or the constant is not in
>>> // range of an add with immediate anymore.
>>> - FindAndMakeBaseConstant(MinValItr, I);
>>> + findAndMakeBaseConstant(MinValItr, CC);
>>> // Start a new base constant search.
>>> - MinValItr = I;
>>> + MinValItr = CC;
>>> }
>>> // Finalize the last base constant search.
>>> - FindAndMakeBaseConstant(MinValItr, ConstantMap.end());
>>> -}
>>> -
>>> -/// \brief Records the basic block of the instruction or all basic blocks of the
>>> -/// users of the constant expression.
>>> -static void CollectBasicBlocks(SmallPtrSet<BasicBlock *, 4> &BBs, Function &F,
>>> - User *U) {
>>> - if (Instruction *I = dyn_cast<Instruction>(U))
>>> - BBs.insert(I->getParent());
>>> - else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U))
>>> - // Find all users of this constant expression.
>>> - for (User *UU : CE->users())
>>> - // Only record users that are instructions. We don't want to go down a
>>> - // nested constant expression chain. Also check if the instruction is even
>>> - // in the current function.
>>> - if (Instruction *I = dyn_cast<Instruction>(UU))
>>> - if(I->getParent()->getParent() == &F)
>>> - BBs.insert(I->getParent());
>>> -}
>>> -
>>> -/// \brief Find the instruction we should insert the constant materialization
>>> -/// before.
>>> -static Instruction *getMatInsertPt(Instruction *I, const DominatorTree *DT) {
>>> - if (!isa<PHINode>(I) && !isa<LandingPadInst>(I)) // Simple case.
>>> - return I;
>>> -
>>> - // We can't insert directly before a phi node or landing pad. Insert before
>>> - // the terminator of the dominating block.
>>> - assert(&I->getParent()->getParent()->getEntryBlock() != I->getParent() &&
>>> - "PHI or landing pad in entry block!");
>>> - BasicBlock *IDom = DT->getNode(I->getParent())->getIDom()->getBlock();
>>> - return IDom->getTerminator();
>>> -}
>>> -
>>> -/// \brief Find an insertion point that dominates all uses.
>>> -Instruction *ConstantHoisting::
>>> -FindConstantInsertionPoint(Function &F, const ConstantInfo &CI) const {
>>> - BasicBlock *Entry = &F.getEntryBlock();
>>> -
>>> - // Collect all basic blocks.
>>> - SmallPtrSet<BasicBlock *, 4> BBs;
>>> - ConstantInfo::RebasedConstantListType::const_iterator RCI, RCE;
>>> - for (RCI = CI.RebasedConstants.begin(), RCE = CI.RebasedConstants.end();
>>> - RCI != RCE; ++RCI)
>>> - for (SmallVectorImpl<User *>::const_iterator U = RCI->Uses.begin(),
>>> - E = RCI->Uses.end(); U != E; ++U)
>>> - CollectBasicBlocks(BBs, F, *U);
>>> -
>>> - if (BBs.count(Entry))
>>> - return getMatInsertPt(&Entry->front(), DT);
>>> -
>>> - while (BBs.size() >= 2) {
>>> - BasicBlock *BB, *BB1, *BB2;
>>> - BB1 = *BBs.begin();
>>> - BB2 = *std::next(BBs.begin());
>>> - BB = DT->findNearestCommonDominator(BB1, BB2);
>>> - if (BB == Entry)
>>> - return getMatInsertPt(&Entry->front(), DT);
>>> - BBs.erase(BB1);
>>> - BBs.erase(BB2);
>>> - BBs.insert(BB);
>>> - }
>>> - assert((BBs.size() == 1) && "Expected only one element.");
>>> - Instruction &FirstInst = (*BBs.begin())->front();
>>> - return getMatInsertPt(&FirstInst, DT);
>>> + findAndMakeBaseConstant(MinValItr, ConstCandVec.end());
>>> }
>>>
>>> /// \brief Emit materialization code for all rebased constants and update their
>>> /// users.
>>> -void ConstantHoisting::EmitBaseConstants(Function &F, User *U,
>>> - Instruction *Base, Constant *Offset,
>>> - ConstantInt *OriginalConstant) {
>>> - if (Instruction *I = dyn_cast<Instruction>(U)) {
>>> - Instruction *Mat = Base;
>>> - if (!Offset->isNullValue()) {
>>> - Mat = BinaryOperator::Create(Instruction::Add, Base, Offset,
>>> - "const_mat", getMatInsertPt(I, DT));
>>> -
>>> - // Use the same debug location as the instruction we are about to update.
>>> - Mat->setDebugLoc(I->getDebugLoc());
>>> -
>>> - DEBUG(dbgs() << "Materialize constant (" << *Base->getOperand(0)
>>> - << " + " << *Offset << ") in BB "
>>> - << I->getParent()->getName() << '\n' << *Mat << '\n');
>>> - }
>>> - DEBUG(dbgs() << "Update: " << *I << '\n');
>>> - I->replaceUsesOfWith(OriginalConstant, Mat);
>>> - DEBUG(dbgs() << "To: " << *I << '\n');
>>> +void ConstantHoisting::emitBaseConstants(Instruction *Base, Constant *Offset,
>>> + const ConstantUser &CU) {
>>> + Instruction *Mat = Base;
>>> + if (Offset) {
>>> + Instruction *InsertionPt = findMatInsertPt(CU.Inst, CU.OpndIdx);
>>> + Mat = BinaryOperator::Create(Instruction::Add, Base, Offset,
>>> + "const_mat", InsertionPt);
>>> +
>>> + DEBUG(dbgs() << "Materialize constant (" << *Base->getOperand(0)
>>> + << " + " << *Offset << ") in BB "
>>> + << Mat->getParent()->getName() << '\n' << *Mat << '\n');
>>> + Mat->setDebugLoc(CU.Inst->getDebugLoc());
>>> + }
>>> + Value *Opnd = CU.Inst->getOperand(CU.OpndIdx);
>>> +
>>> + // Visit constant integer.
>>> + if (isa<ConstantInt>(Opnd)) {
>>> + DEBUG(dbgs() << "Update: " << *CU.Inst << '\n');
>>> + CU.Inst->setOperand(CU.OpndIdx, Mat);
>>> + DEBUG(dbgs() << "To : " << *CU.Inst << '\n');
>>> return;
>>> }
>>> - assert(isa<ConstantExpr>(U) && "Expected a ConstantExpr.");
>>> - ConstantExpr *CE = cast<ConstantExpr>(U);
>>> - SmallVector<std::pair<Instruction *, Instruction *>, 8> WorkList;
>>> - DEBUG(dbgs() << "Visit ConstantExpr " << *CE << '\n');
>>> - for (User *UU : CE->users()) {
>>> - DEBUG(dbgs() << "Check user "; UU->print(dbgs()); dbgs() << '\n');
>>> - // We only handel instructions here and won't walk down a ConstantExpr chain
>>> - // to replace all ConstExpr with instructions.
>>> - if (Instruction *I = dyn_cast<Instruction>(UU)) {
>>> - // Only update constant expressions in the current function.
>>> - if (I->getParent()->getParent() != &F) {
>>> - DEBUG(dbgs() << "Not in the same function - skip.\n");
>>> - continue;
>>> - }
>>>
>>> - Instruction *Mat = Base;
>>> - Instruction *InsertBefore = getMatInsertPt(I, DT);
>>> - if (!Offset->isNullValue()) {
>>> - Mat = BinaryOperator::Create(Instruction::Add, Base, Offset,
>>> - "const_mat", InsertBefore);
>>> -
>>> - // Use the same debug location as the instruction we are about to
>>> - // update.
>>> - Mat->setDebugLoc(I->getDebugLoc());
>>> -
>>> - DEBUG(dbgs() << "Materialize constant (" << *Base->getOperand(0)
>>> - << " + " << *Offset << ") in BB "
>>> - << I->getParent()->getName() << '\n' << *Mat << '\n');
>>> - }
>>> - Instruction *ICE = CE->getAsInstruction();
>>> - ICE->replaceUsesOfWith(OriginalConstant, Mat);
>>> - ICE->insertBefore(InsertBefore);
>>> -
>>> - // Use the same debug location as the instruction we are about to update.
>>> - ICE->setDebugLoc(I->getDebugLoc());
>>> -
>>> - WorkList.push_back(std::make_pair(I, ICE));
>>> - } else {
>>> - DEBUG(dbgs() << "Not an instruction - skip.\n");
>>> + // Visit cast instruction.
>>> + if (auto CastInst = dyn_cast<Instruction>(Opnd)) {
>>> + assert(CastInst->isCast() && "Expected an cast instruction!");
>>> + // Check if we already have visited this cast instruction before to avoid
>>> + // unnecessary cloning.
>>> + Instruction *&ClonedCastInst = ClonedCastMap[CastInst];
>>> + if (!ClonedCastInst) {
>>> + ClonedCastInst = CastInst->clone();
>>> + ClonedCastInst->setOperand(0, Mat);
>>> + ClonedCastInst->insertAfter(CastInst);
>>> + // Use the same debug location as the original cast instruction.
>>> + ClonedCastInst->setDebugLoc(CastInst->getDebugLoc());
>>> + DEBUG(dbgs() << "Clone instruction: " << *ClonedCastInst << '\n'
>>> + << "To : " << *CastInst << '\n');
>>> }
>>> +
>>> + DEBUG(dbgs() << "Update: " << *CU.Inst << '\n');
>>> + CU.Inst->setOperand(CU.OpndIdx, ClonedCastInst);
>>> + DEBUG(dbgs() << "To : " << *CU.Inst << '\n');
>>> + return;
>>> }
>>> - SmallVectorImpl<std::pair<Instruction *, Instruction *> >::iterator I, E;
>>> - for (I = WorkList.begin(), E = WorkList.end(); I != E; ++I) {
>>> - DEBUG(dbgs() << "Create instruction: " << *I->second << '\n');
>>> - DEBUG(dbgs() << "Update: " << *I->first << '\n');
>>> - I->first->replaceUsesOfWith(CE, I->second);
>>> - DEBUG(dbgs() << "To: " << *I->first << '\n');
>>> +
>>> + // Visit constant expression.
>>> + if (auto ConstExpr = dyn_cast<ConstantExpr>(Opnd)) {
>>> + Instruction *ConstExprInst = ConstExpr->getAsInstruction();
>>> + ConstExprInst->setOperand(0, Mat);
>>> + ConstExprInst->insertBefore(findMatInsertPt(CU.Inst, CU.OpndIdx));
>>> +
>>> + // Use the same debug location as the instruction we are about to update.
>>> + ConstExprInst->setDebugLoc(CU.Inst->getDebugLoc());
>>> +
>>> + DEBUG(dbgs() << "Create instruction: " << *ConstExprInst << '\n'
>>> + << "From : " << *ConstExpr << '\n');
>>> + DEBUG(dbgs() << "Update: " << *CU.Inst << '\n');
>>> + CU.Inst->setOperand(CU.OpndIdx, ConstExprInst);
>>> + DEBUG(dbgs() << "To : " << *CU.Inst << '\n');
>>> + return;
>>> }
>>> }
>>>
>>> /// \brief Hoist and hide the base constant behind a bitcast and emit
>>> /// materialization code for derived constants.
>>> -bool ConstantHoisting::EmitBaseConstants(Function &F) {
>>> +bool ConstantHoisting::emitBaseConstants() {
>>> bool MadeChange = false;
>>> - SmallVectorImpl<ConstantInfo>::iterator CI, CE;
>>> - for (CI = Constants.begin(), CE = Constants.end(); CI != CE; ++CI) {
>>> + for (auto const &ConstInfo : ConstantVec) {
>>> // Hoist and hide the base constant behind a bitcast.
>>> - Instruction *IP = FindConstantInsertionPoint(F, *CI);
>>> - IntegerType *Ty = CI->BaseConstant->getType();
>>> - Instruction *Base = new BitCastInst(CI->BaseConstant, Ty, "const", IP);
>>> - DEBUG(dbgs() << "Hoist constant (" << *CI->BaseConstant << ") to BB "
>>> - << IP->getParent()->getName() << '\n');
>>> + Instruction *IP = findConstantInsertionPoint(ConstInfo);
>>> + IntegerType *Ty = ConstInfo.BaseConstant->getType();
>>> + Instruction *Base =
>>> + new BitCastInst(ConstInfo.BaseConstant, Ty, "const", IP);
>>> + DEBUG(dbgs() << "Hoist constant (" << *ConstInfo.BaseConstant << ") to BB "
>>> + << IP->getParent()->getName() << '\n' << *Base << '\n');
>>> NumConstantsHoisted++;
>>>
>>> // Emit materialization code for all rebased constants.
>>> - ConstantInfo::RebasedConstantListType::iterator RCI, RCE;
>>> - for (RCI = CI->RebasedConstants.begin(), RCE = CI->RebasedConstants.end();
>>> - RCI != RCE; ++RCI) {
>>> + for (auto const &RCI : ConstInfo.RebasedConstants) {
>>> NumConstantsRebased++;
>>> - for (SmallVectorImpl<User *>::iterator U = RCI->Uses.begin(),
>>> - E = RCI->Uses.end(); U != E; ++U)
>>> - EmitBaseConstants(F, *U, Base, RCI->Offset, RCI->OriginalConstant);
>>> + for (auto const &U : RCI.Uses)
>>> + emitBaseConstants(Base, RCI.Offset, U);
>>> }
>>>
>>> // Use the same debug location as the last user of the constant.
>>> @@ -432,27 +554,37 @@ bool ConstantHoisting::EmitBaseConstants
>>> return MadeChange;
>>> }
>>>
>>> -/// \brief Optimize expensive integer constants in the given function.
>>> -bool ConstantHoisting::OptimizeConstants(Function &F) {
>>> - bool MadeChange = false;
>>> +/// \brief Check all cast instructions we made a copy of and remove them if they
>>> +/// have no more users.
>>> +void ConstantHoisting::deleteDeadCastInst() const {
>>> + for (auto const &I : ClonedCastMap)
>>> + if (I.first->use_empty())
>>> + I.first->removeFromParent();
>>> +}
>>>
>>> +/// \brief Optimize expensive integer constants in the given function.
>>> +bool ConstantHoisting::optimizeConstants(Function &Fn) {
>>> // Collect all constant candidates.
>>> - CollectConstants(F);
>>> + collectConstantCandidates(Fn);
>>>
>>> - // There are no constants to worry about.
>>> - if (ConstantMap.empty())
>>> - return MadeChange;
>>> + // There are no constant candidates to worry about.
>>> + if (ConstCandVec.empty())
>>> + return false;
>>>
>>> // Combine constants that can be easily materialized with an add from a common
>>> // base constant.
>>> - FindBaseConstants();
>>> + findBaseConstants();
>>> +
>>> + // There are no constants to emit.
>>> + if (ConstantVec.empty())
>>> + return false;
>>>
>>> // Finally hoist the base constant and emit materializating code for dependent
>>> // constants.
>>> - MadeChange |= EmitBaseConstants(F);
>>> + bool MadeChange = emitBaseConstants();
>>>
>>> - ConstantMap.clear();
>>> - Constants.clear();
>>> + // Cleanup dead instructions.
>>> + deleteDeadCastInst();
>>>
>>> return MadeChange;
>>> }
>>>
>>> Modified: llvm/trunk/test/CodeGen/X86/lsr-interesting-step.ll
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lsr-interesting-step.ll?rev=204389&r1=204388&r2=204389&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/test/CodeGen/X86/lsr-interesting-step.ll (original)
>>> +++ llvm/trunk/test/CodeGen/X86/lsr-interesting-step.ll Thu Mar 20 14:55:52 2014
>>> @@ -3,26 +3,24 @@
>>> ; The inner loop should require only one add (and no leas either).
>>> ; rdar://8100380
>>>
>>> -; CHECK: BB0_3:
>>> -; CHECK-NEXT: movb $0, flags(%rdx)
>>> -; CHECK-NEXT: addq %rax, %rdx
>>> -; CHECK-NEXT: cmpq $8192, %rdx
>>> +; CHECK: BB0_2:
>>> +; CHECK-NEXT: movb $0, flags(%rcx)
>>> +; CHECK-NEXT: addq %rax, %rcx
>>> +; CHECK-NEXT: cmpq $8192, %rcx
>>> ; CHECK-NEXT: jl
>>>
>>> @flags = external global [8192 x i8], align 16 ; <[8192 x i8]*> [#uses=1]
>>>
>>> define void @foo() nounwind {
>>> entry:
>>> - %tmp = icmp slt i64 2, 8192 ; <i1> [#uses=1]
>>> - br i1 %tmp, label %bb, label %bb21
>>> + br label %bb
>>>
>>> bb: ; preds = %entry
>>> br label %bb7
>>>
>>> bb7: ; preds = %bb, %bb17
>>> %tmp8 = phi i64 [ %tmp18, %bb17 ], [ 2, %bb ] ; <i64> [#uses=2]
>>> - %tmp9 = icmp slt i64 2, 8192 ; <i1> [#uses=1]
>>> - br i1 %tmp9, label %bb10, label %bb17
>>> + br label %bb10
>>>
>>> bb10: ; preds = %bb7
>>> br label %bb11
>>>
>>> Modified: llvm/trunk/test/CodeGen/X86/negate-add-zero.ll
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/negate-add-zero.ll?rev=204389&r1=204388&r2=204389&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/test/CodeGen/X86/negate-add-zero.ll (original)
>>> +++ llvm/trunk/test/CodeGen/X86/negate-add-zero.ll Thu Mar 20 14:55:52 2014
>>> @@ -827,9 +827,7 @@ declare void @_ZN11MatrixTools9transpose
>>> declare void @_ZN21HNodeTranslateRotate311toCartesianEv(%struct.HNodeTranslateRotate3*)
>>>
>>> define linkonce void @_ZN21HNodeTranslateRotate36setVelERK9CDSVectorIdLi1EN3CDS12DefaultAllocEE(%struct.HNodeTranslateRotate3* %this, %"struct.CDSVector<double,0,CDS::DefaultAlloc>"* %velv) {
>>> -entry:
>>> - %0 = add i32 0, -1 ; <i32> [#uses=1]
>>> - %1 = getelementptr double* null, i32 %0 ; <double*> [#uses=1]
>>> + %1 = getelementptr double* null, i32 -1 ; <double*> [#uses=1]
>>> %2 = load double* %1, align 8 ; <double> [#uses=1]
>>> %3 = load double* null, align 8 ; <double> [#uses=2]
>>> %4 = load double* null, align 8 ; <double> [#uses=2]
>>> @@ -890,13 +888,12 @@ entry:
>>> store double %52, double* %55, align 8
>>> %56 = getelementptr %struct.HNodeTranslateRotate3* %this, i32 0, i32 0, i32 10, i32 0, i32 0, i32 2 ; <double*> [#uses=1]
>>> store double %53, double* %56, align 8
>>> - %57 = add i32 0, 4 ; <i32> [#uses=1]
>>> - %58 = getelementptr %"struct.SubVector<CDSVector<double, 1, CDS::DefaultAlloc> >"* null, i32 0, i32 0 ; <%"struct.CDSVector<double,0,CDS::DefaultAlloc>"**> [#uses=1]
>>> - store %"struct.CDSVector<double,0,CDS::DefaultAlloc>"* %velv, %"struct.CDSVector<double,0,CDS::DefaultAlloc>"** %58, align 8
>>> - %59 = getelementptr %"struct.SubVector<CDSVector<double, 1, CDS::DefaultAlloc> >"* null, i32 0, i32 1 ; <i32*> [#uses=1]
>>> - store i32 %57, i32* %59, align 4
>>> - %60 = getelementptr %"struct.SubVector<CDSVector<double, 1, CDS::DefaultAlloc> >"* null, i32 0, i32 2 ; <i32*> [#uses=1]
>>> - store i32 3, i32* %60, align 8
>>> + %57 = getelementptr %"struct.SubVector<CDSVector<double, 1, CDS::DefaultAlloc> >"* null, i32 0, i32 0 ; <%"struct.CDSVector<double,0,CDS::DefaultAlloc>"**> [#uses=1]
>>> + store %"struct.CDSVector<double,0,CDS::DefaultAlloc>"* %velv, %"struct.CDSVector<double,0,CDS::DefaultAlloc>"** %57, align 8
>>> + %58 = getelementptr %"struct.SubVector<CDSVector<double, 1, CDS::DefaultAlloc> >"* null, i32 0, i32 1 ; <i32*> [#uses=1]
>>> + store i32 4, i32* %58, align 4
>>> + %59 = getelementptr %"struct.SubVector<CDSVector<double, 1, CDS::DefaultAlloc> >"* null, i32 0, i32 2 ; <i32*> [#uses=1]
>>> + store i32 3, i32* %59, align 8
>>> unreachable
>>> }
>>>
>>>
>>> Modified: llvm/trunk/test/Transforms/ConstantHoisting/X86/phi.ll
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ConstantHoisting/X86/phi.ll?rev=204389&r1=204388&r2=204389&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/test/Transforms/ConstantHoisting/X86/phi.ll (original)
>>> +++ llvm/trunk/test/Transforms/ConstantHoisting/X86/phi.ll Thu Mar 20 14:55:52 2014
>>> @@ -19,11 +19,11 @@ return:
>>> ret i8* %retval.0
>>>
>>> ; CHECK-LABEL: @test1
>>> -; CHECK: entry:
>>> -; CHECK: %const_mat = add i64 %const, 1
>>> -; CHECK-NEXT: %1 = inttoptr i64 %const_mat to i8*
>>> -; CHECK-NEXT: br i1 %cmp
>>> -; CHECK: %retval.0 = phi i8* [ null, %entry ], [ %1, %if.end ]
>>> +; CHECK: if.end:
>>> +; CHECK: %2 = inttoptr i64 %const to i8*
>>> +; CHECK-NEXT: br
>>> +; CHECK: return:
>>> +; CHECK-NEXT: %retval.0 = phi i8* [ null, %entry ], [ %2, %if.end ]
>>> }
>>>
>>> define void @test2(i1 %cmp, i64** %tmp) {
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list