++iter;
}
- InstructionBuilder<ir::IRContext::kAnalysisDefUse |
- ir::IRContext::kAnalysisInstrToBlockMapping>
- builder(context(), &*iter);
+ InstructionBuilder builder(
+ context(), &*iter,
+ ir::IRContext::kAnalysisDefUse |
+ ir::IRContext::kAnalysisInstrToBlockMapping);
block.ForEachPhiInst([this, &builder, &modified, &common, &to_kill,
dominators, &block](ir::Instruction* phi) {
// This phi is not compatible, but subsequent phis might be.
});
}
-uint32_t IfConversion::SplatCondition(
- analysis::Vector* vec_data_ty, uint32_t cond,
- InstructionBuilder<ir::IRContext::kAnalysisDefUse |
- ir::IRContext::kAnalysisInstrToBlockMapping>* builder) {
+uint32_t IfConversion::SplatCondition(analysis::Vector* vec_data_ty,
+ uint32_t cond,
+ InstructionBuilder* builder) {
// If the data inputs to OpSelect are vectors, the condition for
// OpSelect must be a boolean vector with the same number of
// components. So splat the condition for the branch into a vector
// |where| indicates the location in |block| to insert the composite
// construct. If necessary, this function will also construct the necessary
// type instructions for the boolean vector.
- uint32_t SplatCondition(
- analysis::Vector* vec_data_ty, uint32_t cond,
- InstructionBuilder<ir::IRContext::kAnalysisDefUse |
- ir::IRContext::kAnalysisInstrToBlockMapping>* builder);
+ uint32_t SplatCondition(analysis::Vector* vec_data_ty, uint32_t cond,
+ InstructionBuilder* builder);
// Returns true if none of |phi|'s users are in |block|.
bool CheckPhiUsers(ir::Instruction* phi, ir::BasicBlock* block);
// In SPIR-V, ids are encoded as uint16_t, this id is guaranteed to be always
// invalid.
-constexpr uint32_t kInvalidId = std::numeric_limits<uint32_t>::max();
+const uint32_t kInvalidId = std::numeric_limits<uint32_t>::max();
// Helper class to abstract instruction construction and insertion.
-// |AnalysesToPreserve| asks the InstructionBuilder to preserve requested
-// analyses.
-// Supported analyses:
+// The instruction builder can preserve the following analyses (specified via
+// the constructors):
// - Def-use analysis
// - Instruction to block analysis
-template <ir::IRContext::Analysis AnalysesToPreserve =
- ir::IRContext::kAnalysisNone>
class InstructionBuilder {
- static_assert(!(AnalysesToPreserve &
- ~(ir::IRContext::kAnalysisDefUse |
- ir::IRContext::kAnalysisInstrToBlockMapping)),
- "There some unsupported analyses");
-
public:
using InsertionPointTy = spvtools::ir::BasicBlock::iterator;
// Creates an InstructionBuilder, all new instructions will be inserted before
// the instruction |insert_before|.
- InstructionBuilder(ir::IRContext* context, ir::Instruction* insert_before)
+ InstructionBuilder(
+ ir::IRContext* context, ir::Instruction* insert_before,
+ ir::IRContext::Analysis preserved_analyses = ir::IRContext::kAnalysisNone)
: InstructionBuilder(context, context->get_instr_block(insert_before),
- InsertionPointTy(insert_before)) {}
+ InsertionPointTy(insert_before),
+ preserved_analyses) {}
// Creates an InstructionBuilder, all new instructions will be inserted at the
// end of the basic block |parent_block|.
- InstructionBuilder(ir::IRContext* context, ir::BasicBlock* parent_block)
- : InstructionBuilder(context, parent_block, parent_block->end()) {}
+ InstructionBuilder(
+ ir::IRContext* context, ir::BasicBlock* parent_block,
+ ir::IRContext::Analysis preserved_analyses = ir::IRContext::kAnalysisNone)
+ : InstructionBuilder(context, parent_block, parent_block->end(),
+ preserved_analyses) {}
// Creates a new selection merge instruction.
// The id |merge_id| is the merge basic block id.
ir::IRContext* GetContext() const { return context_; }
// Returns the set of preserved analyses.
- inline static constexpr ir::IRContext::Analysis GetPreservedAnalysis() {
- return AnalysesToPreserve;
+ inline ir::IRContext::Analysis GetPreservedAnalysis() const {
+ return preserved_analyses_;
}
private:
InstructionBuilder(ir::IRContext* context, ir::BasicBlock* parent,
- InsertionPointTy insert_before)
- : context_(context), parent_(parent), insert_before_(insert_before) {}
+ InsertionPointTy insert_before,
+ ir::IRContext::Analysis preserved_analyses)
+ : context_(context),
+ parent_(parent),
+ insert_before_(insert_before),
+ preserved_analyses_(preserved_analyses) {
+ assert(!(preserved_analyses_ &
+ ~(ir::IRContext::kAnalysisDefUse |
+ ir::IRContext::kAnalysisInstrToBlockMapping)));
+ }
// Returns true if the users requested to update |analysis|.
- inline static constexpr bool IsAnalysisUpdateRequested(
- ir::IRContext::Analysis analysis) {
- return AnalysesToPreserve & analysis;
+ inline bool IsAnalysisUpdateRequested(
+ ir::IRContext::Analysis analysis) const {
+ return preserved_analyses_ & analysis;
}
// Updates the def/use manager if the user requested it. If he did not request
ir::IRContext* context_;
ir::BasicBlock* parent_;
InsertionPointTy insert_before_;
+ const ir::IRContext::Analysis preserved_analyses_;
};
} // namespace opt
kAnalysisEnd = 1 << 7
};
- friend inline constexpr Analysis operator|(Analysis lhs, Analysis rhs);
+ friend inline Analysis operator|(Analysis lhs, Analysis rhs);
friend inline Analysis& operator|=(Analysis& lhs, Analysis rhs);
- friend inline constexpr Analysis operator<<(Analysis a, int shift);
+ friend inline Analysis operator<<(Analysis a, int shift);
friend inline Analysis& operator<<=(Analysis& a, int shift);
// Creates an |IRContext| that contains an owned |Module|
std::unique_ptr<opt::analysis::TypeManager> type_mgr_;
};
-inline constexpr ir::IRContext::Analysis operator|(
- ir::IRContext::Analysis lhs, ir::IRContext::Analysis rhs) {
+inline ir::IRContext::Analysis operator|(ir::IRContext::Analysis lhs,
+ ir::IRContext::Analysis rhs) {
return static_cast<ir::IRContext::Analysis>(static_cast<int>(lhs) |
static_cast<int>(rhs));
}
return lhs;
}
-inline constexpr ir::IRContext::Analysis operator<<(ir::IRContext::Analysis a,
- int shift) {
+inline ir::IRContext::Analysis operator<<(ir::IRContext::Analysis a,
+ int shift) {
return static_cast<ir::IRContext::Analysis>(static_cast<int>(a) << shift);
}
context->get_def_use_mgr();
context->get_instr_block(nullptr);
- opt::InstructionBuilder<> builder(context.get(), &*bb->begin());
+ opt::InstructionBuilder builder(context.get(), &*bb->begin());
ir::Instruction* phi1 = builder.AddPhi(7, {9, 14});
ir::Instruction* phi2 = builder.AddPhi(10, {16, 14});
context->get_instr_block(nullptr);
ir::BasicBlock* bb = context->cfg()->block(18);
- opt::InstructionBuilder<ir::IRContext::kAnalysisDefUse |
- ir::IRContext::kAnalysisInstrToBlockMapping>
- builder(context.get(), &*bb->begin());
+ opt::InstructionBuilder builder(
+ context.get(), &*bb->begin(),
+ ir::IRContext::kAnalysisDefUse |
+ ir::IRContext::kAnalysisInstrToBlockMapping);
ir::Instruction* phi1 = builder.AddPhi(7, {9, 14});
ir::Instruction* phi2 = builder.AddPhi(10, {16, 14});
context.get(), SpvOpLabel, 0, context->TakeNextId(), {})))));
ir::BasicBlock& bb_true = *fn.begin();
{
- opt::InstructionBuilder<> builder(context.get(), &*bb_true.begin());
+ opt::InstructionBuilder builder(context.get(), &*bb_true.begin());
builder.AddBranch(bb_merge.id());
}
context.get(), SpvOpLabel, 0, context->TakeNextId(), {})))));
ir::BasicBlock& bb_cond = *fn.begin();
- opt::InstructionBuilder<> builder(context.get(), &bb_cond);
+ opt::InstructionBuilder builder(context.get(), &bb_cond);
// This also test consecutive instruction insertion: merge selection +
// branch.
builder.AddConditionalBranch(9, bb_true.id(), bb_merge.id(), bb_merge.id());
BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
EXPECT_NE(nullptr, context);
- opt::InstructionBuilder<> builder(
+ opt::InstructionBuilder builder(
context.get(), &*context->module()->begin()->begin()->begin());
EXPECT_NE(nullptr, builder.AddSelect(3u, 4u, 5u, 6u));
BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
EXPECT_NE(nullptr, context);
- opt::InstructionBuilder<> builder(
+ opt::InstructionBuilder builder(
context.get(), &*context->module()->begin()->begin()->begin());
std::vector<uint32_t> ids = {3u, 4u, 4u, 3u};
EXPECT_NE(nullptr, builder.AddCompositeConstruct(5u, ids));