diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 74233f8..50a1068 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -10902,6 +10902,91 @@ static bool CanMoveInstructionBeforePath(const GrowingInterCodeBasicBlockPtrArra return true; } +bool InterCodeBasicBlock::IsDirectDominatorBlock(InterCodeBasicBlock* block) +{ + if (this == block) + return true; + + if (block->mLoopHead) + return false; + + if (block->mEntryBlocks.Size() == 0) + return false; + + for (int i = 0; i < block->mEntryBlocks.Size(); i++) + if (!IsDirectDominatorBlock(block->mEntryBlocks[i])) + return false; + + return true; +} + +bool InterCodeBasicBlock::HoistCommonConditionalPath(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + if (mFalseJump) + { + InterCodeBasicBlock* cblock = nullptr, * eblock = nullptr; + + if (!mTrueJump->mFalseJump && mTrueJump->mTrueJump && IsDirectDominatorBlock(mTrueJump->mTrueJump)) + { + cblock = mTrueJump; + eblock = mTrueJump->mTrueJump; + } + else if (!mFalseJump->mFalseJump && mFalseJump->mTrueJump && IsDirectDominatorBlock(mFalseJump->mTrueJump)) + { + cblock = mFalseJump; + eblock = mFalseJump->mTrueJump; + } + + if (cblock && cblock->mNumEntries == 1) + { + for (int i = 0; i < cblock->mInstructions.Size(); i++) + { + InterInstruction* ins = cblock->mInstructions[i]; + + if (cblock->CanMoveInstructionBeforeBlock(i) && !HasSideEffect(ins->mCode) && ins->mDst.mTemp >= 0 && !cblock->IsTempModifiedInRange(i + 1, cblock->mInstructions.Size(), ins->mDst.mTemp)) + { + int j = 0; + while (j < eblock->mInstructions.Size() && !eblock->mInstructions[j]->IsEqualSource(ins)) + j++; + + if (j < eblock->mInstructions.Size() && !eblock->IsTempModifiedInRange(0, j, ins->mDst.mTemp) && eblock->CanMoveInstructionBeforeBlock(j) && cblock->CanMoveInstructionBeforeBlock(cblock->mInstructions.Size(), eblock->mInstructions[j])) + { + eblock->mInstructions[j]->mCode = IC_LOAD_TEMPORARY; + eblock->mInstructions[j]->mSrc[0] = ins->mDst; + eblock->mInstructions[j]->mNumOperands = 1; + + mInstructions.Insert(mInstructions.Size() - 1, ins); + cblock->mInstructions.Remove(i); + + mExitRequiredTemps += ins->mDst.mTemp; + cblock->mEntryRequiredTemps += ins->mDst.mTemp; + cblock->mExitRequiredTemps += ins->mDst.mTemp; + eblock->mEntryRequiredTemps += ins->mDst.mTemp; + i--; + changed = true; + } + } + } + } + } + + if (mTrueJump && mTrueJump->HoistCommonConditionalPath()) + changed = true; + if (mFalseJump && mFalseJump->HoistCommonConditionalPath()) + changed = true; + } + + return changed; +} + + + bool InterCodeBasicBlock::MoveTrainCrossBlock(void) { bool changed = false; @@ -15115,6 +15200,27 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray mInstructions[i + 1]->mCode = IC_NONE; mInstructions[i + 1]->mNumOperands = 0; changed = true; } +#endif +#if 1 + else if ( + mInstructions[i + 0]->mCode == IC_LEA && mInstructions[i + 0]->mSrc[0].mTemp >= 0 && + mInstructions[i + 1]->mCode == IC_LEA && mInstructions[i + 1]->mSrc[0].mTemp >= 0 && + mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && + mInstructions[i + 1]->mSrc[1].mFinal && + mInstructions[i + 0]->mSrc[0].IsUByte() && mInstructions[i + 1]->mSrc[0].IsUByte() && mInstructions[i + 0]->mSrc[0].mRange.mMaxValue + mInstructions[i + 1]->mSrc[0].mRange.mMaxValue < 256) + { + mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1]; + + mInstructions[i + 0]->mCode = IC_BINARY_OPERATOR; + mInstructions[i + 0]->mOperator = IA_ADD; + mInstructions[i + 0]->mDst.mType = IT_INT16; + mInstructions[i + 0]->mSrc[1] = mInstructions[i + 1]->mSrc[0]; + mInstructions[i + 0]->mDst.mRange = mInstructions[i + 0]->mSrc[0].mRange; + mInstructions[i + 0]->mDst.mRange.mMaxValue += mInstructions[i + 0]->mSrc[1].mRange.mMaxValue; + + mInstructions[i + 1]->mSrc[0] = mInstructions[i + 0]->mDst; + changed = true; + } #endif else if ( mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_ADD && mInstructions[i + 0]->mSrc[1].mTemp < 0 && mInstructions[i + 0]->mSrc[0].mType == IT_INT16 && @@ -16129,7 +16235,6 @@ void InterCodeBasicBlock::WarnUsedUndefinedVariables(void) } } - void InterCodeBasicBlock::CollectVariables(GrowingVariableArray& globalVars, GrowingVariableArray& localVars, GrowingVariableArray& paramVars, InterMemory paramMemory) { int i; @@ -17284,7 +17389,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "test"); + CheckFunc = !strcmp(mIdent->mString, "tile_row"); mEntryBlock = mBlocks[0]; @@ -17666,6 +17771,9 @@ void InterCodeProcedure::Close(void) #endif + HoistCommonConditionalPath(); + DisassembleDebug("HoistCommonConditionalPath"); + #if 1 ResetVisited(); mEntryBlock->MoveLoopHeadCheckToTail(); @@ -18640,6 +18748,19 @@ bool InterCodeProcedure::GlobalConstantPropagation(void) return mEntryBlock->PropagateConstTemps(ctemps); } +void InterCodeProcedure::HoistCommonConditionalPath(void) +{ + for(;;) + { + ResetVisited(); + if (!mEntryBlock->HoistCommonConditionalPath()) + return; + TempForwarding(); + RemoveUnusedInstructions(); + } +} + + void InterCodeProcedure::ReduceTemporaries(void) { NumberSet* collisionSet; diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 8e8378a..4699e7d 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -499,6 +499,8 @@ public: bool ForwardLoopMovedTemp(void); bool MoveTrainCrossBlock(void); + bool HoistCommonConditionalPath(void); + bool IsDirectDominatorBlock(InterCodeBasicBlock* block); void MarkRelevantStatics(void); void RemoveNonRelevantStatics(void); @@ -679,6 +681,7 @@ protected: void RebuildIntegerRangeSet(void); void CombineIndirectAddressing(void); void SingleTailLoopOptimization(InterMemory paramMemory); + void HoistCommonConditionalPath(void); void MergeBasicBlocks(void); void CheckUsedDefinedTemps(void);