GVN-hoist: compute MSSA once per function (PR28670)

With this patch we compute the MemorySSA once and update it in the code generator.

Differential Revision: https://reviews.llvm.org/D22966

llvm-svn: 277649
This commit is contained in:
Sebastian Pop 2016-08-03 20:54:33 +00:00
parent ac5bf59b6e
commit 5d3822fc12
2 changed files with 118 additions and 12 deletions

View File

@ -193,14 +193,11 @@ public:
VN.setAliasAnalysis(AA);
VN.setMemDep(MD);
bool Res = false;
MemorySSA M(F, AA, DT);
MSSA = &M;
// FIXME: use lazy evaluation of VN to avoid the fix-point computation.
while (1) {
// FIXME: only compute MemorySSA once. We need to update the analysis in
// the same time as transforming the code.
MemorySSA M(F, AA, DT);
MSSA = &M;
// Perform DFS Numbering of instructions.
unsigned I = 0;
for (const BasicBlock *BB : depth_first(&F.getEntryBlock()))
@ -208,15 +205,15 @@ public:
DFSNumber.insert({&Inst, ++I});
auto HoistStat = hoistExpressions(F);
if (HoistStat.first + HoistStat.second == 0) {
if (HoistStat.first + HoistStat.second == 0)
return Res;
}
if (HoistStat.second > 0) {
if (HoistStat.second > 0)
// To address a limitation of the current GVN, we need to rerun the
// hoisting after we hoisted loads in order to be able to hoist all
// scalars dependent on the hoisted loads. Same for stores.
// hoisting after we hoisted loads or stores in order to be able to
// hoist all scalars dependent on the hoisted ld/st.
VN.clear();
}
Res = true;
// DFS numbers change when instructions are hoisted: clear and recompute.
@ -310,7 +307,8 @@ private:
for (User *U : Def->users())
if (auto *MU = dyn_cast<MemoryUse>(U)) {
BasicBlock *UBB = MU->getBlock();
// FIXME: MU->getBlock() does not get updated when we move the instruction.
BasicBlock *UBB = MU->getMemoryInst()->getParent();
// Only analyze uses in BB.
if (BB != UBB)
continue;
@ -742,9 +740,23 @@ private:
!makeGepOperandsAvailable(Repl, HoistPt, InstructionsToHoist))
continue;
// Move the instruction at the end of HoistPt.
Repl->moveBefore(HoistPt->getTerminator());
}
MemoryAccess *NewMemAcc = nullptr;
if (MemoryAccess *MA = MSSA->getMemoryAccess(Repl)) {
if (MemoryUseOrDef *OldMemAcc = dyn_cast<MemoryUseOrDef>(MA)) {
// The definition of this ld/st will not change: ld/st hoisting is
// legal when the ld/st is not moved past its current definition.
MemoryAccess *Def = OldMemAcc->getDefiningAccess();
NewMemAcc = MSSA->createMemoryAccessInBB(Repl, Def, HoistPt,
MemorySSA::End);
OldMemAcc->replaceAllUsesWith(NewMemAcc);
MSSA->removeMemoryAccess(OldMemAcc);
}
}
if (isa<LoadInst>(Repl))
++NL;
else if (isa<StoreInst>(Repl))
@ -775,11 +787,36 @@ private:
} else if (isa<CallInst>(Repl)) {
++NumCallsRemoved;
}
if (NewMemAcc) {
// Update the uses of the old MSSA access with NewMemAcc.
MemoryAccess *OldMA = MSSA->getMemoryAccess(I);
OldMA->replaceAllUsesWith(NewMemAcc);
MSSA->removeMemoryAccess(OldMA);
}
Repl->intersectOptionalDataWith(I);
combineKnownMetadata(Repl, I);
I->replaceAllUsesWith(Repl);
I->eraseFromParent();
}
// Remove MemorySSA phi nodes with the same arguments.
if (NewMemAcc) {
SmallPtrSet<MemoryPhi *, 4> UsePhis;
for (User *U : NewMemAcc->users())
if (MemoryPhi *Phi = dyn_cast<MemoryPhi>(U))
UsePhis.insert(Phi);
for (auto *Phi : UsePhis) {
auto In = Phi->incoming_values();
if (std::all_of(In.begin(), In.end(),
[&](Use &U){return U == NewMemAcc;})) {
Phi->replaceAllUsesWith(NewMemAcc);
MSSA->removeMemoryAccess(Phi);
}
}
}
}
NumHoisted += NL + NS + NC + NI;

View File

@ -0,0 +1,69 @@
; RUN: opt -S -gvn-hoist < %s | FileCheck %s
; Check that store hoisting works: there should be only one store left.
; CHECK-LABEL: @getopt
; CHECK: store i32
; CHECK-NOT: store i32
@optind = external global i32, align 4
define void @getopt() {
bb:
br label %bb1
bb1: ; preds = %bb
br i1 undef, label %bb2, label %bb3
bb2: ; preds = %bb1
br label %bb13
bb3: ; preds = %bb1
br i1 undef, label %bb4, label %bb9
bb4: ; preds = %bb3
%tmp = load i32, i32* @optind, align 4
br i1 undef, label %bb5, label %bb7
bb5: ; preds = %bb4
%tmp6 = add nsw i32 %tmp, 1
store i32 %tmp6, i32* @optind, align 4
br label %bb12
bb7: ; preds = %bb4
%tmp8 = add nsw i32 %tmp, 1
store i32 %tmp8, i32* @optind, align 4
br label %bb13
bb9: ; preds = %bb3
%tmp10 = load i32, i32* @optind, align 4
%tmp11 = add nsw i32 %tmp10, 1
store i32 %tmp11, i32* @optind, align 4
br label %bb12
bb12: ; preds = %bb9, %bb5
br label %bb13
bb13: ; preds = %bb12, %bb7, %bb2
ret void
}
@GlobalVar = internal global float 1.000000e+00
; Check that we hoist stores and remove the MSSA phi node.
; CHECK-LABEL: @hoistStoresUpdateMSSA
; CHECK: store float
; CHECK-NOT: store float
define float @hoistStoresUpdateMSSA(float %d) {
entry:
store float 0.000000e+00, float* @GlobalVar
%cmp = fcmp oge float %d, 0.000000e+00
br i1 %cmp, label %if.then, label %if.end
if.then:
store float 0.000000e+00, float* @GlobalVar
br label %if.end
if.end:
%tmp = load float, float* @GlobalVar, align 4
ret float %tmp
}