mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[gvn] Precisely propagate equalities to phi operands
The code used for propagating equalities (e.g. assume facts) was conservative in two ways - one of which this patch fixes. Specifically, it shifts the code reasoning about whether a use is dominated by the end of the assume block to consider phi uses to exist on the predecessor edge. This matches the dominator tree handling for dominates(Edge, Use), and simply extends it to dominates(BB, Use). Note that the decision to use the end of the block is itself a conservative choice. The more precise option would be to use the later of the assume and the value, and replace all uses after that. GVN handles that case separately (with the replace operand mechanism) because it used to be expensive to ask dominator questions within blocks. With the new instruction ordering support, we should probably rewrite this code at some point to simplify. Differential Revision: https://reviews.llvm.org/D98082
This commit is contained in:
parent
bf6c4851ee
commit
fec6c4d338
@ -165,6 +165,9 @@ class DominatorTree : public DominatorTreeBase<BasicBlock, false> {
|
|||||||
// Ensure base-class overloads are visible.
|
// Ensure base-class overloads are visible.
|
||||||
using Base::dominates;
|
using Base::dominates;
|
||||||
|
|
||||||
|
/// Return true if the (end of the) basic block BB dominates the use U.
|
||||||
|
bool dominates(const BasicBlock *BB, const Use &U) const;
|
||||||
|
|
||||||
/// Return true if value Def dominates use U, in the sense that Def is
|
/// Return true if value Def dominates use U, in the sense that Def is
|
||||||
/// available at U, and could be substituted as the used value without
|
/// available at U, and could be substituted as the used value without
|
||||||
/// violating the SSA dominance requirement.
|
/// violating the SSA dominance requirement.
|
||||||
|
@ -112,6 +112,16 @@ bool DominatorTree::invalidate(Function &F, const PreservedAnalyses &PA,
|
|||||||
PAC.preservedSet<CFGAnalyses>());
|
PAC.preservedSet<CFGAnalyses>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DominatorTree::dominates(const BasicBlock *BB, const Use &U) const {
|
||||||
|
Instruction *UserInst = cast<Instruction>(U.getUser());
|
||||||
|
if (auto *PN = dyn_cast<PHINode>(UserInst))
|
||||||
|
// A phi use using a value from a block is dominated by the end of that
|
||||||
|
// block. Note that the phi's parent block may not be.
|
||||||
|
return dominates(BB, PN->getIncomingBlock(U));
|
||||||
|
else
|
||||||
|
return properlyDominates(BB, UserInst->getParent());
|
||||||
|
}
|
||||||
|
|
||||||
// dominates - Return true if Def dominates a use in User. This performs
|
// dominates - Return true if Def dominates a use in User. This performs
|
||||||
// the special checks necessary if Def and User are in the same basic block.
|
// the special checks necessary if Def and User are in the same basic block.
|
||||||
// Note that Def doesn't dominate a use in Def itself!
|
// Note that Def doesn't dominate a use in Def itself!
|
||||||
|
@ -2683,11 +2683,10 @@ unsigned llvm::replaceDominatedUsesWith(Value *From, Value *To,
|
|||||||
unsigned llvm::replaceDominatedUsesWith(Value *From, Value *To,
|
unsigned llvm::replaceDominatedUsesWith(Value *From, Value *To,
|
||||||
DominatorTree &DT,
|
DominatorTree &DT,
|
||||||
const BasicBlock *BB) {
|
const BasicBlock *BB) {
|
||||||
auto ProperlyDominates = [&DT](const BasicBlock *BB, const Use &U) {
|
auto Dominates = [&DT](const BasicBlock *BB, const Use &U) {
|
||||||
auto *I = cast<Instruction>(U.getUser())->getParent();
|
return DT.dominates(BB, U);
|
||||||
return DT.properlyDominates(BB, I);
|
|
||||||
};
|
};
|
||||||
return ::replaceDominatedUsesWith(From, To, BB, ProperlyDominates);
|
return ::replaceDominatedUsesWith(From, To, BB, Dominates);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool llvm::callsGCLeafFunction(const CallBase *Call,
|
bool llvm::callsGCLeafFunction(const CallBase *Call,
|
||||||
|
@ -37,10 +37,8 @@ define i64 @test2(i1 %c, i64 %a, i64 %b) {
|
|||||||
; CHECK: untaken:
|
; CHECK: untaken:
|
||||||
; CHECK-NEXT: br label [[MERGE]]
|
; CHECK-NEXT: br label [[MERGE]]
|
||||||
; CHECK: merge:
|
; CHECK: merge:
|
||||||
; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ [[A]], [[TAKEN]] ], [ [[B:%.*]], [[UNTAKEN]] ]
|
; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ 0, [[TAKEN]] ], [ [[B:%.*]], [[UNTAKEN]] ]
|
||||||
; CHECK-NEXT: [[PHI2:%.*]] = phi i64 [ 0, [[TAKEN]] ], [ [[B]], [[UNTAKEN]] ]
|
; CHECK-NEXT: ret i64 0
|
||||||
; CHECK-NEXT: [[RET:%.*]] = sub i64 [[PHI1]], [[PHI2]]
|
|
||||||
; CHECK-NEXT: ret i64 [[RET]]
|
|
||||||
;
|
;
|
||||||
br i1 %c, label %taken, label %untaken
|
br i1 %c, label %taken, label %untaken
|
||||||
taken:
|
taken:
|
||||||
@ -134,8 +132,7 @@ define i64 @test5(i1 %c, i64 %a) {
|
|||||||
; CHECK: untaken:
|
; CHECK: untaken:
|
||||||
; CHECK-NEXT: br label [[MERGE]]
|
; CHECK-NEXT: br label [[MERGE]]
|
||||||
; CHECK: merge:
|
; CHECK: merge:
|
||||||
; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[A]], [[TAKEN]] ], [ 0, [[UNTAKEN]] ]
|
; CHECK-NEXT: ret i64 0
|
||||||
; CHECK-NEXT: ret i64 [[PHI]]
|
|
||||||
;
|
;
|
||||||
br i1 %c, label %taken, label %untaken
|
br i1 %c, label %taken, label %untaken
|
||||||
taken:
|
taken:
|
||||||
@ -159,8 +156,7 @@ define i64 @test6(i1 %c, i64 %a) {
|
|||||||
; CHECK: untaken:
|
; CHECK: untaken:
|
||||||
; CHECK-NEXT: br label [[MERGE]]
|
; CHECK-NEXT: br label [[MERGE]]
|
||||||
; CHECK: merge:
|
; CHECK: merge:
|
||||||
; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[A]], [[TAKEN]] ], [ 0, [[UNTAKEN]] ]
|
; CHECK-NEXT: ret i64 0
|
||||||
; CHECK-NEXT: ret i64 [[PHI]]
|
|
||||||
;
|
;
|
||||||
br i1 %c, label %taken, label %untaken
|
br i1 %c, label %taken, label %untaken
|
||||||
taken:
|
taken:
|
||||||
|
Loading…
Reference in New Issue
Block a user