uint32_t pred_val_id = it->second;
const analysis::Constant* c = const_mgr_->FindDeclaredConstant(pred_val_id);
assert(c && "Expected to find a constant declaration for a known value.");
- const analysis::BoolConstant* val = c->AsBoolConstant();
- dest_label = val->value() ? instr->GetSingleWordOperand(1)
- : instr->GetSingleWordOperand(2);
+ // Undef values should have returned as varying above.
+ assert(c->AsBoolConstant() || c->AsNullConstant());
+ if (c->AsNullConstant()) {
+ dest_label = instr->GetSingleWordOperand(2u);
+ } else {
+ const analysis::BoolConstant* val = c->AsBoolConstant();
+ dest_label = val->value() ? instr->GetSingleWordOperand(1)
+ : instr->GetSingleWordOperand(2);
+ }
} else {
// For an OpSwitch, extract the value taken by the switch selector and check
// which of the target literals it matches. The branch associated with that
const analysis::Constant* c =
const_mgr_->FindDeclaredConstant(select_val_id);
assert(c && "Expected to find a constant declaration for a known value.");
- const analysis::IntConstant* val = c->AsIntConstant();
+ // TODO: support 64-bit integer switches.
+ uint32_t constant_cond = 0;
+ if (const analysis::IntConstant* val = c->AsIntConstant()) {
+ constant_cond = val->words()[0];
+ } else {
+ // Undef values should have returned varying above.
+ assert(c->AsNullConstant());
+ constant_cond = 0;
+ }
// Start assuming that the selector will take the default value;
dest_label = instr->GetSingleWordOperand(1);
for (uint32_t i = 2; i < instr->NumOperands(); i += 2) {
- if (val->words()[0] == instr->GetSingleWordOperand(i)) {
+ if (constant_cond == instr->GetSingleWordOperand(i)) {
dest_label = instr->GetSingleWordOperand(i + 1);
break;
}
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
SinglePassRunToBinary<opt::CCPPass>(text, true);
}
+
+TEST_F(CCPTest, NullBranchCondition) {
+ const std::string text = R"(
+; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1
+; CHECK: [[int2:%\w+]] = OpConstant {{%\w+}} 2
+; CHECK: OpIAdd {{%\w+}} [[int1]] [[int2]]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %func "func"
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%null = OpConstantNull %bool
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%functy = OpTypeFunction %void
+%func = OpFunction %void None %functy
+%1 = OpLabel
+OpSelectionMerge %2 None
+OpBranchConditional %null %2 %3
+%3 = OpLabel
+OpBranch %2
+%2 = OpLabel
+%phi = OpPhi %int %int_1 %1 %int_2 %3
+%add = OpIAdd %int %int_1 %phi
+OpReturn
+OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<opt::CCPPass>(text, true);
+}
+
+TEST_F(CCPTest, UndefBranchCondition) {
+ const std::string text = R"(
+; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1
+; CHECK: [[phi:%\w+]] = OpPhi
+; CHECK: OpIAdd {{%\w+}} [[int1]] [[phi]]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %func "func"
+%void = OpTypeVoid
+%bool = OpTypeBool
+%int = OpTypeInt 32 1
+%undef = OpUndef %bool
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%functy = OpTypeFunction %void
+%func = OpFunction %void None %functy
+%1 = OpLabel
+OpSelectionMerge %2 None
+OpBranchConditional %undef %2 %3
+%3 = OpLabel
+OpBranch %2
+%2 = OpLabel
+%phi = OpPhi %int %int_1 %1 %int_2 %3
+%add = OpIAdd %int %int_1 %phi
+OpReturn
+OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<opt::CCPPass>(text, true);
+}
+
+TEST_F(CCPTest, NullSwitchCondition) {
+ const std::string text = R"(
+; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1
+; CHECK: [[int2:%\w+]] = OpConstant {{%\w+}} 2
+; CHECK: OpIAdd {{%\w+}} [[int1]] [[int2]]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %func "func"
+%void = OpTypeVoid
+%int = OpTypeInt 32 1
+%null = OpConstantNull %int
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%functy = OpTypeFunction %void
+%func = OpFunction %void None %functy
+%1 = OpLabel
+OpSelectionMerge %2 None
+OpSwitch %null %2 0 %3
+%3 = OpLabel
+OpBranch %2
+%2 = OpLabel
+%phi = OpPhi %int %int_1 %1 %int_2 %3
+%add = OpIAdd %int %int_1 %phi
+OpReturn
+OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<opt::CCPPass>(text, true);
+}
+
+TEST_F(CCPTest, UndefSwitchCondition) {
+ const std::string text = R"(
+; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1
+; CHECK: [[phi:%\w+]] = OpPhi
+; CHECK: OpIAdd {{%\w+}} [[int1]] [[phi]]
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %func "func"
+%void = OpTypeVoid
+%int = OpTypeInt 32 1
+%undef = OpUndef %int
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%functy = OpTypeFunction %void
+%func = OpFunction %void None %functy
+%1 = OpLabel
+OpSelectionMerge %2 None
+OpSwitch %undef %2 0 %3
+%3 = OpLabel
+OpBranch %2
+%2 = OpLabel
+%phi = OpPhi %int %int_1 %1 %int_2 %3
+%add = OpIAdd %int %int_1 %phi
+OpReturn
+OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<opt::CCPPass>(text, true);
+}
#endif
} // namespace