Skip to content

Fix constant propagation of induction variables.#1181

Merged
dnovillo merged 1 commit intoKhronosGroup:masterfrom
dnovillo:const-prop
Jan 8, 2018
Merged

Fix constant propagation of induction variables.#1181
dnovillo merged 1 commit intoKhronosGroup:masterfrom
dnovillo:const-prop

Conversation

@dnovillo
Copy link
Copy Markdown
Contributor

@dnovillo dnovillo commented Jan 8, 2018

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.

@dnovillo dnovillo self-assigned this Jan 8, 2018
%16 = OpLabel

; The Phi should never be considered to have the value %int_0.
; CHECK: OpSLessThan %bool {{%\d+}} %int_10
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be clearer to capture the result id of the phi above and ensure it is used in the less than.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


; This conditional was wrongly converted into an always-true jump due to the
; bad meet evaluation of %27.
; CHECK: OpBranchConditional {{%\d+}} {{%\d+}} {{%\d+}}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, capture the less than result and ensure its the condition of the branch.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// into the |values_| table. Returns SSAPropagator::kVarying.
SSAPropagator::PropStatus MarkInstructionVarying(ir::Instruction* instr);

// Returns true if |id| is a varying value.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name seem slightly confusing. |id| is not a SSA id, but I think that would the intuition. Suggest changing it to |val|.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

@alan-baker alan-baker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor changes.

namespace opt {

bool CCPPass::IsVaryingValue(uint32_t id) const {
return id == std::numeric_limits<uint32_t>::max();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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(); };

// into the |values_| table. Returns SSAPropagator::kVarying.
SSAPropagator::PropStatus MarkInstructionVarying(ir::Instruction* instr);

// Returns true if |id| is a varying value.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

%18 = OpSLessThan %bool %22 %int_10

; This conditional was wrongly converted into an always-true jump due to the
; bad meet evaluation of %27.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

return;
}

// If |use_instr| is a Phi, ignore this edge. Phi instructions can form
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably put this first in the sequence of tests. It might save some time.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Copy Markdown
Contributor Author

@dnovillo dnovillo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. PTAL.

// into the |values_| table. Returns SSAPropagator::kVarying.
SSAPropagator::PropStatus MarkInstructionVarying(ir::Instruction* instr);

// Returns true if |id| is a varying value.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

%16 = OpLabel

; The Phi should never be considered to have the value %int_0.
; CHECK: OpSLessThan %bool {{%\d+}} %int_10
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


; This conditional was wrongly converted into an always-true jump due to the
; bad meet evaluation of %27.
; CHECK: OpBranchConditional {{%\d+}} {{%\d+}} {{%\d+}}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Copy Markdown
Contributor Author

@dnovillo dnovillo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. PTAL.


// Constant manager for the parent IR context. Used to record new constants
// generated during propagation.
analysis::ConstantManager* const_mgr_;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

return;
}

// If |use_instr| is a Phi, ignore this edge. Phi instructions can form
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Copy Markdown
Collaborator

@s-perron s-perron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the if statements look strange. Could you please clarify?

if (it != values_.end()) {
values_[instr->result_id()] = it->second;
return SSAPropagator::kInteresting;
} else if (IsVaryingValue(it->second)) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks odd. If it == values_.end() then load it->second?

Copy link
Copy Markdown
Contributor Author

@dnovillo dnovillo Jan 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator

@s-perron s-perron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

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.
@dnovillo dnovillo merged commit e5560d6 into KhronosGroup:master Jan 8, 2018
@dnovillo
Copy link
Copy Markdown
Contributor Author

dnovillo commented Jan 8, 2018

Re-based and pushed to head as e5560d6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Opt: --ccp (and -O and -Os) generates incorrect code for integer for-loops

4 participants