Home | History | Annotate | Download | only in opt
      1 // Copyright (c) 2018 Google LLC
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #ifndef SOURCE_OPT_FOLDING_RULES_H_
     16 #define SOURCE_OPT_FOLDING_RULES_H_
     17 
     18 #include <cstdint>
     19 #include <unordered_map>
     20 #include <vector>
     21 
     22 #include "source/opt/constants.h"
     23 
     24 namespace spvtools {
     25 namespace opt {
     26 
     27 // Folding Rules:
     28 //
     29 // The folding mechanism is built around the concept of a |FoldingRule|.  A
     30 // folding rule is a function that implements a method of simplifying an
     31 // instruction.
     32 //
     33 // The inputs to a folding rule are:
     34 //     |inst| - the instruction to be simplified.
     35 //     |constants| - if an in-operands is an id of a constant, then the
     36 //                   corresponding value in |constants| contains that
     37 //                   constant value.  Otherwise, the corresponding entry in
     38 //                   |constants| is |nullptr|.
     39 //
     40 // A folding rule returns true if |inst| can be simplified using this rule.  If
     41 // the instruction can be simplified, then |inst| is changed to the simplified
     42 // instruction.  Otherwise, |inst| remains the same.
     43 //
     44 // See folding_rules.cpp for examples on how to write a folding rule.  It is
     45 // important to note that if |inst| can be folded to the result of an
     46 // instruction that feed it, then |inst| should be changed to an OpCopyObject
     47 // that copies that id.
     48 //
     49 // Be sure to add new folding rules to the table of folding rules in the
     50 // constructor for FoldingRules.  The new rule should be added to the list for
     51 // every opcode that it applies to.  Note that earlier rules in the list are
     52 // given priority.  That is, if an earlier rule is able to fold an instruction,
     53 // the later rules will not be attempted.
     54 
     55 using FoldingRule = std::function<bool(
     56     IRContext* context, Instruction* inst,
     57     const std::vector<const analysis::Constant*>& constants)>;
     58 
     59 class FoldingRules {
     60  public:
     61   FoldingRules();
     62 
     63   const std::vector<FoldingRule>& GetRulesForOpcode(SpvOp opcode) const {
     64     auto it = rules_.find(opcode);
     65     if (it != rules_.end()) {
     66       return it->second;
     67     }
     68     return empty_vector_;
     69   }
     70 
     71  private:
     72   std::unordered_map<uint32_t, std::vector<FoldingRule>> rules_;
     73   std::vector<FoldingRule> empty_vector_;
     74 };
     75 
     76 }  // namespace opt
     77 }  // namespace spvtools
     78 
     79 #endif  // SOURCE_OPT_FOLDING_RULES_H_
     80