Welcome to mirror list, hosted at ThFree Co, Russian Federation.

conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp « reduce « source - github.com/KhronosGroup/SPIRV-Tools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2cd779a26a387665f3b2c87f5e85e7240dc4d386 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Copyright (c) 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "source/reduce/conditional_branch_to_simple_conditional_branch_opportunity_finder.h"

#include "source/reduce/conditional_branch_to_simple_conditional_branch_reduction_opportunity.h"
#include "source/reduce/reduction_util.h"

namespace spvtools {
namespace reduce {

std::vector<std::unique_ptr<ReductionOpportunity>>
ConditionalBranchToSimpleConditionalBranchOpportunityFinder::
    GetAvailableOpportunities(opt::IRContext* context,
                              uint32_t target_function) const {
  std::vector<std::unique_ptr<ReductionOpportunity>> result;

  // Find the opportunities for redirecting all false targets before the
  // opportunities for redirecting all true targets because the former
  // opportunities disable the latter, and vice versa, and the efficiency of the
  // reducer is improved by avoiding contiguous opportunities that disable one
  // another.
  for (bool redirect_to_true : {true, false}) {
    // Consider every relevant function.
    for (auto* function : GetTargetFunctions(context, target_function)) {
      // Consider every block in the function.
      for (auto& block : *function) {
        // The terminator must be SpvOpBranchConditional.
        opt::Instruction* terminator = block.terminator();
        if (terminator->opcode() != SpvOpBranchConditional) {
          continue;
        }

        uint32_t true_block_id =
            terminator->GetSingleWordInOperand(kTrueBranchOperandIndex);
        uint32_t false_block_id =
            terminator->GetSingleWordInOperand(kFalseBranchOperandIndex);

        // The conditional branch must not already be simplified.
        if (true_block_id == false_block_id) {
          continue;
        }

        // The redirected target must not be a back-edge to a structured loop
        // header.
        uint32_t redirected_block_id =
            redirect_to_true ? false_block_id : true_block_id;
        uint32_t containing_loop_header =
            context->GetStructuredCFGAnalysis()->ContainingLoop(block.id());
        // The structured CFG analysis does not include a loop header as part
        // of the loop construct, but we want to include it, so handle this
        // special case:
        if (block.GetLoopMergeInst() != nullptr) {
          containing_loop_header = block.id();
        }
        if (redirected_block_id == containing_loop_header) {
          continue;
        }

        result.push_back(
            MakeUnique<
                ConditionalBranchToSimpleConditionalBranchReductionOpportunity>(
                context, block.terminator(), redirect_to_true));
      }
    }
  }
  return result;
}

std::string
ConditionalBranchToSimpleConditionalBranchOpportunityFinder::GetName() const {
  return "ConditionalBranchToSimpleConditionalBranchOpportunityFinder";
}

}  // namespace reduce
}  // namespace spvtools