• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019 Valve Corporation
2 // Copyright (c) 2019 LunarG Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #ifndef LIBSPIRV_OPT_CONVERT_TO_HALF_PASS_H_
17 #define LIBSPIRV_OPT_CONVERT_TO_HALF_PASS_H_
18 
19 #include "source/opt/ir_builder.h"
20 #include "source/opt/pass.h"
21 
22 namespace spvtools {
23 namespace opt {
24 
25 class ConvertToHalfPass : public Pass {
26  public:
ConvertToHalfPass()27   ConvertToHalfPass() : Pass() {}
28 
29   ~ConvertToHalfPass() override = default;
30 
GetPreservedAnalyses()31   IRContext::Analysis GetPreservedAnalyses() override {
32     return IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping;
33   }
34 
35   // See optimizer.hpp for pass user documentation.
36   Status Process() override;
37 
name()38   const char* name() const override { return "convert-to-half-pass"; }
39 
40  private:
41   // Return true if |inst| is an arithmetic, composite or phi op that can be
42   // of type float16
43   bool IsArithmetic(Instruction* inst);
44 
45   // Return true if |inst| returns scalar, vector or matrix type with base
46   // float and |width|
47   bool IsFloat(Instruction* inst, uint32_t width);
48 
49   // Return true if |inst| is decorated with RelaxedPrecision
50   bool IsDecoratedRelaxed(Instruction* inst);
51 
52   // Return true if |id| has been added to the relaxed id set
53   bool IsRelaxed(uint32_t id);
54 
55   // Add |id| to the relaxed id set
56   void AddRelaxed(uint32_t id);
57 
58   // Return type id for float with |width|
59   analysis::Type* FloatScalarType(uint32_t width);
60 
61   // Return type id for vector of length |vlen| of float of |width|
62   analysis::Type* FloatVectorType(uint32_t v_len, uint32_t width);
63 
64   // Return type id for matrix of |v_cnt| vectors of length identical to
65   // |vty_id| of float of |width|
66   analysis::Type* FloatMatrixType(uint32_t v_cnt, uint32_t vty_id,
67                                   uint32_t width);
68 
69   // Return equivalent to float type |ty_id| with |width|
70   uint32_t EquivFloatTypeId(uint32_t ty_id, uint32_t width);
71 
72   // Append instructions to builder to convert value |*val_idp| to type
73   // |ty_id| but with |width|. Set |*val_idp| to the new id.
74   void GenConvert(uint32_t* val_idp, uint32_t width, Instruction* inst);
75 
76   // Remove RelaxedPrecision decoration of |id|.
77   bool RemoveRelaxedDecoration(uint32_t id);
78 
79   // Add |inst| to relaxed instruction set if warranted. Specifically, if
80   // it is float32 and either decorated relaxed or a composite or phi
81   // instruction where all operands are relaxed or all uses are relaxed.
82   bool CloseRelaxInst(Instruction* inst);
83 
84   // If |inst| is an arithmetic, phi, extract or convert instruction of float32
85   // base type and decorated with RelaxedPrecision, change it to the equivalent
86   // float16 based type instruction. Specifically, insert instructions to
87   // convert all operands to float16 (if needed) and change its type to the
88   // equivalent float16 type. Otherwise, insert instructions to convert its
89   // operands back to their original types, if needed.
90   bool GenHalfInst(Instruction* inst);
91 
92   // Gen code for relaxed arithmetic |inst|
93   bool GenHalfArith(Instruction* inst);
94 
95   // Gen code for relaxed phi |inst|
96   bool ProcessPhi(Instruction* inst);
97 
98   // Gen code for relaxed convert |inst|
99   bool ProcessConvert(Instruction* inst);
100 
101   // Gen code for image reference |inst|
102   bool ProcessImageRef(Instruction* inst);
103 
104   // Process default non-relaxed |inst|
105   bool ProcessDefault(Instruction* inst);
106 
107   // If |inst| is an FConvert of a matrix type, decompose it to a series
108   // of vector extracts, converts and inserts into an Undef. These are
109   // generated by GenHalfInst because they are easier to manipulate, but are
110   // invalid so we need to clean them up.
111   bool MatConvertCleanup(Instruction* inst);
112 
113   // Call GenHalfInst on every instruction in |func|.
114   // If code is generated for an instruction, replace the instruction
115   // with the new instructions that are generated.
116   bool ProcessFunction(Function* func);
117 
118   Pass::Status ProcessImpl();
119 
120   // Initialize state for converting to half
121   void Initialize();
122 
123   // Set of core operations to be processed
124   std::unordered_set<uint32_t> target_ops_core_;
125 
126   // Set of 450 extension operations to be processed
127   std::unordered_set<uint32_t> target_ops_450_;
128 
129   // Set of sample operations
130   std::unordered_set<uint32_t> image_ops_;
131 
132   // Set of dref sample operations
133   std::unordered_set<uint32_t> dref_image_ops_;
134 
135   // Set of dref sample operations
136   std::unordered_set<uint32_t> closure_ops_;
137 
138   // Set of ids of all relaxed instructions
139   std::unordered_set<uint32_t> relaxed_ids_set_;
140 
141   // Ids of all converted instructions
142   std::unordered_set<uint32_t> converted_ids_;
143 };
144 
145 }  // namespace opt
146 }  // namespace spvtools
147 
148 #endif  // LIBSPIRV_OPT_CONVERT_TO_HALF_PASS_H_
149