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

Method FindNewBasicBlockFor

source/opt/code_sink.cpp:73–168  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

71}
72
73BasicBlock* CodeSinkingPass::FindNewBasicBlockFor(Instruction* inst) {
74 assert(inst->result_id() != 0 && "Instruction should have a result.");
75 BasicBlock* original_bb = context()->get_instr_block(inst);
76 BasicBlock* bb = original_bb;
77
78 std::unordered_set<uint32_t> bbs_with_uses;
79 get_def_use_mgr()->ForEachUse(
80 inst, [&bbs_with_uses, this](Instruction* use, uint32_t idx) {
81 if (use->opcode() != spv::Op::OpPhi) {
82 BasicBlock* use_bb = context()->get_instr_block(use);
83 if (use_bb) {
84 bbs_with_uses.insert(use_bb->id());
85 }
86 } else {
87 bbs_with_uses.insert(use->GetSingleWordOperand(idx + 1));
88 }
89 });
90
91 while (true) {
92 // If |inst| is used in |bb|, then |inst| cannot be moved any further.
93 if (bbs_with_uses.count(bb->id())) {
94 break;
95 }
96
97 // If |bb| has one successor (succ_bb), and |bb| is the only predecessor
98 // of succ_bb, then |inst| can be moved to succ_bb. If succ_bb, has move
99 // then one predecessor, then moving |inst| into succ_bb could cause it to
100 // be executed more often, so the search has to stop.
101 if (bb->terminator()->opcode() == spv::Op::OpBranch) {
102 uint32_t succ_bb_id = bb->terminator()->GetSingleWordInOperand(0);
103 if (cfg()->preds(succ_bb_id).size() == 1) {
104 bb = context()->get_instr_block(succ_bb_id);
105 continue;
106 } else {
107 break;
108 }
109 }
110
111 // The remaining checks need to know the merge node. If there is no merge
112 // instruction or an OpLoopMerge, then it is a break or continue. We could
113 // figure it out, but not worth doing it now.
114 Instruction* merge_inst = bb->GetMergeInst();
115 if (merge_inst == nullptr ||
116 merge_inst->opcode() != spv::Op::OpSelectionMerge) {
117 break;
118 }
119
120 // Check all of the successors of |bb| it see which lead to a use of |inst|
121 // before reaching the merge node.
122 bool used_in_multiple_blocks = false;
123 uint32_t bb_used_in = 0;
124 bb->ForEachSuccessorLabel([this, bb, &bb_used_in, &used_in_multiple_blocks,
125 &bbs_with_uses](uint32_t* succ_bb_id) {
126 if (IntersectsPath(*succ_bb_id, bb->MergeBlockIdIfAny(), bbs_with_uses)) {
127 if (bb_used_in == 0) {
128 bb_used_in = *succ_bb_id;
129 } else {
130 used_in_multiple_blocks = true;

Callers

nothing calls this directly

Calls 14

get_instr_blockMethod · 0.80
ForEachUseMethod · 0.80
GetSingleWordOperandMethod · 0.80
GetMergeInstMethod · 0.80
ForEachSuccessorLabelMethod · 0.80
MergeBlockIdIfAnyMethod · 0.80
result_idMethod · 0.45
opcodeMethod · 0.45
insertMethod · 0.45
idMethod · 0.45
countMethod · 0.45

Tested by

no test coverage detected