mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
[SCCP] Turn sext into zext for non-negative ranges.
This patch updates SCCP/IPSCCP to use the computed range info to turn sexts into zexts, if the value is known to be non-negative. We already to a similar transform in CorrelatedValuePropagation, but it seems like we can catch a lot of additional cases by doing it in SCCP/IPSCCP as well. The transform is limited to ranges that are known to not include undef. Currently constant ranges from conditions are treated as potentially containing undef, due to PR46144. Once we flip this, the transform will be more effective in practice. Reviewers: efriedma, davide Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D81756
This commit is contained in:
parent
ff3ee09ec7
commit
932ea47fda
@ -67,10 +67,15 @@ using namespace llvm;
|
||||
|
||||
STATISTIC(NumInstRemoved, "Number of instructions removed");
|
||||
STATISTIC(NumDeadBlocks , "Number of basic blocks unreachable");
|
||||
STATISTIC(NumInstReplaced,
|
||||
"Number of instructions replaced with (simpler) instruction");
|
||||
|
||||
STATISTIC(IPNumInstRemoved, "Number of instructions removed by IPSCCP");
|
||||
STATISTIC(IPNumArgsElimed ,"Number of arguments constant propagated by IPSCCP");
|
||||
STATISTIC(IPNumGlobalConst, "Number of globals found to be constant by IPSCCP");
|
||||
STATISTIC(
|
||||
IPNumInstReplaced,
|
||||
"Number of instructions replaced with (simpler) instruction by IPSCCP");
|
||||
|
||||
// The maximum number of range extensions allowed for operations requiring
|
||||
// widening.
|
||||
@ -283,6 +288,8 @@ public:
|
||||
return StructValues;
|
||||
}
|
||||
|
||||
void removeLatticeValueFor(Value *V) { ValueState.erase(V); }
|
||||
|
||||
const ValueLatticeElement &getLatticeValueFor(Value *V) const {
|
||||
assert(!V->getType()->isStructTy() &&
|
||||
"Should use getStructLatticeValueFor");
|
||||
@ -1607,7 +1614,9 @@ static bool tryToReplaceWithConstant(SCCPSolver &Solver, Value *V) {
|
||||
}
|
||||
|
||||
static bool simplifyInstsInBlock(SCCPSolver &Solver, BasicBlock &BB,
|
||||
Statistic &InstRemovedStat) {
|
||||
SmallPtrSetImpl<Value *> &InsertedValues,
|
||||
Statistic &InstRemovedStat,
|
||||
Statistic &InstReplacedStat) {
|
||||
bool MadeChanges = false;
|
||||
for (Instruction &Inst : make_early_inc_range(BB)) {
|
||||
if (Inst.getType()->isVoidTy())
|
||||
@ -1618,6 +1627,22 @@ static bool simplifyInstsInBlock(SCCPSolver &Solver, BasicBlock &BB,
|
||||
// Hey, we just changed something!
|
||||
MadeChanges = true;
|
||||
++InstRemovedStat;
|
||||
} else if (isa<SExtInst>(&Inst)) {
|
||||
Value *ExtOp = Inst.getOperand(0);
|
||||
if (isa<Constant>(ExtOp) || InsertedValues.count(ExtOp))
|
||||
continue;
|
||||
const ValueLatticeElement &IV = Solver.getLatticeValueFor(ExtOp);
|
||||
if (!IV.isConstantRange(/*UndefAllowed=*/false))
|
||||
continue;
|
||||
if (IV.getConstantRange().isAllNonNegative()) {
|
||||
auto *ZExt = new ZExtInst(ExtOp, Inst.getType(), "", &Inst);
|
||||
InsertedValues.insert(ZExt);
|
||||
Inst.replaceAllUsesWith(ZExt);
|
||||
Solver.removeLatticeValueFor(&Inst);
|
||||
Inst.eraseFromParent();
|
||||
InstReplacedStat++;
|
||||
MadeChanges = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return MadeChanges;
|
||||
@ -1653,6 +1678,7 @@ static bool runSCCP(Function &F, const DataLayout &DL,
|
||||
// delete their contents now. Note that we cannot actually delete the blocks,
|
||||
// as we cannot modify the CFG of the function.
|
||||
|
||||
SmallPtrSet<Value *, 32> InsertedValues;
|
||||
for (BasicBlock &BB : F) {
|
||||
if (!Solver.isBlockExecutable(&BB)) {
|
||||
LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB);
|
||||
@ -1664,7 +1690,8 @@ static bool runSCCP(Function &F, const DataLayout &DL,
|
||||
continue;
|
||||
}
|
||||
|
||||
MadeChanges |= simplifyInstsInBlock(Solver, BB, NumInstRemoved);
|
||||
MadeChanges |= simplifyInstsInBlock(Solver, BB, InsertedValues,
|
||||
NumInstRemoved, NumInstReplaced);
|
||||
}
|
||||
|
||||
return MadeChanges;
|
||||
@ -1893,6 +1920,7 @@ bool llvm::runIPSCCP(
|
||||
}
|
||||
}
|
||||
|
||||
SmallPtrSet<Value *, 32> InsertedValues;
|
||||
for (BasicBlock &BB : F) {
|
||||
if (!Solver.isBlockExecutable(&BB)) {
|
||||
LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB);
|
||||
@ -1905,7 +1933,8 @@ bool llvm::runIPSCCP(
|
||||
continue;
|
||||
}
|
||||
|
||||
MadeChanges |= simplifyInstsInBlock(Solver, BB, IPNumInstRemoved);
|
||||
MadeChanges |= simplifyInstsInBlock(Solver, BB, InsertedValues,
|
||||
IPNumInstRemoved, IPNumInstReplaced);
|
||||
}
|
||||
|
||||
DomTreeUpdater DTU = Solver.getDTU(F);
|
||||
|
@ -109,9 +109,9 @@ define i1 @caller.zext() {
|
||||
; x = [100, 301)
|
||||
define internal i1 @f.sext(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: define internal i1 @f.sext(i32 %x, i32 %y) {
|
||||
; CHECK-NEXT: %t.1 = sext i32 %x to i64
|
||||
; CHECK-NEXT: %c.2 = icmp sgt i64 %t.1, 299
|
||||
; CHECK-NEXT: %c.4 = icmp slt i64 %t.1, 101
|
||||
; CHECK-NEXT: [[T_1:%.*]] = zext i32 %x to i64
|
||||
; CHECK-NEXT: %c.2 = icmp sgt i64 [[T_1]], 299
|
||||
; CHECK-NEXT: %c.4 = icmp slt i64 [[T_1]], 101
|
||||
; CHECK-NEXT: %res.1 = add i1 false, %c.2
|
||||
; CHECK-NEXT: %res.2 = add i1 %res.1, false
|
||||
; CHECK-NEXT: %res.3 = add i1 %res.2, %c.4
|
||||
|
@ -105,8 +105,8 @@ exit:
|
||||
define i64 @test5(i32 %x) {
|
||||
; CHECK-LABEL: @test5(
|
||||
; CHECK-NEXT: [[P:%.*]] = and i32 [[X:%.*]], 15
|
||||
; CHECK-NEXT: [[EXT:%.*]] = sext i32 [[P]] to i64
|
||||
; CHECK-NEXT: ret i64 [[EXT]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[P]] to i64
|
||||
; CHECK-NEXT: ret i64 [[TMP1]]
|
||||
;
|
||||
%p = and i32 %x, 15
|
||||
%ext = sext i32 %p to i64
|
||||
@ -126,8 +126,8 @@ define i64 @test6(i32 %x) {
|
||||
define i64 @test7(i16 %x) {
|
||||
; CHECK-LABEL: @test7(
|
||||
; CHECK-NEXT: [[P:%.*]] = and i16 [[X:%.*]], 15
|
||||
; CHECK-NEXT: [[EXT_1:%.*]] = sext i16 [[P]] to i32
|
||||
; CHECK-NEXT: [[EXT_2:%.*]] = sext i32 [[EXT_1]] to i64
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[P]] to i32
|
||||
; CHECK-NEXT: [[EXT_2:%.*]] = sext i32 [[TMP1]] to i64
|
||||
; CHECK-NEXT: ret i64 [[EXT_2]]
|
||||
;
|
||||
%p = and i16 %x, 15
|
||||
|
@ -35,8 +35,8 @@ exit:
|
||||
define i64 @test2(i32 %x) {
|
||||
; CHECK-LABEL: @test2(
|
||||
; CHECK-NEXT: [[P:%.*]] = and i32 [[X:%.*]], 15
|
||||
; CHECK-NEXT: [[EXT:%.*]] = sext i32 [[P]] to i64
|
||||
; CHECK-NEXT: ret i64 [[EXT]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[P]] to i64
|
||||
; CHECK-NEXT: ret i64 [[TMP1]]
|
||||
;
|
||||
%p = and i32 %x, 15
|
||||
%ext = sext i32 %p to i64
|
||||
@ -54,8 +54,8 @@ define i64 @test3(i1 %c.1, i1 %c.2) {
|
||||
; CHECK-NEXT: br label [[EXIT]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[TRUE_1]] ], [ 1, [[TRUE_2]] ], [ 3, [[FALSE]] ]
|
||||
; CHECK-NEXT: [[EXT:%.*]] = sext i32 [[P]] to i64
|
||||
; CHECK-NEXT: ret i64 [[EXT]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[P]] to i64
|
||||
; CHECK-NEXT: ret i64 [[TMP1]]
|
||||
;
|
||||
br i1 %c.1, label %true.1, label %false
|
||||
|
||||
|
@ -451,7 +451,7 @@ define void @foo(i64* %arg) {
|
||||
; SCCP-NEXT: [[TMP7:%.*]] = sub i64 3, [[TMP6]]
|
||||
; SCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1
|
||||
; SCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
|
||||
; SCCP-NEXT: [[TMP10:%.*]] = sext i32 [[TMP9]] to i64
|
||||
; SCCP-NEXT: [[TMP10:%.*]] = zext i32 [[TMP9]] to i64
|
||||
; SCCP-NEXT: br label [[BB11:%.*]]
|
||||
; SCCP: bb11:
|
||||
; SCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP10]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ]
|
||||
@ -489,7 +489,7 @@ define void @foo(i64* %arg) {
|
||||
; IPSCCP-NEXT: [[TMP7:%.*]] = sub i64 3, [[TMP6]]
|
||||
; IPSCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1
|
||||
; IPSCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
|
||||
; IPSCCP-NEXT: [[TMP10:%.*]] = sext i32 [[TMP9]] to i64
|
||||
; IPSCCP-NEXT: [[TMP10:%.*]] = zext i32 [[TMP9]] to i64
|
||||
; IPSCCP-NEXT: br label [[BB11:%.*]]
|
||||
; IPSCCP: bb11:
|
||||
; IPSCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP10]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ]
|
||||
|
Loading…
Reference in New Issue
Block a user