abrown opened PR #3682 from isle-select to main:
This change ports CLIF's
selectinstruction to ISLE for x64.
abrown requested fitzgen for a review on PR #3682.
abrown requested cfallin for a review on PR #3682.
abrown updated PR #3682 from isle-select to main.
abrown updated PR #3682 from isle-select to main.
abrown submitted PR review.
abrown created PR review comment:
@cfallin, I believe this test is incorrect--both previously and with the current lowering. By first moving
%xmm0to%xmm1withmovaps, the flag-checking jumps really have no effect (they just move almost the same data again). Thoughts?
abrown submitted PR review.
abrown created PR review comment:
Zooming out: not only was the
FloatCC::Equallowering incorrect for FP, but there are no tests (that I can see) that exercise the other variants.
abrown edited PR review comment.
cfallin created PR review comment:
This overwrites
dstfrom above, I think -- it seems we want the first cmove to write a tmp, andalternativein the second to be that tmp? So then we have the equivalent ofcmove(cc1, a, cmove(cc2, b, alternative)).
cfallin submitted PR review.
fitzgen submitted PR review.
fitzgen submitted PR review.
fitzgen created PR review comment:
Could this have a comment describing what it is?
fitzgen created PR review comment:
The
is_regprefix makes me think that these will extract fromRegs but they actually will extract fromTypes. Can we rename these tois_{xmm,gpr}_typeinstead perhaps?
fitzgen created PR review comment:
So this is
dst = if cc1 || cc2 { consequent } else { alternative }right?
Could we maybe add that pseudocode to the comments for these variants? I think that will be very helpful for future readers.
fitzgen created PR review comment:
Sounds like we need some runtests for these
selects, rather than just compile tests.
fitzgen created PR review comment:
;;;; Rules for `select` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; CLIF `select` instructions receive a testable argument (i.e. boolean or
fitzgen created PR review comment:
Alternatively, we could have them operate on
Regs and keep the current names. Then we would just have to adjust the call sites appropriately, which I think would be possible for all call sites since they also haveRegs available.
abrown updated PR #3682 from isle-select to main.
abrown updated PR #3682 from isle-select to main.
abrown updated PR #3682 from isle-select to main.
abrown updated PR #3682 from isle-select to main.
abrown has marked PR #3682 as ready for review.
abrown updated PR #3682 from isle-select to main.
fitzgen submitted PR review.
fitzgen submitted PR review.
fitzgen created PR review comment:
I think these hard-coded sizes are fine, since we know an
i128is represented with twoi64GPRs.
fitzgen created PR review comment:
Doing the
emithere is actually unsafe because nothing is guaranteeing that
- we just emitted the flags producer before this
- nothing else is emitted after the flags producer and before this flags consumer that clobbers the flags
What we want to do is return two
ConsumesFlagshere that we can then pass intowith_flags_2along with aFlagsProducer.ISLE doesn't have tuple/fixed-size-arrays support, so we will have to define an extern type for this.
But! The other rule for
cmove_from_valuesfor when it is a single-register value emits only oneConsumesFlags, so I think we actually want an extern type that is either one or twoConsumesFlags. I think we can just use aSmallVec<[ConsumesFlags; 2]>.
fitzgen created PR review comment:
I think that
cmove_from_valuesshould take theseValueRegsinstead ofValues. This lets us reuse it in places where we've already put the values into registers.(decl cmove_from_values (Type CC ValueRegs ValueRegs) ConsumesFlags) (rule (cmove_from_vlaue $I128 cc consequent alternative) ...) ```` ~~~
fitzgen created PR review comment:
These rules look great, thanks!
fitzgen created PR review comment:
Note that we will want a
with_flags_*variant that takes theSmallVec<[ConsumesFlags; 2]>as well, and it will probably have to be implemented in external Rust code so it can loop over eachConsumesFlagsin the small vec.
fitzgen created PR review comment:
We need to have an extractor that ensure that this is a single-register type, as discussed before:
(rule (cmove_from_values (is_single_register_type ty) cc consequent alternative)
fitzgen created PR review comment:
Nitpick: we should clarify how we are combining the multiple flags here:
;; Helper for creating `cmove` instructions with the logical OR of multiple ;; flags. Note that these instructions will always result in more than one ;; emitted x86 instruction.
abrown submitted PR review.
abrown created PR review comment:
The downside to that is that it bloats the rules in
lower.isle; can we do this refactoring in a future PR or issue, e.g., the next time cmove is used?
abrown updated PR #3682 from isle-select to main.
abrown submitted PR review.
abrown created PR review comment:
This sounds like a lot of new infrastructure to build and this PR may already have enough of that. The current lowering rules perform the same unsafe emission as this PR. Can't this be done afterwards?
abrown updated PR #3682 from isle-select to main.
abrown submitted PR review.
abrown created PR review comment:
Ok, I added an extractor that just checks that the type is not
I128in fb334e1--can you take a look at that?
abrown updated PR #3682 from isle-select to main.
fitzgen submitted PR review.
fitzgen created PR review comment:
Sure, that works for me.
fitzgen submitted PR review.
fitzgen created PR review comment:
The current lowering rules for
selectare written in Rust, so it isn't really comparable. It would be one thing if thisemitwas near theemitfor the flags-producer instruction and theemitfor the other flags-consuming instruction, but it isn't. It isn't even clear to me, reading this code, that the instructions will always be emitted in the correct order!It seems to me that the order of evaluation will be something like
- construct
FlagsProducer(do not emit it)- call this constructor
- emit first cmove
- construct FlagsConsumer with the second cmove
- call a
with_flagsvariant with the constructedFlagsProducerandFlagsConsumer
- emit the producer
- emit the consumer
If that is actually how things end up evaluating, then we would get
cmove; test/cmp; cmoveinstead oftest/cmp; cmove; cmove.It looks like we aren't testing
selectwithi128s yet (since you have only ported floating pointselects so far). But this is exactly the kind bug I want to avoid with a dedicatedwith_flags_*variant that takesSmallVec<[ConsumesFlags; 2]>, as described above.I really think we should fix this issue before landing this PR, or change this PR to not define and use
cmove_from_valuesand instead use plaincmove(which will work for all the single-register values forselectthat are are currently supported in ISLE).
cfallin updated PR #3682 from isle-select to main.
abrown submitted PR review.
abrown created PR review comment:
Ok, @cfallin and I (but mostly @cfallin), worked on this a bit. The unpolished results are in 667935f--@fitzgen, thoughts?
fitzgen submitted PR review.
fitzgen created PR review comment:
The extensions to
with_flags,ProducesFlags, andConsumesFlagslook good!
fitzgen submitted PR review.
fitzgen created PR review comment:
Looks good!
abrown updated PR #3682 from isle-select to main.
abrown updated PR #3682 from isle-select to main.
abrown requested fitzgen for a review on PR #3682.
abrown requested cfallin for a review on PR #3682.
cfallin submitted PR review.
fitzgen submitted PR review.
abrown updated PR #3682 from isle-select to main.
abrown updated PR #3682 from isle-select to main.
abrown merged PR #3682.
Last updated: Dec 13 2025 at 19:03 UTC