mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +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:
parent
1709e61793
commit
8562f7e8b8
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
|
@ -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)
|
Loading…
x
Reference in New Issue
Block a user