NewGVN: Fix PR 34430 - we need to look through predicateinfo copies to detect self-cycles of phi nodes. We also need to not ignore certain types of arguments when testing whether the phi has a backedge or was originally constant.
llvm-svn: 312510
This commit is contained in:
parent
54a92fcc5d
commit
f9c9455d3f
|
@ -851,14 +851,22 @@ void NewGVN::deleteExpression(const Expression *E) const {
|
|||
ExpressionAllocator.Deallocate(E);
|
||||
}
|
||||
|
||||
// Return true if V is really PN, even accounting for predicateinfo copies.
|
||||
static bool isCopyOfSelf(const Value *V, const PHINode *PN) {
|
||||
if (V == PN)
|
||||
return V;
|
||||
// If V is a predicateinfo copy, get the thing it is a copy of.
|
||||
static Value *getCopyOf(const Value *V) {
|
||||
if (auto *II = dyn_cast<IntrinsicInst>(V))
|
||||
if (II->getIntrinsicID() == Intrinsic::ssa_copy && II->getOperand(0) == PN)
|
||||
return true;
|
||||
return false;
|
||||
if (II->getIntrinsicID() == Intrinsic::ssa_copy)
|
||||
return II->getOperand(0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Return true if V is really PN, even accounting for predicateinfo copies.
|
||||
static bool isCopyOfPHI(const Value *V, const PHINode *PN) {
|
||||
return V == PN || getCopyOf(V) == PN;
|
||||
}
|
||||
|
||||
static bool isCopyOfAPHI(const Value *V) {
|
||||
auto *CO = getCopyOf(V);
|
||||
return CO && isa<PHINode>(CO);
|
||||
}
|
||||
|
||||
PHIExpression *NewGVN::createPHIExpression(Instruction *I, bool &HasBackedge,
|
||||
|
@ -890,23 +898,21 @@ PHIExpression *NewGVN::createPHIExpression(Instruction *I, bool &HasBackedge,
|
|||
|
||||
// Filter out unreachable phi operands.
|
||||
auto Filtered = make_filter_range(PHIOperands, [&](const Use *U) {
|
||||
if (isCopyOfSelf(*U, PN))
|
||||
auto *BB = PN->getIncomingBlock(*U);
|
||||
if (isCopyOfPHI(*U, PN))
|
||||
return false;
|
||||
if (!ReachableEdges.count({PN->getIncomingBlock(*U), PHIBlock}))
|
||||
if (!ReachableEdges.count({BB, PHIBlock}))
|
||||
return false;
|
||||
// Things in TOPClass are equivalent to everything.
|
||||
if (ValueToClass.lookup(*U) == TOPClass)
|
||||
return false;
|
||||
OriginalOpsConstant = OriginalOpsConstant && isa<Constant>(*U);
|
||||
HasBackedge = HasBackedge || isBackedge(BB, PHIBlock);
|
||||
return lookupOperandLeader(*U) != PN;
|
||||
});
|
||||
std::transform(Filtered.begin(), Filtered.end(), op_inserter(E),
|
||||
[&](const Use *U) -> Value * {
|
||||
auto *BB = PN->getIncomingBlock(*U);
|
||||
HasBackedge = HasBackedge || isBackedge(BB, PHIBlock);
|
||||
OriginalOpsConstant =
|
||||
OriginalOpsConstant && isa<Constant>(*U);
|
||||
return lookupOperandLeader(*U);
|
||||
});
|
||||
std::transform(
|
||||
Filtered.begin(), Filtered.end(), op_inserter(E),
|
||||
[&](const Use *U) -> Value * { return lookupOperandLeader(*U); });
|
||||
return E;
|
||||
}
|
||||
|
||||
|
@ -990,7 +996,6 @@ const Expression *NewGVN::checkSimplificationResults(Expression *E,
|
|||
addAdditionalUsers(V, I);
|
||||
return createVariableOrConstant(CC->getLeader());
|
||||
}
|
||||
|
||||
if (CC->getDefiningExpr()) {
|
||||
// If we simplified to something else, we need to communicate
|
||||
// that we're users of the value we simplified to.
|
||||
|
@ -1611,8 +1616,9 @@ bool NewGVN::isCycleFree(const Instruction *I) const {
|
|||
if (SCC.size() == 1)
|
||||
InstCycleState.insert({I, ICS_CycleFree});
|
||||
else {
|
||||
bool AllPhis =
|
||||
llvm::all_of(SCC, [](const Value *V) { return isa<PHINode>(V); });
|
||||
bool AllPhis = llvm::all_of(SCC, [](const Value *V) {
|
||||
return isa<PHINode>(V) || isCopyOfAPHI(V);
|
||||
});
|
||||
ICS = AllPhis ? ICS_CycleFree : ICS_Cycle;
|
||||
for (auto *Member : SCC)
|
||||
if (auto *MemberPhi = dyn_cast<PHINode>(Member))
|
||||
|
@ -1632,9 +1638,9 @@ const Expression *NewGVN::performSymbolicPHIEvaluation(Instruction *I) const {
|
|||
// This is really shorthand for "this phi cannot cycle due to forward
|
||||
// change in value of the phi is guaranteed not to later change the value of
|
||||
// the phi. IE it can't be v = phi(undef, v+1)
|
||||
bool AllConstant = true;
|
||||
auto *E =
|
||||
cast<PHIExpression>(createPHIExpression(I, HasBackedge, AllConstant));
|
||||
bool OriginalOpsConstant = true;
|
||||
auto *E = cast<PHIExpression>(
|
||||
createPHIExpression(I, HasBackedge, OriginalOpsConstant));
|
||||
// We match the semantics of SimplifyPhiNode from InstructionSimplify here.
|
||||
// See if all arguments are the same.
|
||||
// We track if any were undef because they need special handling.
|
||||
|
@ -1660,14 +1666,10 @@ const Expression *NewGVN::performSymbolicPHIEvaluation(Instruction *I) const {
|
|||
deleteExpression(E);
|
||||
return createDeadExpression();
|
||||
}
|
||||
unsigned NumOps = 0;
|
||||
Value *AllSameValue = *(Filtered.begin());
|
||||
++Filtered.begin();
|
||||
// Can't use std::equal here, sadly, because filter.begin moves.
|
||||
if (llvm::all_of(Filtered, [&](Value *Arg) {
|
||||
++NumOps;
|
||||
return Arg == AllSameValue;
|
||||
})) {
|
||||
if (llvm::all_of(Filtered, [&](Value *Arg) { return Arg == AllSameValue; })) {
|
||||
// In LLVM's non-standard representation of phi nodes, it's possible to have
|
||||
// phi nodes with cycles (IE dependent on other phis that are .... dependent
|
||||
// on the original phi node), especially in weird CFG's where some arguments
|
||||
|
@ -1682,9 +1684,8 @@ const Expression *NewGVN::performSymbolicPHIEvaluation(Instruction *I) const {
|
|||
// multivalued phi, and we need to know if it's cycle free in order to
|
||||
// evaluate whether we can ignore the undef. The other parts of this are
|
||||
// just shortcuts. If there is no backedge, or all operands are
|
||||
// constants, or all operands are ignored but the undef, it also must be
|
||||
// cycle free.
|
||||
if (!AllConstant && HasBackedge && NumOps > 0 &&
|
||||
// constants, it also must be cycle free.
|
||||
if (HasBackedge && !OriginalOpsConstant &&
|
||||
!isa<UndefValue>(AllSameValue) && !isCycleFree(I))
|
||||
return E;
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; ModuleID = 'bugpoint-reduced-simplified.bc'
|
||||
; RUN: opt < %s -newgvn -S | FileCheck %s
|
||||
source_filename = "bugpoint-output-e4c7d0f.bc"
|
||||
|
||||
; Make sure we still properly resolve phi cycles when they involve predicateinfo copies of phis.
|
||||
define void @hoge() local_unnamed_addr #0 {
|
||||
; CHECK-LABEL: @hoge(
|
||||
; CHECK-NEXT: bb:
|
||||
; CHECK-NEXT: br i1 undef, label [[BB6:%.*]], label [[BB1:%.*]]
|
||||
; CHECK: bb1:
|
||||
; CHECK-NEXT: br label [[BB6]]
|
||||
; CHECK: bb2:
|
||||
; CHECK-NEXT: br i1 true, label [[BB3:%.*]], label [[BB6]]
|
||||
; CHECK: bb3:
|
||||
; CHECK-NEXT: br label [[BB4:%.*]]
|
||||
; CHECK: bb4:
|
||||
; CHECK-NEXT: br i1 undef, label [[BB2:%.*]], label [[BB6]]
|
||||
; CHECK: bb6:
|
||||
; CHECK-NEXT: br label [[BB4]]
|
||||
;
|
||||
bb:
|
||||
br i1 undef, label %bb6, label %bb1
|
||||
|
||||
bb1: ; preds = %bb
|
||||
br label %bb6
|
||||
|
||||
bb2: ; preds = %bb4
|
||||
%tmp = icmp slt i8 %tmp5, 7
|
||||
br i1 %tmp, label %bb3, label %bb6
|
||||
|
||||
bb3: ; preds = %bb2
|
||||
br label %bb4
|
||||
|
||||
bb4: ; preds = %bb6, %bb3
|
||||
%tmp5 = phi i8 [ %tmp5, %bb3 ], [ %tmp7, %bb6 ]
|
||||
br i1 undef, label %bb2, label %bb6
|
||||
|
||||
bb6: ; preds = %bb4, %bb2, %bb1, %bb
|
||||
%tmp7 = phi i8 [ %tmp5, %bb4 ], [ %tmp5, %bb2 ], [ 5, %bb1 ], [ undef, %bb ]
|
||||
br label %bb4
|
||||
}
|
||||
|
||||
attributes #0 = { norecurse noreturn nounwind ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||
|
||||
!llvm.ident = !{!0}
|
||||
|
||||
!0 = !{!"clang version 6.0.0 (http://llvm.org/git/clang.git e649d902285b23af8ba58cb92a739f3bad2723df) (/Users/dannyb/sources/llvm-clean 0abfd30028cbb294ff2c2dd5e2df4ec3fdb6c591)"}
|
Loading…
Reference in New Issue