[BOLT] Fix frameopt=all for gcc

Summary:
Fix two bugs. First, stack pointer tracking, the dataflow
analysis, was converging to the "superposition" state (meaning that at
this point there are multiple and conflicting states) too early in case
the entry state in the BB was "empty" AND there was an SP computation in
the block. In these cases, we need to propagate an "empty" value as well
and wait for an iteration where the input is not empty (only entry BBs
start with a non-empty well-defined value). Previously, it was
propagating "superposition", meaning there is a conflict of states in
this block, which is not true, since the input is empty and, therefore,
there is no preceding state to justify a collision of states.

Second, if SPT failed and has no idea about the stack values in a block
(if it is in the superposition state at a given point in a BB), shrink
wrapping should not attempt to insert computation into those blocks
that we do not understand what is happening. Fix it to bail on those
cases.

(cherry picked from FBD5858402)
This commit is contained in:
Rafael Auler 2017-09-18 16:26:00 -07:00 committed by Maksim Panchenko
parent 9df155ce11
commit ef0ec9edf9
2 changed files with 22 additions and 3 deletions

View File

@ -696,6 +696,7 @@ void ShrinkWrapping::computeSaveLocations() {
SavePos = std::vector<SmallPtrSet<MCInst *, 4>>(BC.MRI->getNumRegs());
auto &RI = Info.getReachingInsnsBackwards();
auto &DA = Info.getDominatorAnalysis();
auto &SPT = Info.getStackPointerTracking();
DEBUG(dbgs() << "Checking save/restore possibilities\n");
for (auto &BB : BF) {
@ -710,6 +711,12 @@ void ShrinkWrapping::computeSaveLocations() {
if (RI.isInLoop(BB))
continue;
const auto SPFP = *SPT.getStateBefore(*First);
// If we don't know stack state at this point, bail
if ((SPFP.first == SPT.SUPERPOSITION || SPFP.first == SPT.EMPTY) &&
(SPFP.second == SPT.SUPERPOSITION || SPFP.second == SPT.EMPTY))
continue;
for (unsigned I = 0, E = BC.MRI->getNumRegs(); I != E; ++I) {
if (!CSA.CalleeSaved[I])
continue;
@ -1144,9 +1151,15 @@ void ShrinkWrapping::moveSaveRestores() {
auto FIELoad = CSA.LoadFIEByReg[I];
assert(FIESave && FIELoad);
auto &SPT = Info.getStackPointerTracking();
auto SaveOffset = SPT.getStateBefore(*BestPosSave)->first;
const auto SPFP = *SPT.getStateBefore(*BestPosSave);
auto SaveOffset = SPFP.first;
auto SaveSize = FIESave->Size;
// If we don't know stack state at this point, bail
if ((SPFP.first == SPT.SUPERPOSITION || SPFP.first == SPT.EMPTY) &&
(SPFP.second == SPT.SUPERPOSITION || SPFP.second == SPT.EMPTY))
continue;
// Operation mode: if true, will insert push/pops instead of loads/restores
bool UsePushPops = validatePushPopsMode(I, BestPosSave, SaveOffset);

View File

@ -123,8 +123,11 @@ protected:
else
FP = std::make_pair(0, 0);
int64_t Output;
if (!MIA->evaluateSimple(Point, Output, SP, FP))
if (!MIA->evaluateSimple(Point, Output, SP, FP)) {
if (SPVal == EMPTY && FPVal == EMPTY)
return SPVal;
return SUPERPOSITION;
}
return static_cast<int>(Output);
}
@ -155,8 +158,11 @@ protected:
else
SP = std::make_pair(0, 0);
int64_t Output;
if (!MIA->evaluateSimple(Point, Output, SP, FP))
if (!MIA->evaluateSimple(Point, Output, SP, FP)) {
if (SPVal == EMPTY && FPVal == EMPTY)
return FPVal;
return SUPERPOSITION;
}
if (!HasFramePointer) {
if (MIA->escapesVariable(Point, *this->BC.MRI, false)) {