1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[IndVars] Remove -liv-reduce

It is an off-by-default option that no one seems to use[0], and given
that SCEV directly understands the overflow instrinsics there is no real
need for it anymore.

[0]: http://lists.llvm.org/pipermail/llvm-dev/2016-April/098181.html

llvm-svn: 271845
This commit is contained in:
Sanjoy Das 2016-06-05 18:01:12 +00:00
parent 1709e61793
commit 8562f7e8b8
4 changed files with 1 additions and 144 deletions

View File

@ -33,24 +33,14 @@ class ScalarEvolution;
class IVVisitor {
protected:
const DominatorTree *DT;
bool ShouldSplitOverflowIntrinsics;
virtual void anchor();
public:
IVVisitor(): DT(nullptr), ShouldSplitOverflowIntrinsics(false) {}
IVVisitor() : DT(nullptr) {}
virtual ~IVVisitor() {}
const DominatorTree *getDomTree() const { return DT; }
bool shouldSplitOverflowInstrinsics() const {
return ShouldSplitOverflowIntrinsics;
}
void setSplitOverflowIntrinsics() {
ShouldSplitOverflowIntrinsics = true;
assert(DT && "Splitting overflow intrinsics requires a DomTree.");
}
virtual void visitCast(CastInst *Cast) = 0;
};

View File

@ -68,9 +68,6 @@ static cl::opt<bool> VerifyIndvars(
"verify-indvars", cl::Hidden,
cl::desc("Verify the ScalarEvolution result after running indvars"));
static cl::opt<bool> ReduceLiveIVs("liv-reduce", cl::Hidden,
cl::desc("Reduce live induction variables."));
enum ReplaceExitVal { NeverRepl, OnlyCheapRepl, AlwaysRepl };
static cl::opt<ReplaceExitVal> ReplaceExitValue(
@ -1489,8 +1486,6 @@ public:
: SE(SCEV), TTI(TTI), IVPhi(IV) {
DT = DTree;
WI.NarrowIV = IVPhi;
if (ReduceLiveIVs)
setSplitOverflowIntrinsics();
}
// Implement the interface used by simplifyUsersOfIV.

View File

@ -76,9 +76,6 @@ namespace {
void eliminateIVRemainder(BinaryOperator *Rem, Value *IVOperand,
bool IsSigned);
bool strengthenOverflowingOperation(BinaryOperator *OBO, Value *IVOperand);
Instruction *splitOverflowIntrinsic(Instruction *IVUser,
const DominatorTree *DT);
};
}
@ -552,69 +549,6 @@ bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO,
return Changed;
}
/// \brief Split sadd.with.overflow into add + sadd.with.overflow to allow
/// analysis and optimization.
///
/// \return A new value representing the non-overflowing add if possible,
/// otherwise return the original value.
Instruction *SimplifyIndvar::splitOverflowIntrinsic(Instruction *IVUser,
const DominatorTree *DT) {
IntrinsicInst *II = dyn_cast<IntrinsicInst>(IVUser);
if (!II || II->getIntrinsicID() != Intrinsic::sadd_with_overflow)
return IVUser;
// Find a branch guarded by the overflow check.
BranchInst *Branch = nullptr;
Instruction *AddVal = nullptr;
for (User *U : II->users()) {
if (ExtractValueInst *ExtractInst = dyn_cast<ExtractValueInst>(U)) {
if (ExtractInst->getNumIndices() != 1)
continue;
if (ExtractInst->getIndices()[0] == 0)
AddVal = ExtractInst;
else if (ExtractInst->getIndices()[0] == 1 && ExtractInst->hasOneUse())
Branch = dyn_cast<BranchInst>(ExtractInst->user_back());
}
}
if (!AddVal || !Branch)
return IVUser;
BasicBlock *ContinueBB = Branch->getSuccessor(1);
if (std::next(pred_begin(ContinueBB)) != pred_end(ContinueBB))
return IVUser;
// Check if all users of the add are provably NSW.
bool AllNSW = true;
for (Use &U : AddVal->uses()) {
if (Instruction *UseInst = dyn_cast<Instruction>(U.getUser())) {
BasicBlock *UseBB = UseInst->getParent();
if (PHINode *PHI = dyn_cast<PHINode>(UseInst))
UseBB = PHI->getIncomingBlock(U);
if (!DT->dominates(ContinueBB, UseBB)) {
AllNSW = false;
break;
}
}
}
if (!AllNSW)
return IVUser;
// Go for it...
IRBuilder<> Builder(IVUser);
Instruction *AddInst = dyn_cast<Instruction>(
Builder.CreateNSWAdd(II->getOperand(0), II->getOperand(1)));
// The caller expects the new add to have the same form as the intrinsic. The
// IV operand position must be the same.
assert((AddInst->getOpcode() == Instruction::Add &&
AddInst->getOperand(0) == II->getOperand(0)) &&
"Bad add instruction created from overflow intrinsic.");
AddVal->replaceAllUsesWith(AddInst);
DeadInsts.emplace_back(AddVal);
return AddInst;
}
/// Add all uses of Def to the current IV's worklist.
static void pushIVUsers(
Instruction *Def,
@ -689,12 +623,6 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
// Bypass back edges to avoid extra work.
if (UseInst == CurrIV) continue;
if (V && V->shouldSplitOverflowInstrinsics()) {
UseInst = splitOverflowIntrinsic(UseInst, V->getDomTree());
if (!UseInst)
continue;
}
Instruction *IVOperand = UseOper.second;
for (unsigned N = 0; IVOperand; ++N) {
assert(N <= Simplified.size() && "runaway iteration");

View File

@ -1,56 +0,0 @@
; RUN: opt < %s -indvars -liv-reduce -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx"
; CHECK-LABEL: @addwithoverflow
; CHECK-LABEL: loop1:
; CHECK-NOT: zext
; CHECK: add nsw
; CHECK: @llvm.sadd.with.overflow
; CHECK-LABEL: loop2:
; CHECK-NOT: extractvalue
; CHECK: add nuw
; CHECK: @llvm.sadd.with.overflow
; CHECK-LABEL: loop3:
; CHECK-NOT: extractvalue
; CHECK: ret
define i64 @addwithoverflow(i32 %n, i64* %a) {
entry:
br label %loop0
loop0:
%i = phi i32 [ 0, %entry ], [ %i1val, %loop3 ]
%s = phi i32 [ 0, %entry ], [ %addsval, %loop3 ]
%bc = icmp ult i32 %i, %n
br i1 %bc, label %loop1, label %exit
loop1:
%zxt = zext i32 %i to i64
%ofs = shl nuw nsw i64 %zxt, 3
%gep = getelementptr i64, i64* %a, i64 %zxt
%v = load i64, i64* %gep, align 8
%truncv = trunc i64 %v to i32
%adds = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %s, i32 %truncv)
%ovflows = extractvalue { i32, i1 } %adds, 1
br i1 %ovflows, label %exit, label %loop2
loop2:
%addsval = extractvalue { i32, i1 } %adds, 0
%i1 = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i, i32 1)
%i1check = extractvalue { i32, i1 } %i1, 1
br i1 %i1check, label %exit, label %loop3
loop3:
%i1val = extractvalue { i32, i1 } %i1, 0
%test = icmp slt i32 %i1val, %n
br i1 %test, label %return, label %loop0
return:
%ret = zext i32 %addsval to i64
ret i64 %ret
exit:
unreachable
}
declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32)