cfallin opened PR #14295 from cfallin:fix-second-result-etor to bytecodealliance:main:
In #14293, a test case that uses the first result (i.e., the product) of an
smul_overflowoperator as a condition (e.g. as part oficmp eqcomparing to zero) incorrectly triggers the lowering rule I added in #14254 which was meant to match only compare-to-zero on the second (overflow) result.This was a result if a fairly subtle issue involving auto-conversions in ISLE. I had written
(rule (is_nonzero (second_result umul @ (smul_overflow ...))) ...)where the intent was to match an
is_nonzero(which is a helper term) lowering with the second result (overflow flag) of thesmul_overflow.
second_resulthas a term signature(Value) Inst, in other words it takes anInstand returns anOption<Value>.is_nonzerotakes aValue. So we auto-convert theValuein the first arg position ofis_nonzerto anInst; that usesdef_inst, which looks up the defining instruction of the given value. Thensecond_resulttakes thatInstand gives the second value. But then the next level,(smul_overflow ...), *again* usesdef_instand goes from the (second result)Value` back to the inst and matches.In other words, we're too permissive with the autoconversions on
ValuetoInst; all of this was designed at a time when we more or less only handled single-result instructions with any nontrivial lowering rule, so the two were mostly interchangeable. The handling for the overflow-flag ops changes that.The specific step in that chain above that is unambiguously wrong wrt intent is (first result)
Value->Inst->second_resultmatching. So this PR instead introducesis_second_resultthat isValue->Option<Value>and matches only when the specificValueis the second result of an instruction.This does have me thinking a bit more about the role that the
Value->Instautoconvert matching plays. It is absolutely essential to the ergonomics of ISLE: without it, we couldn't write(rule (lower (iadd (imul a b) c)) ...)because
iadd's args areValues and we need to match back to anInstforimul. But we also have cases like the one in this PR where we really shouldn't be so permissive. Perhaps we want a kind of type modifier (=Value?) that means "exactly this type, not autoconverted". I'll bring this up in the Cranelift meeting this week.Fixes #14293.
<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease review the Bytecode Alliance's AI tool usage policy at
https://github.com/bytecodealliance/governance/blob/main/AI_TOOL_POLICY.mdPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
cfallin requested alexcrichton for a review on PR #14295.
cfallin requested wasmtime-compiler-reviewers for a review on PR #14295.
cfallin edited PR #14295:
In #14293, a test case that uses the first result (i.e., the product) of an
smul_overflowoperator as a condition (e.g. as part oficmp eqcomparing to zero) incorrectly triggers the lowering rule I added in #14254 which was meant to match only compare-to-zero on the second (overflow) result.This was a result of a fairly subtle issue involving auto-conversions in ISLE. I had written
(rule (is_nonzero (second_result umul @ (smul_overflow ...))) ...)where the intent was to match an
is_nonzero(which is a helper term) lowering with the second result (overflow flag) of thesmul_overflow.
second_resulthas a term signature(Value) Inst, in other words it takes anInstand returns anOption<Value>.is_nonzerotakes aValue. So we auto-convert theValuein the first arg position ofis_nonzerto anInst; that usesdef_inst, which looks up the defining instruction of the given value. Thensecond_resulttakes thatInstand gives the second value. But then the next level,(smul_overflow ...), *again* usesdef_instand goes from the (second result)Value` back to the inst and matches.In other words, we're too permissive with the autoconversions on
ValuetoInst; all of this was designed at a time when we more or less only handled single-result instructions with any nontrivial lowering rule, so the two were mostly interchangeable. The handling for the overflow-flag ops changes that.The specific step in that chain above that is unambiguously wrong wrt intent is (first result)
Value->Inst->second_resultmatching. So this PR instead introducesis_second_resultthat isValue->Option<Value>and matches only when the specificValueis the second result of an instruction.This does have me thinking a bit more about the role that the
Value->Instautoconvert matching plays. It is absolutely essential to the ergonomics of ISLE: without it, we couldn't write(rule (lower (iadd (imul a b) c)) ...)because
iadd's args areValues and we need to match back to anInstforimul. But we also have cases like the one in this PR where we really shouldn't be so permissive. Perhaps we want a kind of type modifier (=Value?) that means "exactly this type, not autoconverted". I'll bring this up in the Cranelift meeting this week.Fixes #14293.
<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease review the Bytecode Alliance's AI tool usage policy at
https://github.com/bytecodealliance/governance/blob/main/AI_TOOL_POLICY.mdPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
cfallin edited PR #14295:
In #14293, a test case that uses the first result (i.e., the product) of an
smul_overflowoperator as a condition (e.g. as part oficmp eqcomparing to zero) incorrectly triggers the lowering rule I added in #14254 which was meant to match only compare-to-zero on the second (overflow) result.This was a result of a fairly subtle issue involving auto-conversions in ISLE. I had written
(rule (is_nonzero (second_result umul @ (smul_overflow ...))) ...)where the intent was to match an
is_nonzero(which is a helper term) lowering with the second result (overflow flag) of thesmul_overflow.
second_resulthas a term signature(Value) Inst, in other words it takes anInstand returns anOption<Value>.is_nonzerotakes aValue. So we auto-convert theValuein the first arg position ofis_nonzerto anInst; that usesdef_inst, which looks up the defining instruction of the given value. Thensecond_resulttakes thatInstand gives the second value. But then the next level,(smul_overflow ...), again usesdef_instand goes from the (second result)Valueback to the inst and matches.In other words, we're too permissive with the autoconversions on
ValuetoInst; all of this was designed at a time when we more or less only handled single-result instructions with any nontrivial lowering rule, so the two were mostly interchangeable. The handling for the overflow-flag ops changes that.The specific step in that chain above that is unambiguously wrong wrt intent is (first result)
Value->Inst->second_resultmatching. So this PR instead introducesis_second_resultthat isValue->Option<Value>and matches only when the specificValueis the second result of an instruction.This does have me thinking a bit more about the role that the
Value->Instautoconvert matching plays. It is absolutely essential to the ergonomics of ISLE: without it, we couldn't write(rule (lower (iadd (imul a b) c)) ...)because
iadd's args areValues and we need to match back to anInstforimul. But we also have cases like the one in this PR where we really shouldn't be so permissive. Perhaps we want a kind of type modifier (=Value?) that means "exactly this type, not autoconverted". I'll bring this up in the Cranelift meeting this week.Fixes #14293.
<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease review the Bytecode Alliance's AI tool usage policy at
https://github.com/bytecodealliance/governance/blob/main/AI_TOOL_POLICY.mdPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
github-actions[bot] added the label cranelift on PR #14295.
github-actions[bot] added the label cranelift:area:aarch64 on PR #14295.
github-actions[bot] added the label cranelift:area:machinst on PR #14295.
github-actions[bot] added the label cranelift:area:x64 on PR #14295.
alexcrichton commented on PR #14295:
I don't really understand what's going on here, and I also didn't catch this in prior review, so I'm going to swap in @fitzgen
alexcrichton unassigned alexcrichton from PR #14295 Fix subtle ISLE extractor issue leading to incorrect matching in *mul_overflow lowering..
alexcrichton requested fitzgen for a review on PR #14295.
:thumbs_up: fitzgen submitted PR review:
LGTM modulo comments below
:speech_balloon: fitzgen created PR review comment:
Seems like we could probably minimize this test case a bit
:speech_balloon: fitzgen created PR review comment:
Do we still even want to have
second_result? Is anything still using it that couldn't move tois_second_result?
:speech_balloon: fitzgen created PR review comment:
self.lower_ctx.dfg().inst_results(inst).get(1) == Some(&val)is a little shorter and more clear to me
:memo: cfallin submitted PR review.
:speech_balloon: cfallin created PR review comment:
Yes, it's still used elsewhere, specifically to get the
Valuefor the second result from the actualInstinlower(where we have a boundInst, notValue) onuadd_overflow. Will leave for now but happy to consider refactors in followup along with the auto-conversion question.
cfallin updated PR #14295.
:memo: cfallin submitted PR review.
:speech_balloon: cfallin created PR review comment:
Done!
:memo: cfallin submitted PR review.
:speech_balloon: cfallin created PR review comment:
Done!
cfallin has enabled auto merge for PR #14295.
cfallin added PR #14295 Fix subtle ISLE extractor issue leading to incorrect matching in *mul_overflow lowering. to the merge queue
:check: cfallin merged PR #14295.
cfallin removed PR #14295 Fix subtle ISLE extractor issue leading to incorrect matching in *mul_overflow lowering. from the merge queue
Last updated: Sep 20 2026 at 18:08 UTC