forked from OSchip/llvm-project
Revert rL305578. There is still some buildbot failure to be fixed.
llvm-svn: 305603
This commit is contained in:
parent
160a97d2e7
commit
c7ba876323
|
@ -68,21 +68,6 @@ public:
|
|||
class ValueTable {
|
||||
DenseMap<Value *, uint32_t> valueNumbering;
|
||||
DenseMap<Expression, uint32_t> expressionNumbering;
|
||||
|
||||
// Expressions is the vector of Expression. ExprIdx is the mapping from
|
||||
// value number to the index of Expression in Expressions. We use it
|
||||
// instead of a DenseMap because filling such mapping is faster than
|
||||
// filling a DenseMap and the compile time is a little better.
|
||||
uint32_t nextExprNumber;
|
||||
std::vector<Expression> Expressions;
|
||||
std::vector<uint32_t> ExprIdx;
|
||||
// Value number to PHINode mapping. Used for phi-translate in scalarpre.
|
||||
DenseMap<uint32_t, PHINode *> NumberingPhi;
|
||||
// Cache for phi-translate in scalarpre.
|
||||
typedef DenseMap<std::pair<uint32_t, const BasicBlock *>, uint32_t>
|
||||
PhiTranslateMap;
|
||||
PhiTranslateMap PhiTranslateTable;
|
||||
|
||||
AliasAnalysis *AA;
|
||||
MemoryDependenceResults *MD;
|
||||
DominatorTree *DT;
|
||||
|
@ -94,10 +79,6 @@ public:
|
|||
Value *LHS, Value *RHS);
|
||||
Expression createExtractvalueExpr(ExtractValueInst *EI);
|
||||
uint32_t lookupOrAddCall(CallInst *C);
|
||||
uint32_t phiTranslateImpl(const BasicBlock *BB, const BasicBlock *PhiBlock,
|
||||
uint32_t Num, GVN &Gvn);
|
||||
std::pair<uint32_t, bool> assignExpNewValueNum(Expression &exp);
|
||||
bool areAllValsInBB(uint32_t num, const BasicBlock *BB, GVN &Gvn);
|
||||
|
||||
public:
|
||||
ValueTable();
|
||||
|
@ -106,11 +87,9 @@ public:
|
|||
~ValueTable();
|
||||
|
||||
uint32_t lookupOrAdd(Value *V);
|
||||
uint32_t lookup(Value *V, bool Verify = true) const;
|
||||
uint32_t lookup(Value *V) const;
|
||||
uint32_t lookupOrAddCmp(unsigned Opcode, CmpInst::Predicate Pred,
|
||||
Value *LHS, Value *RHS);
|
||||
uint32_t phiTranslate(const BasicBlock *BB, const BasicBlock *PhiBlock,
|
||||
uint32_t Num, GVN &Gvn);
|
||||
bool exists(Value *V) const;
|
||||
void add(Value *V, uint32_t num);
|
||||
void clear();
|
||||
|
@ -152,10 +131,6 @@ private:
|
|||
SmallMapVector<llvm::Value *, llvm::Constant *, 4> ReplaceWithConstMap;
|
||||
SmallVector<Instruction *, 8> InstrsToErase;
|
||||
|
||||
// Map the block to reversed postorder traversal number. It is used to
|
||||
// find back edge easily.
|
||||
DenseMap<const BasicBlock *, uint32_t> BlockRPONumber;
|
||||
|
||||
typedef SmallVector<NonLocalDepResult, 64> LoadDepVect;
|
||||
typedef SmallVector<gvn::AvailableValueInBlock, 64> AvailValInBlkVect;
|
||||
typedef SmallVector<BasicBlock *, 64> UnavailBlkVect;
|
||||
|
@ -239,7 +214,7 @@ private:
|
|||
bool performPRE(Function &F);
|
||||
bool performScalarPRE(Instruction *I);
|
||||
bool performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
|
||||
BasicBlock *Curr, unsigned int ValNo);
|
||||
unsigned int ValNo);
|
||||
Value *findLeader(const BasicBlock *BB, uint32_t num);
|
||||
void cleanupGlobalSets();
|
||||
void verifyRemoved(const Instruction *I) const;
|
||||
|
@ -251,7 +226,6 @@ private:
|
|||
bool processFoldableCondBr(BranchInst *BI);
|
||||
void addDeadBlock(BasicBlock *BB);
|
||||
void assignValNumForDeadCode();
|
||||
void assignBlockRPONumber(Function &F);
|
||||
};
|
||||
|
||||
/// Create a legacy GVN pass. This also allows parameterizing whether or not
|
||||
|
|
|
@ -80,10 +80,9 @@ MaxRecurseDepth("max-recurse-depth", cl::Hidden, cl::init(1000), cl::ZeroOrMore,
|
|||
struct llvm::GVN::Expression {
|
||||
uint32_t opcode;
|
||||
Type *type;
|
||||
bool commutative;
|
||||
SmallVector<uint32_t, 4> varargs;
|
||||
|
||||
Expression(uint32_t o = ~2U) : opcode(o), commutative(false) {}
|
||||
Expression(uint32_t o = ~2U) : opcode(o) {}
|
||||
|
||||
bool operator==(const Expression &other) const {
|
||||
if (opcode != other.opcode)
|
||||
|
@ -247,7 +246,6 @@ GVN::Expression GVN::ValueTable::createExpr(Instruction *I) {
|
|||
assert(I->getNumOperands() == 2 && "Unsupported commutative instruction!");
|
||||
if (e.varargs[0] > e.varargs[1])
|
||||
std::swap(e.varargs[0], e.varargs[1]);
|
||||
e.commutative = true;
|
||||
}
|
||||
|
||||
if (CmpInst *C = dyn_cast<CmpInst>(I)) {
|
||||
|
@ -258,7 +256,6 @@ GVN::Expression GVN::ValueTable::createExpr(Instruction *I) {
|
|||
Predicate = CmpInst::getSwappedPredicate(Predicate);
|
||||
}
|
||||
e.opcode = (C->getOpcode() << 8) | Predicate;
|
||||
e.commutative = true;
|
||||
} else if (InsertValueInst *E = dyn_cast<InsertValueInst>(I)) {
|
||||
for (InsertValueInst::idx_iterator II = E->idx_begin(), IE = E->idx_end();
|
||||
II != IE; ++II)
|
||||
|
@ -284,7 +281,6 @@ GVN::Expression GVN::ValueTable::createCmpExpr(unsigned Opcode,
|
|||
Predicate = CmpInst::getSwappedPredicate(Predicate);
|
||||
}
|
||||
e.opcode = (Opcode << 8) | Predicate;
|
||||
e.commutative = true;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -352,25 +348,25 @@ GVN::ValueTable::~ValueTable() = default;
|
|||
/// add - Insert a value into the table with a specified value number.
|
||||
void GVN::ValueTable::add(Value *V, uint32_t num) {
|
||||
valueNumbering.insert(std::make_pair(V, num));
|
||||
if (PHINode *PN = dyn_cast<PHINode>(V))
|
||||
NumberingPhi[num] = PN;
|
||||
}
|
||||
|
||||
uint32_t GVN::ValueTable::lookupOrAddCall(CallInst *C) {
|
||||
if (AA->doesNotAccessMemory(C)) {
|
||||
Expression exp = createExpr(C);
|
||||
uint32_t e = assignExpNewValueNum(exp).first;
|
||||
uint32_t &e = expressionNumbering[exp];
|
||||
if (!e) e = nextValueNumber++;
|
||||
valueNumbering[C] = e;
|
||||
return e;
|
||||
} else if (AA->onlyReadsMemory(C)) {
|
||||
Expression exp = createExpr(C);
|
||||
auto ValNum = assignExpNewValueNum(exp);
|
||||
if (ValNum.second) {
|
||||
valueNumbering[C] = ValNum.first;
|
||||
return ValNum.first;
|
||||
uint32_t &e = expressionNumbering[exp];
|
||||
if (!e) {
|
||||
e = nextValueNumber++;
|
||||
valueNumbering[C] = e;
|
||||
return e;
|
||||
}
|
||||
if (!MD) {
|
||||
uint32_t e = assignExpNewValueNum(exp).first;
|
||||
e = nextValueNumber++;
|
||||
valueNumbering[C] = e;
|
||||
return e;
|
||||
}
|
||||
|
@ -526,29 +522,23 @@ uint32_t GVN::ValueTable::lookupOrAdd(Value *V) {
|
|||
case Instruction::ExtractValue:
|
||||
exp = createExtractvalueExpr(cast<ExtractValueInst>(I));
|
||||
break;
|
||||
case Instruction::PHI:
|
||||
valueNumbering[V] = nextValueNumber;
|
||||
NumberingPhi[nextValueNumber] = cast<PHINode>(V);
|
||||
return nextValueNumber++;
|
||||
default:
|
||||
valueNumbering[V] = nextValueNumber;
|
||||
return nextValueNumber++;
|
||||
}
|
||||
|
||||
uint32_t e = assignExpNewValueNum(exp).first;
|
||||
uint32_t& e = expressionNumbering[exp];
|
||||
if (!e) e = nextValueNumber++;
|
||||
valueNumbering[V] = e;
|
||||
return e;
|
||||
}
|
||||
|
||||
/// Returns the value number of the specified value. Fails if
|
||||
/// the value has not yet been numbered.
|
||||
uint32_t GVN::ValueTable::lookup(Value *V, bool Verify) const {
|
||||
uint32_t GVN::ValueTable::lookup(Value *V) const {
|
||||
DenseMap<Value*, uint32_t>::const_iterator VI = valueNumbering.find(V);
|
||||
if (Verify) {
|
||||
assert(VI != valueNumbering.end() && "Value not numbered?");
|
||||
return VI->second;
|
||||
}
|
||||
return (VI != valueNumbering.end()) ? VI->second : 0;
|
||||
assert(VI != valueNumbering.end() && "Value not numbered?");
|
||||
return VI->second;
|
||||
}
|
||||
|
||||
/// Returns the value number of the given comparison,
|
||||
|
@ -559,28 +549,21 @@ uint32_t GVN::ValueTable::lookupOrAddCmp(unsigned Opcode,
|
|||
CmpInst::Predicate Predicate,
|
||||
Value *LHS, Value *RHS) {
|
||||
Expression exp = createCmpExpr(Opcode, Predicate, LHS, RHS);
|
||||
return assignExpNewValueNum(exp).first;
|
||||
uint32_t& e = expressionNumbering[exp];
|
||||
if (!e) e = nextValueNumber++;
|
||||
return e;
|
||||
}
|
||||
|
||||
/// Remove all entries from the ValueTable.
|
||||
void GVN::ValueTable::clear() {
|
||||
valueNumbering.clear();
|
||||
expressionNumbering.clear();
|
||||
NumberingPhi.clear();
|
||||
PhiTranslateTable.clear();
|
||||
nextValueNumber = 1;
|
||||
Expressions.clear();
|
||||
ExprIdx.clear();
|
||||
nextExprNumber = 0;
|
||||
}
|
||||
|
||||
/// Remove a value from the value numbering.
|
||||
void GVN::ValueTable::erase(Value *V) {
|
||||
uint32_t Num = valueNumbering.lookup(V);
|
||||
valueNumbering.erase(V);
|
||||
// If V is PHINode, V <--> value number is an one-to-one mapping.
|
||||
if (isa<PHINode>(V))
|
||||
NumberingPhi.erase(Num);
|
||||
}
|
||||
|
||||
/// verifyRemoved - Verify that the value is removed from all internal data
|
||||
|
@ -1468,95 +1451,6 @@ bool GVN::processLoad(LoadInst *L) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// Return a pair the first field showing the value number of \p Exp and the
|
||||
/// second field showing whether it is a value number newly created.
|
||||
std::pair<uint32_t, bool>
|
||||
GVN::ValueTable::assignExpNewValueNum(Expression &Exp) {
|
||||
uint32_t &e = expressionNumbering[Exp];
|
||||
bool CreateNewValNum = !e;
|
||||
if (CreateNewValNum) {
|
||||
Expressions.push_back(Exp);
|
||||
if (ExprIdx.size() < nextValueNumber + 1)
|
||||
ExprIdx.resize(nextValueNumber * 2);
|
||||
e = nextValueNumber;
|
||||
ExprIdx[nextValueNumber++] = nextExprNumber++;
|
||||
}
|
||||
return {e, CreateNewValNum};
|
||||
}
|
||||
|
||||
/// Return whether all the values related with the same \p num are
|
||||
/// defined in \p BB.
|
||||
bool GVN::ValueTable::areAllValsInBB(uint32_t Num, const BasicBlock *BB,
|
||||
GVN &Gvn) {
|
||||
LeaderTableEntry *Vals = &Gvn.LeaderTable[Num];
|
||||
while (Vals && Vals->BB == BB)
|
||||
Vals = Vals->Next;
|
||||
return !Vals;
|
||||
}
|
||||
|
||||
/// Wrap phiTranslateImpl to provide caching functionality.
|
||||
uint32_t GVN::ValueTable::phiTranslate(const BasicBlock *Pred,
|
||||
const BasicBlock *PhiBlock, uint32_t Num,
|
||||
GVN &Gvn) {
|
||||
auto FindRes = PhiTranslateTable.find({Num, Pred});
|
||||
if (FindRes != PhiTranslateTable.end())
|
||||
return FindRes->second;
|
||||
uint32_t NewNum = phiTranslateImpl(Pred, PhiBlock, Num, Gvn);
|
||||
PhiTranslateTable.insert({{Num, Pred}, NewNum});
|
||||
return NewNum;
|
||||
}
|
||||
|
||||
/// Translate value number \p Num using phis, so that it has the values of
|
||||
/// the phis in BB.
|
||||
uint32_t GVN::ValueTable::phiTranslateImpl(const BasicBlock *Pred,
|
||||
const BasicBlock *PhiBlock,
|
||||
uint32_t Num, GVN &Gvn) {
|
||||
if (PHINode *PN = NumberingPhi[Num]) {
|
||||
for (unsigned i = 0; i != PN->getNumIncomingValues(); ++i) {
|
||||
if (PN->getParent() == PhiBlock && PN->getIncomingBlock(i) == Pred)
|
||||
if (uint32_t TransVal = lookup(PN->getIncomingValue(i), false))
|
||||
return TransVal;
|
||||
}
|
||||
return Num;
|
||||
}
|
||||
|
||||
// If there is any value related with Num is defined in a BB other than
|
||||
// PhiBlock, it cannot depend on a phi in PhiBlock without going through
|
||||
// a backedge. We can do an early exit in that case to save compile time.
|
||||
if (!areAllValsInBB(Num, PhiBlock, Gvn))
|
||||
return Num;
|
||||
|
||||
if (ExprIdx[Num] == 0 || Num >= ExprIdx.size())
|
||||
return Num;
|
||||
Expression Exp = Expressions[ExprIdx[Num]];
|
||||
|
||||
for (unsigned i = 0; i < Exp.varargs.size(); i++) {
|
||||
// For InsertValue and ExtractValue, some varargs are index numbers
|
||||
// instead of value numbers. Those index numbers should not be
|
||||
// translated.
|
||||
if ((i > 1 && Exp.opcode == Instruction::InsertValue) ||
|
||||
(i > 0 && Exp.opcode == Instruction::ExtractValue))
|
||||
continue;
|
||||
Exp.varargs[i] = phiTranslate(Pred, PhiBlock, Exp.varargs[i], Gvn);
|
||||
}
|
||||
|
||||
if (Exp.commutative) {
|
||||
assert(Exp.varargs.size() == 2 && "Unsupported commutative expression!");
|
||||
if (Exp.varargs[0] > Exp.varargs[1]) {
|
||||
std::swap(Exp.varargs[0], Exp.varargs[1]);
|
||||
uint32_t Opcode = Exp.opcode >> 8;
|
||||
if (Opcode == Instruction::ICmp || Opcode == Instruction::FCmp)
|
||||
Exp.opcode = (Opcode << 8) |
|
||||
CmpInst::getSwappedPredicate(
|
||||
static_cast<CmpInst::Predicate>(Exp.opcode & 255));
|
||||
}
|
||||
}
|
||||
|
||||
if (uint32_t NewNum = expressionNumbering[Exp])
|
||||
return NewNum;
|
||||
return Num;
|
||||
}
|
||||
|
||||
// In order to find a leader for a given value number at a
|
||||
// specific basic block, we first obtain the list of all Values for that number,
|
||||
// and then scan the list to find one whose block dominates the block in
|
||||
|
@ -1601,15 +1495,6 @@ static bool isOnlyReachableViaThisEdge(const BasicBlockEdge &E,
|
|||
return Pred != nullptr;
|
||||
}
|
||||
|
||||
|
||||
void GVN::assignBlockRPONumber(Function &F) {
|
||||
uint32_t NextBlockNumber = 1;
|
||||
ReversePostOrderTraversal<Function *> RPOT(&F);
|
||||
for (BasicBlock *BB : RPOT)
|
||||
BlockRPONumber[BB] = NextBlockNumber++;
|
||||
}
|
||||
|
||||
|
||||
// Tries to replace instruction with const, using information from
|
||||
// ReplaceWithConstMap.
|
||||
bool GVN::replaceOperandsWithConsts(Instruction *Instr) const {
|
||||
|
@ -1971,7 +1856,6 @@ bool GVN::runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
|
|||
// Fabricate val-num for dead-code in order to suppress assertion in
|
||||
// performPRE().
|
||||
assignValNumForDeadCode();
|
||||
assignBlockRPONumber(F);
|
||||
bool PREChanged = true;
|
||||
while (PREChanged) {
|
||||
PREChanged = performPRE(F);
|
||||
|
@ -2043,7 +1927,7 @@ bool GVN::processBlock(BasicBlock *BB) {
|
|||
|
||||
// Instantiate an expression in a predecessor that lacked it.
|
||||
bool GVN::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
|
||||
BasicBlock *Curr, unsigned int ValNo) {
|
||||
unsigned int ValNo) {
|
||||
// Because we are going top-down through the block, all value numbers
|
||||
// will be available in the predecessor by the time we need them. Any
|
||||
// that weren't originally present will have been instantiated earlier
|
||||
|
@ -2061,9 +1945,7 @@ bool GVN::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
|
|||
success = false;
|
||||
break;
|
||||
}
|
||||
uint32_t TValNo =
|
||||
VN.phiTranslate(Pred, Curr, VN.lookup(Op), *this);
|
||||
if (Value *V = findLeader(Pred, TValNo)) {
|
||||
if (Value *V = findLeader(Pred, VN.lookup(Op))) {
|
||||
Instr->setOperand(i, V);
|
||||
} else {
|
||||
success = false;
|
||||
|
@ -2080,12 +1962,10 @@ bool GVN::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
|
|||
Instr->insertBefore(Pred->getTerminator());
|
||||
Instr->setName(Instr->getName() + ".pre");
|
||||
Instr->setDebugLoc(Instr->getDebugLoc());
|
||||
|
||||
unsigned Num = VN.lookupOrAdd(Instr);
|
||||
VN.add(Instr, Num);
|
||||
VN.add(Instr, ValNo);
|
||||
|
||||
// Update the availability map to include the new instruction.
|
||||
addToLeaderTable(Num, Instr, Pred);
|
||||
addToLeaderTable(ValNo, Instr, Pred);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2123,27 +2003,18 @@ bool GVN::performScalarPRE(Instruction *CurInst) {
|
|||
|
||||
SmallVector<std::pair<Value *, BasicBlock *>, 8> predMap;
|
||||
for (BasicBlock *P : predecessors(CurrentBlock)) {
|
||||
// We're not interested in PRE where blocks with predecessors that are
|
||||
// not reachable.
|
||||
if (!DT->isReachableFromEntry(P)) {
|
||||
// We're not interested in PRE where the block is its
|
||||
// own predecessor, or in blocks with predecessors
|
||||
// that are not reachable.
|
||||
if (P == CurrentBlock) {
|
||||
NumWithout = 2;
|
||||
break;
|
||||
}
|
||||
// It is not safe to do PRE when P->CurrentBlock is a loop backedge, and
|
||||
// when CurInst has operand defined in CurrentBlock (so it may be defined
|
||||
// by phi in the loop header).
|
||||
if (BlockRPONumber[P] >= BlockRPONumber[CurrentBlock] &&
|
||||
any_of(CurInst->operands(), [&](const Use &U) {
|
||||
if (auto *Inst = dyn_cast<Instruction>(U.get()))
|
||||
return Inst->getParent() == CurrentBlock;
|
||||
return false;
|
||||
})) {
|
||||
} else if (!DT->isReachableFromEntry(P)) {
|
||||
NumWithout = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t TValNo = VN.phiTranslate(P, CurrentBlock, ValNo, *this);
|
||||
Value *predV = findLeader(P, TValNo);
|
||||
Value *predV = findLeader(P, ValNo);
|
||||
if (!predV) {
|
||||
predMap.push_back(std::make_pair(static_cast<Value *>(nullptr), P));
|
||||
PREPred = P;
|
||||
|
@ -2183,7 +2054,7 @@ bool GVN::performScalarPRE(Instruction *CurInst) {
|
|||
}
|
||||
// We need to insert somewhere, so let's give it a shot
|
||||
PREInstr = CurInst->clone();
|
||||
if (!performScalarPREInsertion(PREInstr, PREPred, CurrentBlock, ValNo)) {
|
||||
if (!performScalarPREInsertion(PREInstr, PREPred, ValNo)) {
|
||||
// If we failed insertion, make sure we remove the instruction.
|
||||
DEBUG(verifyRemoved(PREInstr));
|
||||
PREInstr->deleteValue();
|
||||
|
@ -2297,7 +2168,6 @@ bool GVN::iterateOnFunction(Function &F) {
|
|||
void GVN::cleanupGlobalSets() {
|
||||
VN.clear();
|
||||
LeaderTable.clear();
|
||||
BlockRPONumber.clear();
|
||||
TableAllocator.Reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,131 +0,0 @@
|
|||
; RUN: opt < %s -gvn -S | FileCheck %s
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
|
||||
@a = common global [100 x i64] zeroinitializer, align 16
|
||||
@b = common global [100 x i64] zeroinitializer, align 16
|
||||
@g1 = common global i64 0, align 8
|
||||
@g2 = common global i64 0, align 8
|
||||
@g3 = common global i64 0, align 8
|
||||
declare i64 @goo(...) local_unnamed_addr #1
|
||||
|
||||
define void @test1(i64 %a, i64 %b, i64 %c, i64 %d) {
|
||||
entry:
|
||||
%mul = mul nsw i64 %b, %a
|
||||
store i64 %mul, i64* @g1, align 8
|
||||
%t0 = load i64, i64* @g2, align 8
|
||||
%cmp = icmp sgt i64 %t0, 3
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
||||
if.then: ; preds = %entry
|
||||
%mul2 = mul nsw i64 %d, %c
|
||||
store i64 %mul2, i64* @g2, align 8
|
||||
br label %if.end
|
||||
|
||||
; Check phi-translate works and mul is removed.
|
||||
; CHECK-LABEL: @test1(
|
||||
; CHECK: if.end:
|
||||
; CHECK: %[[MULPHI:.*]] = phi i64 [ {{.*}}, %if.then ], [ %mul, %entry ]
|
||||
; CHECK-NOT: = mul
|
||||
; CHECK: store i64 %[[MULPHI]], i64* @g3, align 8
|
||||
if.end: ; preds = %if.then, %entry
|
||||
%b.addr.0 = phi i64 [ %d, %if.then ], [ %b, %entry ]
|
||||
%a.addr.0 = phi i64 [ %c, %if.then ], [ %a, %entry ]
|
||||
%mul3 = mul nsw i64 %a.addr.0, %b.addr.0
|
||||
store i64 %mul3, i64* @g3, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test2(i64 %i) {
|
||||
entry:
|
||||
%arrayidx = getelementptr inbounds [100 x i64], [100 x i64]* @a, i64 0, i64 %i
|
||||
%t0 = load i64, i64* %arrayidx, align 8
|
||||
%arrayidx1 = getelementptr inbounds [100 x i64], [100 x i64]* @b, i64 0, i64 %i
|
||||
%t1 = load i64, i64* %arrayidx1, align 8
|
||||
%mul = mul nsw i64 %t1, %t0
|
||||
store i64 %mul, i64* @g1, align 8
|
||||
%cmp = icmp sgt i64 %mul, 3
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
||||
; Check phi-translate works for the phi generated by loadpre. A new mul will be
|
||||
; inserted in if.then block.
|
||||
; CHECK-LABEL: @test2(
|
||||
; CHECK: if.then:
|
||||
; CHECK: %[[MUL_THEN:.*]] = mul
|
||||
; CHECK: br label %if.end
|
||||
if.then: ; preds = %entry
|
||||
%call = tail call i64 (...) @goo() #2
|
||||
store i64 %call, i64* @g2, align 8
|
||||
br label %if.end
|
||||
|
||||
; CHECK: if.end:
|
||||
; CHECK: %[[MULPHI:.*]] = phi i64 [ %[[MUL_THEN]], %if.then ], [ %mul, %entry ]
|
||||
; CHECK-NOT: = mul
|
||||
; CHECK: store i64 %[[MULPHI]], i64* @g3, align 8
|
||||
if.end: ; preds = %if.then, %entry
|
||||
%i.addr.0 = phi i64 [ 3, %if.then ], [ %i, %entry ]
|
||||
%arrayidx3 = getelementptr inbounds [100 x i64], [100 x i64]* @a, i64 0, i64 %i.addr.0
|
||||
%t2 = load i64, i64* %arrayidx3, align 8
|
||||
%arrayidx4 = getelementptr inbounds [100 x i64], [100 x i64]* @b, i64 0, i64 %i.addr.0
|
||||
%t3 = load i64, i64* %arrayidx4, align 8
|
||||
%mul5 = mul nsw i64 %t3, %t2
|
||||
store i64 %mul5, i64* @g3, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check phi-translate doesn't go through backedge, which may lead to incorrect
|
||||
; pre transformation.
|
||||
; CHECK: for.end:
|
||||
; CHECK-NOT: %{{.*pre-phi}} = phi
|
||||
; CHECK: ret void
|
||||
define void @test3(i64 %N, i64* nocapture readonly %a) {
|
||||
entry:
|
||||
br label %for.cond
|
||||
|
||||
for.cond: ; preds = %for.body, %entry
|
||||
%i.0 = phi i64 [ 0, %entry ], [ %add, %for.body ]
|
||||
%add = add nuw nsw i64 %i.0, 1
|
||||
%arrayidx = getelementptr inbounds i64, i64* %a, i64 %add
|
||||
%tmp0 = load i64, i64* %arrayidx, align 8
|
||||
%cmp = icmp slt i64 %i.0, %N
|
||||
br i1 %cmp, label %for.body, label %for.end
|
||||
|
||||
for.body: ; preds = %for.cond
|
||||
%call = tail call i64 (...) @goo() #2
|
||||
%add1 = sub nsw i64 0, %call
|
||||
%tobool = icmp eq i64 %tmp0, %add1
|
||||
br i1 %tobool, label %for.cond, label %for.end
|
||||
|
||||
for.end: ; preds = %for.body, %for.cond
|
||||
%i.0.lcssa = phi i64 [ %i.0, %for.body ], [ %i.0, %for.cond ]
|
||||
%arrayidx2 = getelementptr inbounds i64, i64* %a, i64 %i.0.lcssa
|
||||
%tmp1 = load i64, i64* %arrayidx2, align 8
|
||||
store i64 %tmp1, i64* @g1, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
; It is incorrect to use the value of %andres in last loop iteration
|
||||
; to do pre.
|
||||
; CHECK-LABEL: @test4(
|
||||
; CHECK: for.body:
|
||||
; CHECK-NOT: %andres.pre-phi = phi i32
|
||||
; CHECK: br i1 %tobool1
|
||||
|
||||
define i32 @test4(i32 %cond, i32 %SectionAttrs.0231.ph, i32 *%AttrFlag) {
|
||||
for.body.preheader:
|
||||
%t514 = load volatile i32, i32* %AttrFlag
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%t320 = phi i32 [ %t334, %bb343 ], [ %t514, %for.body.preheader ]
|
||||
%andres = and i32 %t320, %SectionAttrs.0231.ph
|
||||
%tobool1 = icmp eq i32 %andres, 0
|
||||
br i1 %tobool1, label %bb343, label %critedge.loopexit
|
||||
|
||||
bb343:
|
||||
%t334 = load volatile i32, i32* %AttrFlag
|
||||
%tobool2 = icmp eq i32 %cond, 0
|
||||
br i1 %tobool2, label %critedge.loopexit, label %for.body
|
||||
|
||||
critedge.loopexit:
|
||||
unreachable
|
||||
}
|
|
@ -37,7 +37,7 @@ sw.bb2: ; preds = %if.end, %entry
|
|||
%3 = load double, double* %arrayidx5, align 8
|
||||
; CHECK: sw.bb2:
|
||||
; CHECK-NOT: sext
|
||||
; CHECK: phi double [
|
||||
; CHECK-NEXT: phi double [
|
||||
; CHECK-NOT: load
|
||||
%sub6 = fsub double 3.000000e+00, %3
|
||||
br label %return
|
||||
|
|
|
@ -72,7 +72,7 @@ block4:
|
|||
%PRE = load i32, i32* %P3
|
||||
ret i32 %PRE
|
||||
; CHECK: block4:
|
||||
; CHECK: phi i32 [
|
||||
; CHECK-NEXT: phi i32 [
|
||||
; CHECK-NOT: load
|
||||
; CHECK: ret i32
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ block4:
|
|||
%PRE = load i32, i32* %P3
|
||||
ret i32 %PRE
|
||||
; CHECK: block4:
|
||||
; CHECK: phi i32 [
|
||||
; CHECK-NEXT: phi i32 [
|
||||
; CHECK-NOT: load
|
||||
; CHECK: ret i32
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ block4:
|
|||
%PRE = load i32, i32* %P3
|
||||
ret i32 %PRE
|
||||
; CHECK: block4:
|
||||
; CHECK: phi i32 [
|
||||
; CHECK-NEXT: phi i32 [
|
||||
; CHECK-NOT: load
|
||||
; CHECK: ret i32
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue