| 120 | } |
| 121 | |
| 122 | IL::BasicBlock::Iterator IL::BasicBlock::Split(IL::BasicBlock *destBlock, const IL::BasicBlock::Iterator &splitIterator, BasicBlockSplitFlagSet splitFlags) { |
| 123 | ASSERT(destBlock->IsEmpty(), "Cannot split into a filled basic block"); |
| 124 | |
| 125 | // The actual split iterator |
| 126 | Iterator splitIteratorPhi = splitIterator; |
| 127 | |
| 128 | // Redirect backedges? |
| 129 | if (splitFlags & BasicBlockSplitFlag::RedirectLoopBackedge) { |
| 130 | // Are we splitting the terminator too? |
| 131 | if (splitIteratorPhi != end()) { |
| 132 | Iterator terminator = GetTerminator(); |
| 133 | |
| 134 | // Is this a loop header we're splitting? |
| 135 | BranchControlFlow controlFlow; |
| 136 | if (Backend::IL::GetControlFlow(terminator.Get(), controlFlow) && controlFlow._continue != InvalidID) { |
| 137 | BasicBlock* continueBlock = map.GetBasicBlock(controlFlow._continue); |
| 138 | |
| 139 | // Get the terminator in the continue block |
| 140 | auto* continueBranch = continueBlock->GetTerminator().GetMutable()->Cast<BranchInstruction>(); |
| 141 | ASSERT(continueBranch, "Continue blocks must contain a single branch"); |
| 142 | |
| 143 | // Remap the back-edge to the new loop header |
| 144 | continueBranch->branch = destBlock->GetID(); |
| 145 | } |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | bool hasUnresolvedBackEdgePhis = false; |
| 150 | |
| 151 | // Splitting phis? |
| 152 | if (splitIteratorPhi->Is<PhiInstruction>() && splitFlags & BasicBlockSplitFlag::SplitPhiEdges) { |
| 153 | BranchControlFlow controlFlow; |
| 154 | Backend::IL::GetControlFlow(GetTerminator(), controlFlow); |
| 155 | |
| 156 | // Does the phi operation reference a backedge? |
| 157 | bool hasBackEdge = IsAnyPhiBranchBackEdge(splitIterator->As<PhiInstruction>(), controlFlow); |
| 158 | hasUnresolvedBackEdgePhis = hasBackEdge; |
| 159 | |
| 160 | // Validate that all phi operations have the same status |
| 161 | // We're making quite a few assumptions on this, so it must hold true |
| 162 | #ifndef NDEBUG |
| 163 | for (auto it = splitIteratorPhi; it != destBlock->end() && it->Is<PhiInstruction>(); ++it) { |
| 164 | ASSERT(IsAnyPhiBranchBackEdge(it->As<PhiInstruction>(), controlFlow) == hasBackEdge, "Mismatch in back-edge status"); |
| 165 | } |
| 166 | #endif // !NDEBUG |
| 167 | |
| 168 | // If there's no back edges, preserve the phi operations, do not split with them |
| 169 | if (!hasBackEdge) { |
| 170 | splitIteratorPhi = Backend::IL::FirstNonPhi(this, splitIteratorPhi); |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | // Byte offset to the split point |
| 175 | uint32_t splitPointRelocationOffset = relocationTable[splitIteratorPhi.relocationIndex]->offset; |
| 176 | |
| 177 | // Redirect all branch users if requested |
| 178 | if (splitFlags & BasicBlockSplitFlag::RedirectBranchUsers) { |
| 179 | TrivialStackVector<IL::OpaqueInstructionRef, 128> removed(allocators); |
no test coverage detected