Skip to content

Commit 261244f

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 8c13316 + 97f1d48 commit 261244f

File tree

3 files changed

+88
-13
lines changed

3 files changed

+88
-13
lines changed

source/opt/dead_branch_elim_pass.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ bool DeadBranchElimPass::MarkLiveBlocks(
167167
}
168168

169169
if (simplify) {
170-
modified = true;
171170
conditions_to_simplify.push_back({block, live_lab_id});
172171
stack.push_back(GetParentBlock(live_lab_id));
173172
} else {
@@ -179,24 +178,29 @@ bool DeadBranchElimPass::MarkLiveBlocks(
179178
}
180179
}
181180

182-
// Traverse |conditions_to_simplify in reverse order. This is done so that we
183-
// simplify nested constructs before simplifying the constructs that contain
184-
// them.
181+
// Traverse |conditions_to_simplify| in reverse order. This is done so that
182+
// we simplify nested constructs before simplifying the constructs that
183+
// contain them.
185184
for (auto b = conditions_to_simplify.rbegin();
186185
b != conditions_to_simplify.rend(); ++b) {
187-
SimplifyBranch(b->first, b->second);
186+
modified |= SimplifyBranch(b->first, b->second);
188187
}
189188

190189
return modified;
191190
}
192191

193-
void DeadBranchElimPass::SimplifyBranch(BasicBlock* block,
192+
bool DeadBranchElimPass::SimplifyBranch(BasicBlock* block,
194193
uint32_t live_lab_id) {
195194
Instruction* merge_inst = block->GetMergeInst();
196195
Instruction* terminator = block->terminator();
197196
if (merge_inst && merge_inst->opcode() == SpvOpSelectionMerge) {
198197
if (merge_inst->NextNode()->opcode() == SpvOpSwitch &&
199198
SwitchHasNestedBreak(block->id())) {
199+
if (terminator->NumInOperands() == 2) {
200+
// We cannot remove the branch, and it already has a single case, so no
201+
// work to do.
202+
return false;
203+
}
200204
// We have to keep the switch because it has a nest break, so we
201205
// remove all cases except for the live one.
202206
Instruction::OperandList new_operands;
@@ -231,6 +235,7 @@ void DeadBranchElimPass::SimplifyBranch(BasicBlock* block,
231235
AddBranch(live_lab_id, block);
232236
context()->KillInst(terminator);
233237
}
238+
return true;
234239
}
235240

236241
void DeadBranchElimPass::MarkUnreachableStructuredTargets(
@@ -643,7 +648,8 @@ bool DeadBranchElimPass::SwitchHasNestedBreak(uint32_t switch_header_id) {
643648
if (bb->id() == switch_header_id) {
644649
return true;
645650
}
646-
return (cfg_analysis->ContainingConstruct(inst) == switch_header_id);
651+
return (cfg_analysis->ContainingConstruct(inst) == switch_header_id &&
652+
bb->GetMergeInst() == nullptr);
647653
});
648654
}
649655

source/opt/dead_branch_elim_pass.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,15 @@ class DeadBranchElimPass : public MemPass {
159159
std::unordered_set<BasicBlock*>* blocks_with_back_edges);
160160

161161
// Returns true if there is a brach to the merge node of the selection
162-
// construct |switch_header_id| that is inside a nested selection construct.
162+
// construct |switch_header_id| that is inside a nested selection construct or
163+
// in the header of the nested selection construct.
163164
bool SwitchHasNestedBreak(uint32_t switch_header_id);
164165

165-
// Replaces the terminator of |block| with a branch to |live_lab_id|. The
166-
// merge instruction is deleted or moved as needed to maintain structured
167-
// control flow. Assumes that the StructuredCFGAnalysis is valid for the
168-
// constructs containing |block|.
169-
void SimplifyBranch(BasicBlock* block, uint32_t live_lab_id);
166+
// Return true of the terminator of |block| is successfully replaced with a
167+
// branch to |live_lab_id|. The merge instruction is deleted or moved as
168+
// needed to maintain structured control flow. Assumes that the
169+
// StructuredCFGAnalysis is valid for the constructs containing |block|.
170+
bool SimplifyBranch(BasicBlock* block, uint32_t live_lab_id);
170171
};
171172

172173
} // namespace opt

