diff --git a/include/base/SMPBasicBlock.h b/include/base/SMPBasicBlock.h index 5080d4a706df59252aa4c074671b4587d7bd6cc1..067a47820f23a5195772648a18c41160fa1a869b 100644 --- a/include/base/SMPBasicBlock.h +++ b/include/base/SMPBasicBlock.h @@ -351,6 +351,7 @@ public: bool IsBlockPred(int BlockNum) const; // Is BlockNum a predecessor block of this block bool HasLoopHeadAsSuccessor(int &HeadBlockNum) const; // block has HeadBlockNum as successor, which is a loop header bool HasLoopHeadWithInvertedExitAsSuccessor(void) const; // block has loop head successor that ends with INVERTED_LOOP_EXIT + bool HasInvertedLoopBack(void) const; // COND_BRANCH falls through to loop header of innermost loop containing this block bool IsLiveIn(const STARSOpndTypePtr &CurrOp); inline bool IsLiveOut(const STARSOpndTypePtr &CurrOp) const { return (LiveOutSet.end() != LiveOutSet.find(CurrOp)); diff --git a/include/base/SMPDataFlowAnalysis.h b/include/base/SMPDataFlowAnalysis.h index fef5ea8789f245d74618a655da46b016d00e5097..381c58efa426d1c084f062e205f3e84b82ceb381 100644 --- a/include/base/SMPDataFlowAnalysis.h +++ b/include/base/SMPDataFlowAnalysis.h @@ -671,7 +671,8 @@ enum ControlFlowType { JUMP_TO_SWITCH_INDIR_JUMP = 9, // jump around default case or preliminary calculations to INDIR_JUMP block for switch SHORT_CIRCUIT_BRANCH = 10, // any branch in short-circuit conditional evaluation SHORT_CIRCUIT_LOOP_EXIT = 11, // short-circuit compound conditional expression that exits loop when true - INVERTED_LOOP_EXIT = 12 // COND_BRANCH falls out of loop via headerblock, branch taken stays in loop; code layout puts headerblock at bottom + INVERTED_LOOP_EXIT = 12, // COND_BRANCH falls out of loop via headerblock, branch taken stays in loop; code layout puts headerblock at bottom + INVERTED_LOOP_BACK = 13 // COND_BRANCH falls through to loop headerblock of its containing innermost loop }; // Strings for debug dumps of ControlFlowType. diff --git a/src/base/SMPBasicBlock.cpp b/src/base/SMPBasicBlock.cpp index d7471f7584ba5a3ea41e50b1cc19fbcf334934e9..f5329462680808ce7b2f977c1593456282d2a130 100644 --- a/src/base/SMPBasicBlock.cpp +++ b/src/base/SMPBasicBlock.cpp @@ -1139,6 +1139,26 @@ bool SMPBasicBlock::HasLoopHeadWithInvertedExitAsSuccessor(void) const { return OddFlowCase; } // end of SMPBasicBlock::HasLoopHeadWithInvertedExitAsSuccessor() +// COND_BRANCH falls through to loop header of innermost loop containing this block +bool SMPBasicBlock::HasInvertedLoopBack(void) const { + bool FallsThroughToLoopHead = false; + if (this->HasConditionalBranch()) { + list<SMPBasicBlock *>::const_iterator SuccIter = this->GetCondNonFallThroughSucc(); + SMPBasicBlock *SuccBlock = (*SuccIter); + assert(nullptr != SuccBlock); + int TargetBlockNum = SuccBlock->GetNumber(); + SuccIter = this->GetCondOtherSucc(TargetBlockNum); + SuccBlock = (*SuccIter); + assert(nullptr != SuccBlock); + int FallThroughBlockNum = SuccBlock->GetNumber(); + if (SuccBlock->IsLoopHeaderBlock()) { + FallsThroughToLoopHead = (SuccBlock->IsLoopHeaderBlock() && this->GetFunc()->AreBlocksInSameLoops(FallThroughBlockNum, this->GetNumber())); + } + } + + return FallsThroughToLoopHead; +} // end of SMPBasicBlock::HasInvertedLoopBack() + // Determine if CurrOp is LiveIn; if LiveIn set is stale, recompute. bool SMPBasicBlock::IsLiveIn(const STARSOpndTypePtr &CurrOp) { @@ -2683,7 +2703,8 @@ bool SMPBasicBlock::DoesDefControlLoopFlow(const STARSOpndTypePtr &DefOp, int De if (FlowType == COND_BRANCH) { STARS_ea_t LastAddr = LastInst->GetAddr(); ControlFlowType LastBranchType = this->GetFunc()->GetControlFlowType(LastAddr); - if ((LastBranchType != LOOP_EXIT) && (LastBranchType != LOOP_BACK)) { + bool IsLoopBack = ((LastBranchType == LOOP_BACK) || (LastBranchType == INVERTED_LOOP_BACK)); + if ((LastBranchType != LOOP_EXIT) && (!IsLoopBack)) { return false; } } diff --git a/src/base/SMPDataFlowAnalysis.cpp b/src/base/SMPDataFlowAnalysis.cpp index 489777f03f362b51e62400135bdba65b1cbb0556..f5e3ed84ad0491df54d6a3d9d00d5ff1b34666c7 100644 --- a/src/base/SMPDataFlowAnalysis.cpp +++ b/src/base/SMPDataFlowAnalysis.cpp @@ -163,8 +163,8 @@ const char *SPARKFloatingPointStackRegNames[8] = { "FloatingPointStackDummy", "F const char *CFTTypeStrings[20] = { "FALL_THROUGH", "BRANCH_IF_THEN", "BRANCH_IF_THEN_ELSE", "JUMP_BEFORE_ELSE", "LOOP_BACK", "LOOP_EXIT", "JUMP_INTO_LOOP_TEST", "JUMP_TO_DEFAULT_CASE", "CASE_BREAK_TO_FOLLOW_NODE", -"JUMP_TO_SWITCH_INDIR_JUMP", "SHORT_CIRCUIT_BRANCH", "SHORT_CIRCUIT_LOOP_EXIT", "INVERTED_LOOP_EXIT", -"", "", "", "", "", "", "" +"JUMP_TO_SWITCH_INDIR_JUMP", "SHORT_CIRCUIT_BRANCH", "SHORT_CIRCUIT_LOOP_EXIT", "INVERTED_LOOP_EXIT", +"INVERTED_LOOP_BACK", "", "", "", "", "", "" }; // Distinguishes subword regs from their parent regs diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp index 8642815e22db8755fa885769701786cdf92e2c92..cf8599f5a665eb40eb4ddff01b1dd733a43dd1b0 100644 --- a/src/base/SMPFunction.cpp +++ b/src/base/SMPFunction.cpp @@ -12093,7 +12093,8 @@ int SMPFunction::TrackConditionalBranchTerminus(int BranchHeadBlockNum, int Curr list<int> WorkListBlockNums; STARS_ea_t LastAddr = CurrBlock->GetLastAddr(); ControlFlowType LastCFType = this->GetControlFlowType(LastAddr); - if (LastCFType == LOOP_BACK) { + bool IsLoopBack = ((LastCFType == LOOP_BACK) || (LastCFType == INVERTED_LOOP_BACK)); + if (IsLoopBack) { // Don't follow back edge, but get the other successor, if conditional. vector<SMPInstr *>::const_reverse_iterator LastInstIter = CurrBlock->GetRevInstCBegin(); if (COND_BRANCH == (*LastInstIter)->GetDataFlowType()) { @@ -17014,7 +17015,12 @@ void SMPFunction::MarkSpecialNumericErrorCases(void) { } else if (CurrBlock->IsLoopTailBlock()) { // We must be looping back to the loop header. - this->SetControlFlowType(InstAddr, LOOP_BACK); + if (CurrBlock->HasInvertedLoopBack()) { // falling through to loop header + this->SetControlFlowType(InstAddr, INVERTED_LOOP_BACK); + } + else { // normal case; branching to loop header + this->SetControlFlowType(InstAddr, LOOP_BACK); + } if (COND_BRANCH == CurrDataFlowType) { int HeaderBlockNum = CurrBlock->GetLoopHeaderNumber(); if (!CurrBlock->IsDoubleLoopTailBlock()) { // normal case @@ -23031,8 +23037,9 @@ void SMPFunction::EmitSPARKAdaForConditional(int HeaderBlockNum, int FollowBlock // For the if-then case, we emit the code for the then-block and then "end if;" and return. // For the if-then-else case, we emit the code for the then-block and then "else" etc. ControlFlowType LastCFType = this->GetControlFlowType(LastAddr); + bool IsLoopBack = ((LastCFType == LOOP_BACK) || (LastCFType == INVERTED_LOOP_BACK)); bool StaysInLoop = this->IsNonExitingLoopBackBranch(LastAddr); - bool IfThenCase = ((LastCFType == BRANCH_IF_THEN) || (StaysInLoop && ((LastCFType == LOOP_BACK) || (LastCFType == LOOP_EXIT)))); + bool IfThenCase = ((LastCFType == BRANCH_IF_THEN) || (StaysInLoop && (IsLoopBack || (LastCFType == LOOP_EXIT)))); bool ShortCircuitCase = (LastCFType == SHORT_CIRCUIT_BRANCH); assert(IfThenCase || ShortCircuitCase || (LastCFType == BRANCH_IF_THEN_ELSE)); int FallThroughBlockNum = SMP_BLOCKNUM_UNINIT; @@ -23056,6 +23063,12 @@ void SMPFunction::EmitSPARKAdaForConditional(int HeaderBlockNum, int FollowBlock assert(2 == HeaderBlock->GetNumSuccessors()); SuccIter = HeaderBlock->GetFallThroughSucc(); FallThroughBlockNum = (*SuccIter)->GetNumber(); + if (LastCFType == INVERTED_LOOP_BACK) { + // Swap the fall-through and distant blocks. + int TempBlockNum = DistantBlockNum; + DistantBlockNum = FallThroughBlockNum; + FallThroughBlockNum = TempBlockNum; + } } SMPBasicBlock *ThenBlock = this->RPOBlocks[(size_t) FallThroughBlockNum]; bool CheckFTBlock = false; // check for falling out of loop? diff --git a/src/base/SMPInstr.cpp b/src/base/SMPInstr.cpp index 90b69a516b45f3d60bac5230d4ee3a907369ed1d..b94aa3822c3c0b1df477feb232ce8d1f4e1662c4 100644 --- a/src/base/SMPInstr.cpp +++ b/src/base/SMPInstr.cpp @@ -7014,7 +7014,7 @@ void SMPInstr::EmitSPARKAda(FILE *OutFile) { ; // jumps around else clauses are handled in SMPFunction::EmitSPARKAdaForConditional() } } - else if (LOOP_BACK == FuncControlFlowType) { + else if ((LOOP_BACK == FuncControlFlowType) || (INVERTED_LOOP_BACK == FuncControlFlowType)) { // We must be looping back to the loop header. if (JUMP == CurrDataFlowType) { // simple case #if STARS_SPARK_CENTRALIZE_EMIT_LOOP