return SSAPropagator::kInteresting;
}
+ // Conservatively mark this instruction as varying if any input id is varying.
+ if (!instr->WhileEachInId([this](uint32_t* op_id) {
+ auto iter = values_.find(*op_id);
+ if (iter != values_.end() && IsVaryingValue(iter->second)) return false;
+ return true;
+ })) {
+ return MarkInstructionVarying(instr);
+ }
+
// If not, see if there is a least one unknown operand to the instruction. If
// so, we might be able to fold it later.
if (!instr->WhileEachInId([this](uint32_t* op_id) {
}
bool CCPPass::PropagateConstants(ir::Function* fp) {
+ // Mark function parameters as varying.
+ fp->ForEachParam([this](const ir::Instruction* inst) {
+ values_[inst->result_id()] = kVaryingSSAId;
+ });
+
const auto visit_fn = [this](ir::Instruction* instr,
ir::BasicBlock** dest_bb) {
return VisitInstruction(instr, dest_bb);
// module. The values of each OpConstant declaration is the identity
// assignment (i.e., each constant is its own value).
for (const auto& inst : get_module()->types_values()) {
- // Skip specialization constants. Treat undef as varying.
+ // Record compile time constant ids. Treat all other global values as
+ // varying.
if (inst.IsConstant()) {
values_[inst.result_id()] = inst.result_id();
- } else if (inst.opcode() == SpvOpUndef) {
+ } else {
values_[inst.result_id()] = kVaryingSSAId;
}
}
SinglePassRunAndMatch<opt::CCPPass>(text, true);
}
+
+// Test for #1361.
+TEST_F(CCPTest, CompositeConstructOfGlobalValue) {
+ const std::string text = R"(
+; CHECK: [[phi:%\w+]] = OpPhi
+; CHECK-NEXT: OpCompositeExtract {{%\w+}} [[phi]] 0
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %func "func" %in
+%void = OpTypeVoid
+%int = OpTypeInt 32 1
+%bool = OpTypeBool
+%functy = OpTypeFunction %void
+%ptr_int_Input = OpTypePointer Input %int
+%in = OpVariable %ptr_int_Input Input
+%struct = OpTypeStruct %ptr_int_Input %ptr_int_Input
+%struct_null = OpConstantNull %struct
+%func = OpFunction %void None %functy
+%1 = OpLabel
+OpBranch %2
+%2 = OpLabel
+%phi = OpPhi %struct %struct_null %1 %5 %4
+%extract = OpCompositeExtract %ptr_int_Input %phi 0
+OpLoopMerge %3 %4 None
+OpBranch %4
+%4 = OpLabel
+%5 = OpCompositeConstruct %struct %in %in
+OpBranch %2
+%3 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<opt::CCPPass>(text, true);
+}
#endif
} // namespace