Hello, I'm trying to generate an x64 IDIV instruction. I have 2 64bit input values and a 64bit divisor. I tried to iconcat
the inputs and sextend
the divisor to 128 bit values and then use sdiv
and srem
to calculate the results. The problem is that 128bit division seems unimplemented and isle.rs/put_in_reg
panics when trying to assign a 128bit value to a 64bit register. Is there any way to do this cleanly? Or do I have to manually calculate everything? Would that then simplify to a single x64 IDIV in the end?
This topic was moved here from #general > Generate 128bit IDIV by fitzgen (he/him).
I believe you're right that Cranelift doesn't have support for this. Other compilers I've seen implemente 128-bit division with a libcall (e.g. __udivti3
) and that would most likely be Cranelift's own fallback libcall as well.
I don't think that x64 idiv
matches CLIF semantics though because I believe the instruction itself semantically divides a 128-bit integer by a 64-bit integer producing a 64-bit division result and a 64-bit remainer. That doesn't cleanly map to CLIF sdiv
or udiv
because you'd also need an ireduce
on the outside explicitly discarding the upper bits
we could consider adding an ISLE rule to match that case, fwiw
I think it'd look something like
(has_type $I64 (ireduce (sdiv x (has_type $I64 (sextend y)))))
for a pattern here (which may or may not be what you're looking for
it may also require edits to the MInst
enum to support the full generality here, I haven't looked at div myself in a while
So it's not really possible at the moment without modifying Cranelift, right? Maybe I'll try to insert it somehow after Cranelift has finished running.
Right yeah, there's no lowering rules in Cranelift where the upper bits of the division operation are customized. They're always zero or sign-extended from the lower 64-bits
Last updated: Dec 23 2024 at 12:05 UTC