[RDF] Fix liveness propagation through shadows

Each shadow only represents data flow that is restricted to its reaching
def. Propagating more than that could lead to spurious register liveness,
resulting in extra (incorrectly) block live-ins.

llvm-svn: 283143
This commit is contained in:
Krzysztof Parzyszek 2016-10-03 20:17:20 +00:00
parent a827ed8891
commit c8b6ecabd8
2 changed files with 80 additions and 29 deletions

View File

@ -530,7 +530,7 @@ void Liveness::computePhiInfo() {
RegisterSet UpReached;
for (const std::pair<RegisterRef,NodeSet> &T : RUM) {
RegisterRef R = T.first;
if (!isRestrictedToRef(PA, UA, R))
if (UA.Addr->getFlags() & NodeAttrs::Shadow)
R = getRestrictedRegRef(UA);
if (!MidDefs.hasCoverOf(R))
UpReached.insert(R);
@ -648,7 +648,7 @@ void Liveness::computeLiveIns() {
auto &LOX = PhiLOX[PrA.Addr->getCode()];
for (auto R : RUs) {
RegisterRef RR = R.first;
if (!isRestrictedToRef(PA, UA, RR))
if (UA.Addr->getFlags() & NodeAttrs::Shadow)
RR = getRestrictedRegRef(UA);
// The restricted ref may be different from the ref that was
// accessed in the "real use". This means that this phi use
@ -770,29 +770,6 @@ void Liveness::resetKills(MachineBasicBlock *B) {
}
// For shadows, determine if RR is aliased to a reaching def of any other
// shadow associated with RA. The register ref on RA will be "larger" than
// each individual reaching def, and to determine the data-flow between defs
// and uses of RR it may be necessary to visit all shadows. If RR is not
// aliased to the reaching def of any other shadow, then visiting only RA
// is sufficient. In that sense, the data flow of RR would be restricted to
// the reference RA.
// For non-shadows, this function returns "true".
bool Liveness::isRestrictedToRef(NodeAddr<InstrNode*> IA, NodeAddr<RefNode*> RA,
RegisterRef RR) const {
NodeId Start = RA.Id;
for (NodeAddr<RefNode*> TA = DFG.getNextShadow(IA, RA);
TA.Id != 0 && TA.Id != Start; TA = DFG.getNextShadow(IA, TA)) {
NodeId RD = TA.Addr->getReachingDef();
if (RD == 0)
continue;
if (DFG.alias(RR, DFG.addr<DefNode*>(RD).Addr->getRegRef()))
return false;
}
return true;
}
RegisterRef Liveness::getRestrictedRegRef(NodeAddr<RefNode*> RA) const {
assert(DFG.IsRef<NodeAttrs::Use>(RA));
if (RA.Addr->getFlags() & NodeAttrs::Shadow) {
@ -850,12 +827,13 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
}
if (Trace) {
dbgs() << LLVM_FUNCTION_NAME << " in BB#" << B->getNumber()
<< " after recursion into";
dbgs() << "\n-- BB#" << B->getNumber() << ": " << LLVM_FUNCTION_NAME
<< " after recursion into: {";
for (auto I : *N)
dbgs() << ' ' << I->getBlock()->getNumber();
dbgs() << "\n LiveIn: " << Print<RefMap>(LiveIn, DFG);
dbgs() << "\n Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
dbgs() << " }\n";
dbgs() << " LiveIn: " << Print<RefMap>(LiveIn, DFG) << '\n';
dbgs() << " Local: " << Print<RegisterSet>(LiveMap[B], DFG) << '\n';
}
// Add phi uses that are live on exit from this block.

View File

@ -0,0 +1,73 @@
; RUN: llc -march=hexagon -verify-machineinstrs < %s | FileCheck %s
; Verify that the code compiles successfully.
; CHECK: call printf
target triple = "hexagon"
%struct.0 = type { i32, i32, i32, i32, i32, i32, i32, i32, i32 }
@.str.13 = external unnamed_addr constant [60 x i8], align 1
declare void @printf(i8* nocapture readonly, ...) local_unnamed_addr #0
declare void @danny() local_unnamed_addr #0
declare zeroext i8 @sammy() local_unnamed_addr #0
; Function Attrs: nounwind
define void @main() local_unnamed_addr #0 {
entry:
br i1 undef, label %if.then8, label %if.end10
if.then8: ; preds = %entry
ret void
if.end10: ; preds = %entry
br label %do.body
do.body: ; preds = %if.end88.do.body_crit_edge, %if.end10
%cond = icmp eq i32 undef, 0
br i1 %cond, label %if.end49, label %if.then124
if.end49: ; preds = %do.body
br i1 undef, label %if.end55, label %if.then53
if.then53: ; preds = %if.end49
call void @danny()
br label %if.end55
if.end55: ; preds = %if.then53, %if.end49
%call76 = call zeroext i8 @sammy() #0
switch i8 %call76, label %sw.epilog79 [
i8 0, label %sw.bb77
i8 3, label %sw.bb77
]
sw.bb77: ; preds = %if.end55, %if.end55
unreachable
sw.epilog79: ; preds = %if.end55
br i1 undef, label %if.end88, label %if.then81
if.then81: ; preds = %sw.epilog79
%div87 = fdiv float 0.000000e+00, undef
br label %if.end88
if.end88: ; preds = %if.then81, %sw.epilog79
%t.1 = phi float [ undef, %sw.epilog79 ], [ %div87, %if.then81 ]
%div89 = fdiv float 1.000000e+00, %t.1
%mul92 = fmul float undef, %div89
%div93 = fdiv float %mul92, 1.000000e+06
%conv107 = fpext float %div93 to double
call void (i8*, ...) @printf(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @.str.13, i32 0, i32 0), double %conv107, double undef, i64 undef, i32 undef) #0
br i1 undef, label %if.end88.do.body_crit_edge, label %if.then124
if.end88.do.body_crit_edge: ; preds = %if.end88
br label %do.body
if.then124: ; preds = %if.end88, %do.body
unreachable
}
attributes #0 = { nounwind }