MCPcopy Create free account
hub / github.com/KhronosGroup/SPIRV-Tools / CanPerformUnroll

Method CanPerformUnroll

source/opt/loop_unroller.cpp:1037–1114  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1035 * */
1036
1037bool LoopUtils::CanPerformUnroll() {
1038 // The loop is expected to be in structured order.
1039 if (!loop_->GetHeaderBlock()->GetMergeInst()) {
1040 return false;
1041 }
1042
1043 // Find check the loop has a condition we can find and evaluate.
1044 const BasicBlock* condition = loop_->FindConditionBlock();
1045 if (!condition) return false;
1046
1047 // Check that we can find and process the induction variable.
1048 const Instruction* induction = loop_->FindConditionVariable(condition);
1049 if (!induction || induction->opcode() != spv::Op::OpPhi) return false;
1050
1051 // Check that we can find the number of loop iterations.
1052 if (!loop_->FindNumberOfIterations(induction, &*condition->ctail(), nullptr))
1053 return false;
1054
1055#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1056 // ClusterFuzz/OSS-Fuzz is likely to yield examples with very high loop
1057 // iteration counts. This can cause timeouts and memouts during fuzzing that
1058 // are not classed as bugs. To avoid this noise, loop unrolling is not applied
1059 // to loops with large iteration counts when fuzzing.
1060 constexpr size_t kFuzzerIterationLimit = 100;
1061 size_t num_iterations;
1062 loop_->FindNumberOfIterations(induction, &*condition->ctail(),
1063 &num_iterations);
1064 if (num_iterations > kFuzzerIterationLimit) {
1065 return false;
1066 }
1067#endif
1068
1069 // Make sure the latch block is a unconditional branch to the header
1070 // block.
1071 const Instruction& branch = *loop_->GetLatchBlock()->ctail();
1072 bool branching_assumption =
1073 branch.opcode() == spv::Op::OpBranch &&
1074 branch.GetSingleWordInOperand(0) == loop_->GetHeaderBlock()->id();
1075 if (!branching_assumption) {
1076 return false;
1077 }
1078
1079 std::vector<Instruction*> inductions;
1080 loop_->GetInductionVariables(inductions);
1081
1082 // Ban breaks within the loop.
1083 const std::vector<uint32_t>& merge_block_preds =
1084 context_->cfg()->preds(loop_->GetMergeBlock()->id());
1085 if (merge_block_preds.size() != 1) {
1086 return false;
1087 }
1088
1089 // Ban continues within the loop.
1090 const std::vector<uint32_t>& continue_block_preds =
1091 context_->cfg()->preds(loop_->GetContinueBlock()->id());
1092 if (continue_block_preds.size() != 1) {
1093 return false;
1094 }

Callers 2

ProcessMethod · 0.80
TEST_FFunction · 0.80

Calls 15

GetMergeInstMethod · 0.80
FindConditionBlockMethod · 0.80
FindConditionVariableMethod · 0.80
ctailMethod · 0.80
GetLatchBlockMethod · 0.80
GetInductionVariablesMethod · 0.80
GetMergeBlockMethod · 0.80
GetContinueBlockMethod · 0.80
GetHeaderBlockMethod · 0.45

Tested by

no test coverage detected