Fix constant propagation of induction variables.#1181
Fix constant propagation of induction variables.#1181dnovillo merged 1 commit intoKhronosGroup:masterfrom
Conversation
test/opt/ccp_test.cpp
Outdated
| %16 = OpLabel | ||
|
|
||
| ; The Phi should never be considered to have the value %int_0. | ||
| ; CHECK: OpSLessThan %bool {{%\d+}} %int_10 |
There was a problem hiding this comment.
It might be clearer to capture the result id of the phi above and ensure it is used in the less than.
test/opt/ccp_test.cpp
Outdated
|
|
||
| ; This conditional was wrongly converted into an always-true jump due to the | ||
| ; bad meet evaluation of %27. | ||
| ; CHECK: OpBranchConditional {{%\d+}} {{%\d+}} {{%\d+}} |
There was a problem hiding this comment.
Same here, capture the less than result and ensure its the condition of the branch.
source/opt/ccp_pass.h
Outdated
| // into the |values_| table. Returns SSAPropagator::kVarying. | ||
| SSAPropagator::PropStatus MarkInstructionVarying(ir::Instruction* instr); | ||
|
|
||
| // Returns true if |id| is a varying value. |
There was a problem hiding this comment.
The parameter name seem slightly confusing. |id| is not a SSA id, but I think that would the intuition. Suggest changing it to |val|.
There was a problem hiding this comment.
It actually is an SSA id. I'll clarify. The values table maps SSA ids to SSA ids. I've added a new constant kVaryingSSAId in the code and documented its semantics.
There was a problem hiding this comment.
Recommend renaming the method to IsVaryingValueId.
And the method comment should be
// Returns true if |id| is the sentinel id indicating a varying value. It is never a valid SSA id.
OR: delete the method and test against kVaryingSentinelValueId everywhere. That is probably less readable, though.
source/opt/ccp_pass.cpp
Outdated
| namespace opt { | ||
|
|
||
| bool CCPPass::IsVaryingValue(uint32_t id) const { | ||
| return id == std::numeric_limits<uint32_t>::max(); |
There was a problem hiding this comment.
You should use a named constant value for this, to document and enforce consistency with MarkInstructionVarying.
E.g. enum { kVaryingValueSentinelId = std::numeric_limits<uint32_t>::max(); };
source/opt/ccp_pass.h
Outdated
| // into the |values_| table. Returns SSAPropagator::kVarying. | ||
| SSAPropagator::PropStatus MarkInstructionVarying(ir::Instruction* instr); | ||
|
|
||
| // Returns true if |id| is a varying value. |
There was a problem hiding this comment.
Recommend renaming the method to IsVaryingValueId.
And the method comment should be
// Returns true if |id| is the sentinel id indicating a varying value. It is never a valid SSA id.
OR: delete the method and test against kVaryingSentinelValueId everywhere. That is probably less readable, though.
test/opt/ccp_test.cpp
Outdated
| %18 = OpSLessThan %bool %22 %int_10 | ||
|
|
||
| ; This conditional was wrongly converted into an always-true jump due to the | ||
| ; bad meet evaluation of %27. |
There was a problem hiding this comment.
I think you mean %22 here. The example has changed since you first looked at it.
|
|
||
| ; This Phi should not have all constant arguments: | ||
| ; CHECK: OpPhi %int %int_0 {{%\d+}} {{%\d+}} {{%\d+}} | ||
| %22 = OpPhi %int %int_0 %12 %21 %15 |
There was a problem hiding this comment.
Should test like this:
; CHECK [[phi:%\w+]] = OpPhi %int %int_0 {{%\w+}} [[induction_var:%\w+]] {{\d+}}
Then later as @alan-baker suggests, use [[phi]] in the OpSLessThan.
Also later add
; CHECK: [[induction_var]] = OpIAdd %int [[phi]] %int_1
|
|
||
| // Constant manager for the parent IR context. Used to record new constants | ||
| // generated during propagation. | ||
| analysis::ConstantManager* const_mgr_; |
There was a problem hiding this comment.
You must also update the comment for the values_ member. Should say that an SSA id can map to the kVaryingValueSentinelId to indicate that the id has been proven to be varying.
| return; | ||
| } | ||
|
|
||
| // If |use_instr| is a Phi, ignore this edge. Phi instructions can form |
There was a problem hiding this comment.
I'd probably put this first in the sequence of tests. It might save some time.
source/opt/ccp_pass.h
Outdated
| // into the |values_| table. Returns SSAPropagator::kVarying. | ||
| SSAPropagator::PropStatus MarkInstructionVarying(ir::Instruction* instr); | ||
|
|
||
| // Returns true if |id| is a varying value. |
There was a problem hiding this comment.
It actually is an SSA id. I'll clarify. The values table maps SSA ids to SSA ids. I've added a new constant kVaryingSSAId in the code and documented its semantics.
test/opt/ccp_test.cpp
Outdated
| %16 = OpLabel | ||
|
|
||
| ; The Phi should never be considered to have the value %int_0. | ||
| ; CHECK: OpSLessThan %bool {{%\d+}} %int_10 |
test/opt/ccp_test.cpp
Outdated
|
|
||
| ; This conditional was wrongly converted into an always-true jump due to the | ||
| ; bad meet evaluation of %27. | ||
| ; CHECK: OpBranchConditional {{%\d+}} {{%\d+}} {{%\d+}} |
|
|
||
| // Constant manager for the parent IR context. Used to record new constants | ||
| // generated during propagation. | ||
| analysis::ConstantManager* const_mgr_; |
| return; | ||
| } | ||
|
|
||
| // If |use_instr| is a Phi, ignore this edge. Phi instructions can form |
s-perron
left a comment
There was a problem hiding this comment.
One of the if statements look strange. Could you please clarify?
source/opt/ccp_pass.cpp
Outdated
| if (it != values_.end()) { | ||
| values_[instr->result_id()] = it->second; | ||
| return SSAPropagator::kInteresting; | ||
| } else if (IsVaryingValue(it->second)) { |
There was a problem hiding this comment.
This looks odd. If it == values_.end() then load it->second?
There was a problem hiding this comment.
Fixed, thanks. The case can actually never happen because the propagator is guaranteed to always have generated a value of the RHS of an OpCopyObject (it works in def-use and dominator order, after all). However, it would've failed to mark the LHS varying if the RHS was varying and would mark the instruction interesting, causing an additional go around the propagator.
This fixes KhronosGroup#1143. When an instruction transitions from constant to bottom (varying) in the lattice, we were telling the propagator that the instruction was varying, but never updating the actual value in the values table. This led to incorrect value substitutions at the end of propagation. The patch also re-enables CCP in -O and -Os.
|
Re-based and pushed to head as e5560d6. |
This fixes #1143.
When an instruction transitions from constant to bottom (varying) in the
lattice, we were telling the propagator that the instruction was
varying, but never updating the actual value in the values table.
This led to incorrect value substitutions at the end of propagation.