| 241 | } |
| 242 | |
| 243 | bool BlockIsBackEdge(opt::IRContext* context, uint32_t block_id, |
| 244 | uint32_t loop_header_id) { |
| 245 | auto block = context->cfg()->block(block_id); |
| 246 | auto loop_header = context->cfg()->block(loop_header_id); |
| 247 | |
| 248 | // |block| and |loop_header| must be defined, |loop_header| must be in fact |
| 249 | // loop header and |block| must branch to it. |
| 250 | if (!(block && loop_header && loop_header->IsLoopHeader() && |
| 251 | block->IsSuccessor(loop_header))) { |
| 252 | return false; |
| 253 | } |
| 254 | |
| 255 | // |block| must be reachable and be dominated by |loop_header|. |
| 256 | opt::DominatorAnalysis* dominator_analysis = |
| 257 | context->GetDominatorAnalysis(loop_header->GetParent()); |
| 258 | return context->IsReachable(*block) && |
| 259 | dominator_analysis->Dominates(loop_header, block); |
| 260 | } |
| 261 | |
| 262 | bool BlockIsInLoopContinueConstruct(opt::IRContext* context, uint32_t block_id, |
| 263 | uint32_t maybe_loop_header_id) { |
no test coverage detected