Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

[codegen] legalize imul for 64-bit and 128-bit operands #1109

Merged
merged 1 commit into from Oct 10, 2019

Conversation

ryzokuken
Copy link
Contributor

Add a legalization that legalizes imul.I64 for 32-bit ISAs.

Refs: bnjbvr/cranelift-x86#4

/cc @wingo @caitp

@bnjbvr PTAL.

There's one small problem though, there's no existing way to handle carry output in imul. Good news? According to https://www.felixcloutier.com/x86/imul, imul does set the appropriate flags on x86-32 atleast, so I can just add an alternate imul_ifcout instruction, I guess? wdyt?

@ryzokuken
Copy link
Contributor Author

@bjorn3 this is exactly what I needed! Thanks.

@bjorn3
Copy link
Contributor

bjorn3 commented Oct 3, 2019

On x86 you can directly use x86_u/smulx to get both low and hi bits at once:

https://github.com/CraneStation/cranelift/blob/6ed06a1e8e428aedb7adfd825b131abb9a7a3d15/cranelift-codegen/meta/src/isa/x86/legalize.rs#L85

Copy link
Contributor

@bjorn3 bjorn3 left a comment

Choose a reason for hiding this comment

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

Is it just me, or does it need to be more complex. compiler-builtins uses 18 lines to implement this: https://github.com/rust-lang/compiler-builtins/blob/462b73c1fe1f67a62223a3ccf830f02a2571c016/src/int/mul.rs#L7-L26

// TODO(ryzokuken): explore the perf diff w/ x86_umulx and consider have a
// separate legalization for x86.
narrow.legalize(
def!(a = imul.I64(x, y)),
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please also implement this and further i64 -> i32 narrowing legalizations for i128?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I could legalize imul.ty in terms of imul.ty_half which is good, but I guess I'll need to legalize umulhi for I64 for that too?

Copy link
Contributor

@bjorn3 bjorn3 Oct 3, 2019

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

so umulhi is defined for x86_64. I guess it's okay to add the legalization since it's not defined for any other ISA anyway...

@ryzokuken
Copy link
Contributor Author

@bjorn3 @bnjbvr done, with tests and all.

@ryzokuken ryzokuken changed the title [codegen] legalize imul.I64 for 32-bit ISAs [codegen] legalize imul for 64-bit and 128-bit operands Oct 3, 2019
@ryzokuken ryzokuken changed the title [codegen] legalize imul for 64-bit and 128-bit operands [codegen] legalize imul for 64-bit and 128-bit operands Oct 3, 2019
@bjorn3
Copy link
Contributor

bjorn3 commented Oct 3, 2019

Could you please add a run test with very large 128bit ints, say 0x98fe985354ab06f2347ac4503f1e24 and 0x42e1f3054ca7432f606ba453589ef89? It should return 0xa363ce3b6849f307be2044b2742ebd44. They have to be very large, so that no parts are zero and 128bit, so the legalizations actually get used on 64bit archs.

Tested using:

fn main() {
    println!("{:x}", 0x98fe985354ab06f2347ac4503f1e24u128.wrapping_mul(0x42e1f3054ca7432f606ba453589ef89u128));
}

Note: I just typed some random numbers and letters to generate those numbers.

@ryzokuken
Copy link
Contributor Author

ryzokuken commented Oct 3, 2019

@bjorn3 I added a test, but it'll need both iconst.I128 (non existent, but should be fairly straightforward after #1081) and icmp_imm.I128 (#1081) in order to pass...

@bjorn3
Copy link
Contributor

bjorn3 commented Oct 3, 2019

iconst.i64 + iconcat.i128 could be used instead of iconst.i128 for now.

@ryzokuken
Copy link
Contributor Author

@bjorn3 FAIL filetests/isa/x86/imul-i128.clif: 8: i128 is not a valid typevar for iconcat 😅

@bjorn3
Copy link
Contributor

bjorn3 commented Oct 4, 2019

It will probably work when leaving .i128 out.

@ryzokuken
Copy link
Contributor Author

@bjorn3 the current test has issues: FAIL filetests/isa/x86/imul-i128.clif: 13: Too many hexadecimal digits. I guess it'll work once we have landed #1081.

@bjorn3
Copy link
Contributor

bjorn3 commented Oct 8, 2019

Immediate values are limited to 64bit as 128bit would drastically increase memory usage. You could use the non imm variant of icmp instead.

@ryzokuken
Copy link
Contributor Author

@bjorn3 looks like this will now work as soon as icmp is merged. Current error:

FAIL filetests/isa/x86/imul-i128.clif: run(%test_imul_i128):
Verifier errors:
- inst11: v5 is a ghost value used by a real [Op1ret#c3] instruction

Copy link
Member

@bnjbvr bnjbvr left a comment

Choose a reason for hiding this comment

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

Thanks, looking nice!

cranelift-codegen/meta/src/shared/legalize.rs Outdated Show resolved Hide resolved
cranelift-codegen/meta/src/shared/legalize.rs Outdated Show resolved Hide resolved
Add a legalization that legalizes imul.I64 for 32-bit ISAs and imul.I128
for 64-bit (and subsequently 32-bit) ISAs.

Refs: bnjbvr/cranelift-x86#4
@bnjbvr bnjbvr merged commit d13e14b into bytecodealliance:master Oct 10, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants