| 127 | } |
| 128 | |
| 129 | SSAPropagator::PropStatus CCPPass::VisitAssignment(Instruction* instr) { |
| 130 | assert(instr->result_id() != 0 && |
| 131 | "Expecting an instruction that produces a result"); |
| 132 | |
| 133 | // If this is a copy operation, and the RHS is a known constant, assign its |
| 134 | // value to the LHS. |
| 135 | if (instr->opcode() == spv::Op::OpCopyObject) { |
| 136 | uint32_t rhs_id = instr->GetSingleWordInOperand(0); |
| 137 | auto it = values_.find(rhs_id); |
| 138 | if (it != values_.end()) { |
| 139 | if (IsVaryingValue(it->second)) { |
| 140 | return MarkInstructionVarying(instr); |
| 141 | } else { |
| 142 | uint32_t new_val = ComputeLatticeMeet(instr, it->second); |
| 143 | values_[instr->result_id()] = new_val; |
| 144 | return IsVaryingValue(new_val) ? SSAPropagator::kVarying |
| 145 | : SSAPropagator::kInteresting; |
| 146 | } |
| 147 | } |
| 148 | return SSAPropagator::kNotInteresting; |
| 149 | } |
| 150 | |
| 151 | // Instructions with a RHS that cannot produce a constant are always varying. |
| 152 | if (!instr->IsFoldable()) { |
| 153 | return MarkInstructionVarying(instr); |
| 154 | } |
| 155 | |
| 156 | // See if the RHS of the assignment folds into a constant value. |
| 157 | auto map_func = [this](uint32_t id) { |
| 158 | auto it = values_.find(id); |
| 159 | if (it == values_.end() || IsVaryingValue(it->second)) { |
| 160 | return id; |
| 161 | } |
| 162 | return it->second; |
| 163 | }; |
| 164 | Instruction* folded_inst = |
| 165 | context()->get_instruction_folder().FoldInstructionToConstant(instr, |
| 166 | map_func); |
| 167 | |
| 168 | if (folded_inst && context()->id_overflow()) { |
| 169 | return SSAPropagator::kFailed; |
| 170 | } |
| 171 | if (folded_inst != nullptr) { |
| 172 | // We do not want to change the body of the function by adding new |
| 173 | // instructions. When folding we can only generate new constants. |
| 174 | assert((folded_inst->IsConstant() || |
| 175 | IsSpecConstantInst(folded_inst->opcode())) && |
| 176 | "CCP is only interested in constant values."); |
| 177 | uint32_t new_val = ComputeLatticeMeet(instr, folded_inst->result_id()); |
| 178 | values_[instr->result_id()] = new_val; |
| 179 | return IsVaryingValue(new_val) ? SSAPropagator::kVarying |
| 180 | : SSAPropagator::kInteresting; |
| 181 | } |
| 182 | |
| 183 | // Conservatively mark this instruction as varying if any input id is varying. |
| 184 | if (!instr->WhileEachInId([this](uint32_t* op_id) { |
| 185 | auto iter = values_.find(*op_id); |
| 186 | if (iter != values_.end() && IsVaryingValue(iter->second)) return false; |
nothing calls this directly
no test coverage detected