[llvm] r204389 - [Constant Hoisting] Extend coverage of the constant hoisting pass.
Eric Christopher
echristo at gmail.com
Thu Mar 20 13:12:39 PDT 2014
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