| 267 | } |
| 268 | |
| 269 | bool LoopFissionImpl::CanPerformSplit() { |
| 270 | // Return false if any of the condition instructions in the loop depend on a |
| 271 | // load. |
| 272 | if (load_used_in_condition_) { |
| 273 | return false; |
| 274 | } |
| 275 | |
| 276 | // Build a list of all parent loops of this loop. Loop dependence analysis |
| 277 | // needs this structure. |
| 278 | std::vector<const Loop*> loops; |
| 279 | Loop* parent_loop = loop_; |
| 280 | while (parent_loop) { |
| 281 | loops.push_back(parent_loop); |
| 282 | parent_loop = parent_loop->GetParent(); |
| 283 | } |
| 284 | |
| 285 | LoopDependenceAnalysis analysis{context_, loops}; |
| 286 | |
| 287 | // A list of all the stores in the cloned loop. |
| 288 | std::vector<Instruction*> set_one_stores{}; |
| 289 | |
| 290 | // A list of all the loads in the cloned loop. |
| 291 | std::vector<Instruction*> set_one_loads{}; |
| 292 | |
| 293 | // Populate the above lists. |
| 294 | for (Instruction* inst : cloned_loop_instructions_) { |
| 295 | if (inst->opcode() == spv::Op::OpStore) { |
| 296 | set_one_stores.push_back(inst); |
| 297 | } else if (inst->opcode() == spv::Op::OpLoad) { |
| 298 | set_one_loads.push_back(inst); |
| 299 | } |
| 300 | |
| 301 | // If we find any instruction which we can't move (such as a barrier), |
| 302 | // return false. |
| 303 | if (!MovableInstruction(*inst)) return false; |
| 304 | } |
| 305 | |
| 306 | // We need to calculate the depth of the loop to create the loop dependency |
| 307 | // distance vectors. |
| 308 | const size_t loop_depth = loop_->GetDepth(); |
| 309 | |
| 310 | // Check the dependencies between loads in the cloned loop and stores in the |
| 311 | // original and vice versa. |
| 312 | for (Instruction* inst : original_loop_instructions_) { |
| 313 | // If we find any instruction which we can't move (such as a barrier), |
| 314 | // return false. |
| 315 | if (!MovableInstruction(*inst)) return false; |
| 316 | |
| 317 | // Look at the dependency between the loads in the original and stores in |
| 318 | // the cloned loops. |
| 319 | if (inst->opcode() == spv::Op::OpLoad) { |
| 320 | for (Instruction* store : set_one_stores) { |
| 321 | DistanceVector vec{loop_depth}; |
| 322 | |
| 323 | // If the store actually should appear after the load, return false. |
| 324 | // This means the store has been placed in the wrong grouping. |
| 325 | if (instruction_order_[store] > instruction_order_[inst]) { |
| 326 | return false; |