test/opt/dead_branch_elim_test.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,7 @@ OpFunctionEnd
13781378

13791379
SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
13801380
}
1381+
13811382
TEST_F(DeadBranchElimTest, LeaveContinueBackedgeExtraBlock) {
13821383
const std::string text = R"(
13831384
; CHECK: OpBranch [[header:%\w+]]
@@ -3161,6 +3162,73 @@ OpFunctionEnd
31613162
SinglePassRunAndCheck<DeadBranchElimPass>(before, after, true, true);
31623163
}
31633164

3165+
TEST_F(DeadBranchElimTest, BreakInNestedHeaderWithSingleCase) {
3166+
const std::string text = R"(OpCapability Shader
3167+
%1 = OpExtInstImport "GLSL.std.450"
3168+
OpMemoryModel Logical GLSL450
3169+
OpEntryPoint Fragment %main "main"
3170+
OpExecutionMode %main OriginUpperLeft
3171+
OpSource GLSL 450
3172+
OpName %main "main"
3173+
%void = OpTypeVoid
3174+
%4 = OpTypeFunction %void
3175+
%bool = OpTypeBool
3176+
%uint = OpTypeInt 32 0
3177+
%uint_0 = OpConstant %uint 0
3178+
%8 = OpUndef %bool
3179+
%main = OpFunction %void None %4
3180+
%9 = OpLabel
3181+
OpSelectionMerge %10 None
3182+
OpSwitch %uint_0 %11
3183+
%11 = OpLabel
3184+
OpSelectionMerge %12 None
3185+
OpBranchConditional %8 %10 %12
3186+
%12 = OpLabel
3187+
OpBranch %10
3188+
%10 = OpLabel
3189+
OpReturn
3190+
OpFunctionEnd
3191+
)";
3192+
3193+
SinglePassRunAndCheck<DeadBranchElimPass>(text, text, true, true);
3194+
}
3195+
3196+
TEST_F(DeadBranchElimTest, BreakInNestedHeaderWithTwoCases) {
3197+
const std::string text = R"(
3198+
; CHECK: OpSelectionMerge [[merge:%\w+]] None
3199+
; CHECK-NEXT: OpSwitch %uint_0 [[bb:%\w+\n]]
3200+
OpCapability Shader
3201+
%1 = OpExtInstImport "GLSL.std.450"
3202+
OpMemoryModel Logical GLSL450
3203+
OpEntryPoint Fragment %main "main"
3204+
OpExecutionMode %main OriginUpperLeft
3205+
OpSource GLSL 450
3206+
OpName %main "main"
3207+
%void = OpTypeVoid
3208+
%4 = OpTypeFunction %void
3209+
%bool = OpTypeBool
3210+
%uint = OpTypeInt 32 0
3211+
%uint_0 = OpConstant %uint 0
3212+
%8 = OpUndef %bool
3213+
%main = OpFunction %void None %4
3214+
%9 = OpLabel
3215+
OpSelectionMerge %10 None
3216+
OpSwitch %uint_0 %11 1 %12
3217+
%11 = OpLabel
3218+
OpSelectionMerge %13 None
3219+
OpBranchConditional %8 %10 %13
3220+
%13 = OpLabel
3221+
OpBranch %10
3222+
%12 = OpLabel
3223+
OpBranch %10
3224+
%10 = OpLabel
3225+
OpReturn
3226+
OpFunctionEnd
3227+
)";
3228+
3229+
SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
3230+
}
3231+
31643232
// TODO(greg-lunarg): Add tests to verify handling of these cases:
31653233
//
31663234
// More complex control flow

0 commit comments

Comments
 (0)