mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[JumpThreading] Perform phi-translation in SimplifyPartiallyRedundantLoad.
Summary: In case we are loading on a phi-load in SimplifyPartiallyRedundantLoad. Try to phi translate it into incoming values in the predecessors before we search for available loads. This needs https://reviews.llvm.org/D30524 Reviewers: davide, sanjoy, efriedma, dberlin, rengolin Reviewed By: dberlin Subscribers: junbuml, llvm-commits Differential Revision: https://reviews.llvm.org/D30543 llvm-svn: 298217
This commit is contained in:
parent
7ed0553795
commit
92773d49ef
@ -931,6 +931,14 @@ bool JumpThreadingPass::ProcessImpliedCondition(BasicBlock *BB) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Return true if Op is an instruction defined in the given block.
|
||||
static bool isOpDefinedInBlock(Value *Op, BasicBlock *BB) {
|
||||
if (Instruction *OpInst = dyn_cast<Instruction>(Op))
|
||||
if (OpInst->getParent() == BB)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// SimplifyPartiallyRedundantLoad - If LI is an obviously partially redundant
|
||||
/// load instruction, eliminate it by replacing it with a PHI node. This is an
|
||||
/// important optimization that encourages jump threading, and needs to be run
|
||||
@ -953,11 +961,10 @@ bool JumpThreadingPass::SimplifyPartiallyRedundantLoad(LoadInst *LI) {
|
||||
|
||||
Value *LoadedPtr = LI->getOperand(0);
|
||||
|
||||
// If the loaded operand is defined in the LoadBB, it can't be available.
|
||||
// TODO: Could do simple PHI translation, that would be fun :)
|
||||
if (Instruction *PtrOp = dyn_cast<Instruction>(LoadedPtr))
|
||||
if (PtrOp->getParent() == LoadBB)
|
||||
return false;
|
||||
// If the loaded operand is defined in the LoadBB and its not a phi,
|
||||
// it can't be available in predecessors.
|
||||
if (isOpDefinedInBlock(LoadedPtr, LoadBB) && !isa<PHINode>(LoadedPtr))
|
||||
return false;
|
||||
|
||||
// Scan a few instructions up from the load, to see if it is obviously live at
|
||||
// the entry to its block.
|
||||
@ -1008,23 +1015,31 @@ bool JumpThreadingPass::SimplifyPartiallyRedundantLoad(LoadInst *LI) {
|
||||
if (!PredsScanned.insert(PredBB).second)
|
||||
continue;
|
||||
|
||||
// Scan the predecessor to see if the value is available in the pred.
|
||||
BBIt = PredBB->end();
|
||||
unsigned NumScanedInst = 0;
|
||||
Value *PredAvailable = FindAvailableLoadedValue(
|
||||
LI, PredBB, BBIt, DefMaxInstsToScan, AA, &IsLoadCSE, &NumScanedInst);
|
||||
Value *PredAvailable = nullptr;
|
||||
// NOTE: We don't CSE load that is volatile or anything stronger than
|
||||
// unordered, that should have been checked when we entered the function.
|
||||
assert(LI->isUnordered() && "Attempting to CSE volatile or atomic loads");
|
||||
// If this is a load on a phi pointer, phi-translate it and search
|
||||
// for available load/store to the pointer in predecessors.
|
||||
Value *Ptr = LoadedPtr->DoPHITranslation(LoadBB, PredBB);
|
||||
PredAvailable = FindAvailablePtrLoadStore(
|
||||
Ptr, LI->getType(), LI->isAtomic(), PredBB, BBIt, DefMaxInstsToScan,
|
||||
nullptr, &IsLoadCSE, &NumScanedInst);
|
||||
|
||||
// If PredBB has a single predecessor, continue scanning through the single
|
||||
// predecessor.
|
||||
// If PredBB has a single predecessor, continue scanning through the
|
||||
// single precessor.
|
||||
BasicBlock *SinglePredBB = PredBB;
|
||||
while (!PredAvailable && SinglePredBB && BBIt == SinglePredBB->begin() &&
|
||||
NumScanedInst < DefMaxInstsToScan) {
|
||||
SinglePredBB = SinglePredBB->getSinglePredecessor();
|
||||
if (SinglePredBB) {
|
||||
BBIt = SinglePredBB->end();
|
||||
PredAvailable = FindAvailableLoadedValue(
|
||||
LI, SinglePredBB, BBIt, (DefMaxInstsToScan - NumScanedInst), AA,
|
||||
&IsLoadCSE, &NumScanedInst);
|
||||
PredAvailable = FindAvailablePtrLoadStore(
|
||||
Ptr, LI->getType(), LI->isAtomic(), SinglePredBB, BBIt,
|
||||
(DefMaxInstsToScan - NumScanedInst), nullptr, &IsLoadCSE,
|
||||
&NumScanedInst);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1087,10 +1102,10 @@ bool JumpThreadingPass::SimplifyPartiallyRedundantLoad(LoadInst *LI) {
|
||||
if (UnavailablePred) {
|
||||
assert(UnavailablePred->getTerminator()->getNumSuccessors() == 1 &&
|
||||
"Can't handle critical edge here!");
|
||||
LoadInst *NewVal =
|
||||
new LoadInst(LoadedPtr, LI->getName() + ".pr", false,
|
||||
LI->getAlignment(), LI->getOrdering(), LI->getSynchScope(),
|
||||
UnavailablePred->getTerminator());
|
||||
LoadInst *NewVal = new LoadInst(
|
||||
LoadedPtr->DoPHITranslation(LoadBB, UnavailablePred),
|
||||
LI->getName() + ".pr", false, LI->getAlignment(), LI->getOrdering(),
|
||||
LI->getSynchScope(), UnavailablePred->getTerminator());
|
||||
NewVal->setDebugLoc(LI->getDebugLoc());
|
||||
if (AATags)
|
||||
NewVal->setAAMetadata(AATags);
|
||||
|
@ -490,6 +490,41 @@ declare void @fn2(i64)
|
||||
declare void @fn3(i64)
|
||||
|
||||
|
||||
; Make sure we phi-translate and make the partially redundant load in
|
||||
; merge fully redudant and then we can jump-thread the block with the
|
||||
; store.
|
||||
;
|
||||
; CHECK-LABEL: define i32 @phi_translate_partial_redundant_loads(i32, i32*, i32*
|
||||
; CHECK: merge.thread:
|
||||
; CHECK: store
|
||||
; CHECK: br label %left_x
|
||||
;
|
||||
; CHECK: left_x:
|
||||
; CHECK-NEXT: ret i32 20
|
||||
define i32 @phi_translate_partial_redundant_loads(i32, i32*, i32*) {
|
||||
%cmp0 = icmp ne i32 %0, 0
|
||||
br i1 %cmp0, label %left, label %right
|
||||
|
||||
left:
|
||||
store i32 1, i32* %1, align 4
|
||||
br label %merge
|
||||
|
||||
right:
|
||||
br label %merge
|
||||
|
||||
merge:
|
||||
%phiptr = phi i32* [ %1, %left ], [ %2, %right ]
|
||||
%newload = load i32, i32* %phiptr, align 4
|
||||
%cmp1 = icmp slt i32 %newload, 5
|
||||
br i1 %cmp1, label %left_x, label %right_x
|
||||
|
||||
left_x:
|
||||
ret i32 20
|
||||
|
||||
right_x:
|
||||
ret i32 10
|
||||
}
|
||||
|
||||
!0 = !{!3, !3, i64 0}
|
||||
!1 = !{!"omnipotent char", !2}
|
||||
!2 = !{!"Simple C/C++ TBAA"}
|
||||
|
Loading…
x
Reference in New Issue
Block a user