1
0
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:
Florian Hahn 2020-06-19 09:27:52 +01:00
parent ff3ee09ec7
commit 932ea47fda
5 changed files with 45 additions and 16 deletions

View File

@ -67,10 +67,15 @@ using namespace llvm;
STATISTIC(NumInstRemoved, "Number of instructions removed"); STATISTIC(NumInstRemoved, "Number of instructions removed");
STATISTIC(NumDeadBlocks , "Number of basic blocks unreachable"); 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(IPNumInstRemoved, "Number of instructions removed by IPSCCP");
STATISTIC(IPNumArgsElimed ,"Number of arguments constant propagated by IPSCCP"); STATISTIC(IPNumArgsElimed ,"Number of arguments constant propagated by IPSCCP");
STATISTIC(IPNumGlobalConst, "Number of globals found to be constant 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 // The maximum number of range extensions allowed for operations requiring
// widening. // widening.
@ -283,6 +288,8 @@ public:
return StructValues; return StructValues;
} }
void removeLatticeValueFor(Value *V) { ValueState.erase(V); }
const ValueLatticeElement &getLatticeValueFor(Value *V) const { const ValueLatticeElement &getLatticeValueFor(Value *V) const {
assert(!V->getType()->isStructTy() && assert(!V->getType()->isStructTy() &&
"Should use getStructLatticeValueFor"); "Should use getStructLatticeValueFor");
@ -1607,7 +1614,9 @@ static bool tryToReplaceWithConstant(SCCPSolver &Solver, Value *V) {
} }
static bool simplifyInstsInBlock(SCCPSolver &Solver, BasicBlock &BB, static bool simplifyInstsInBlock(SCCPSolver &Solver, BasicBlock &BB,
Statistic &InstRemovedStat) { SmallPtrSetImpl<Value *> &InsertedValues,
Statistic &InstRemovedStat,
Statistic &InstReplacedStat) {
bool MadeChanges = false; bool MadeChanges = false;
for (Instruction &Inst : make_early_inc_range(BB)) { for (Instruction &Inst : make_early_inc_range(BB)) {
if (Inst.getType()->isVoidTy()) if (Inst.getType()->isVoidTy())
@ -1618,6 +1627,22 @@ static bool simplifyInstsInBlock(SCCPSolver &Solver, BasicBlock &BB,
// Hey, we just changed something! // Hey, we just changed something!
MadeChanges = true; MadeChanges = true;
++InstRemovedStat; ++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; 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, // delete their contents now. Note that we cannot actually delete the blocks,
// as we cannot modify the CFG of the function. // as we cannot modify the CFG of the function.
SmallPtrSet<Value *, 32> InsertedValues;
for (BasicBlock &BB : F) { for (BasicBlock &BB : F) {
if (!Solver.isBlockExecutable(&BB)) { if (!Solver.isBlockExecutable(&BB)) {
LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB); LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB);
@ -1664,7 +1690,8 @@ static bool runSCCP(Function &F, const DataLayout &DL,
continue; continue;
} }
MadeChanges |= simplifyInstsInBlock(Solver, BB, NumInstRemoved); MadeChanges |= simplifyInstsInBlock(Solver, BB, InsertedValues,
NumInstRemoved, NumInstReplaced);
} }
return MadeChanges; return MadeChanges;
@ -1893,6 +1920,7 @@ bool llvm::runIPSCCP(
} }
} }
SmallPtrSet<Value *, 32> InsertedValues;
for (BasicBlock &BB : F) { for (BasicBlock &BB : F) {
if (!Solver.isBlockExecutable(&BB)) { if (!Solver.isBlockExecutable(&BB)) {
LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB); LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB);
@ -1905,7 +1933,8 @@ bool llvm::runIPSCCP(
continue; continue;
} }
MadeChanges |= simplifyInstsInBlock(Solver, BB, IPNumInstRemoved); MadeChanges |= simplifyInstsInBlock(Solver, BB, InsertedValues,
IPNumInstRemoved, IPNumInstReplaced);
} }
DomTreeUpdater DTU = Solver.getDTU(F); DomTreeUpdater DTU = Solver.getDTU(F);

View File

@ -109,9 +109,9 @@ define i1 @caller.zext() {
; x = [100, 301) ; x = [100, 301)
define internal i1 @f.sext(i32 %x, i32 %y) { define internal i1 @f.sext(i32 %x, i32 %y) {
; CHECK-LABEL: 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: [[T_1:%.*]] = zext i32 %x to i64
; CHECK-NEXT: %c.2 = icmp sgt i64 %t.1, 299 ; CHECK-NEXT: %c.2 = icmp sgt i64 [[T_1]], 299
; CHECK-NEXT: %c.4 = icmp slt i64 %t.1, 101 ; CHECK-NEXT: %c.4 = icmp slt i64 [[T_1]], 101
; CHECK-NEXT: %res.1 = add i1 false, %c.2 ; CHECK-NEXT: %res.1 = add i1 false, %c.2
; CHECK-NEXT: %res.2 = add i1 %res.1, false ; CHECK-NEXT: %res.2 = add i1 %res.1, false
; CHECK-NEXT: %res.3 = add i1 %res.2, %c.4 ; CHECK-NEXT: %res.3 = add i1 %res.2, %c.4

View File

@ -105,8 +105,8 @@ exit:
define i64 @test5(i32 %x) { define i64 @test5(i32 %x) {
; CHECK-LABEL: @test5( ; CHECK-LABEL: @test5(
; CHECK-NEXT: [[P:%.*]] = and i32 [[X:%.*]], 15 ; CHECK-NEXT: [[P:%.*]] = and i32 [[X:%.*]], 15
; CHECK-NEXT: [[EXT:%.*]] = sext i32 [[P]] to i64 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[P]] to i64
; CHECK-NEXT: ret i64 [[EXT]] ; CHECK-NEXT: ret i64 [[TMP1]]
; ;
%p = and i32 %x, 15 %p = and i32 %x, 15
%ext = sext i32 %p to i64 %ext = sext i32 %p to i64
@ -126,8 +126,8 @@ define i64 @test6(i32 %x) {
define i64 @test7(i16 %x) { define i64 @test7(i16 %x) {
; CHECK-LABEL: @test7( ; CHECK-LABEL: @test7(
; CHECK-NEXT: [[P:%.*]] = and i16 [[X:%.*]], 15 ; CHECK-NEXT: [[P:%.*]] = and i16 [[X:%.*]], 15
; CHECK-NEXT: [[EXT_1:%.*]] = sext i16 [[P]] to i32 ; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[P]] to i32
; CHECK-NEXT: [[EXT_2:%.*]] = sext i32 [[EXT_1]] to i64 ; CHECK-NEXT: [[EXT_2:%.*]] = sext i32 [[TMP1]] to i64
; CHECK-NEXT: ret i64 [[EXT_2]] ; CHECK-NEXT: ret i64 [[EXT_2]]
; ;
%p = and i16 %x, 15 %p = and i16 %x, 15

View File

@ -35,8 +35,8 @@ exit:
define i64 @test2(i32 %x) { define i64 @test2(i32 %x) {
; CHECK-LABEL: @test2( ; CHECK-LABEL: @test2(
; CHECK-NEXT: [[P:%.*]] = and i32 [[X:%.*]], 15 ; CHECK-NEXT: [[P:%.*]] = and i32 [[X:%.*]], 15
; CHECK-NEXT: [[EXT:%.*]] = sext i32 [[P]] to i64 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[P]] to i64
; CHECK-NEXT: ret i64 [[EXT]] ; CHECK-NEXT: ret i64 [[TMP1]]
; ;
%p = and i32 %x, 15 %p = and i32 %x, 15
%ext = sext i32 %p to i64 %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-NEXT: br label [[EXIT]]
; CHECK: exit: ; CHECK: exit:
; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[TRUE_1]] ], [ 1, [[TRUE_2]] ], [ 3, [[FALSE]] ] ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[TRUE_1]] ], [ 1, [[TRUE_2]] ], [ 3, [[FALSE]] ]
; CHECK-NEXT: [[EXT:%.*]] = sext i32 [[P]] to i64 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[P]] to i64
; CHECK-NEXT: ret i64 [[EXT]] ; CHECK-NEXT: ret i64 [[TMP1]]
; ;
br i1 %c.1, label %true.1, label %false br i1 %c.1, label %true.1, label %false

View File

@ -451,7 +451,7 @@ define void @foo(i64* %arg) {
; SCCP-NEXT: [[TMP7:%.*]] = sub i64 3, [[TMP6]] ; SCCP-NEXT: [[TMP7:%.*]] = sub i64 3, [[TMP6]]
; SCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1 ; SCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1
; SCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32 ; 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-NEXT: br label [[BB11:%.*]]
; SCCP: bb11: ; SCCP: bb11:
; SCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP10]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ] ; 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: [[TMP7:%.*]] = sub i64 3, [[TMP6]]
; IPSCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1 ; IPSCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1
; IPSCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32 ; 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-NEXT: br label [[BB11:%.*]]
; IPSCCP: bb11: ; IPSCCP: bb11:
; IPSCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP10]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ] ; IPSCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP10]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ]