Skip to content

Commit ccaa726

Browse files
committed
x64: convert scalar multiplications
1 parent 7c2399a commit ccaa726

File tree

8 files changed

+105
-87
lines changed

8 files changed

+105
-87
lines changed

cranelift/codegen/src/isa/x64/inst.isle

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,12 +1810,18 @@
18101810
(extern extractor is_imm8_xmm is_imm8_xmm)
18111811
(decl is_simm8 (i8) GprMemImm)
18121812
(extern extractor is_simm8 is_simm8)
1813+
(decl is_rust_simm8 (i8) i32)
1814+
(extern extractor is_rust_simm8 is_rust_simm8)
18131815
(decl is_imm16 (u16) GprMemImm)
18141816
(extern extractor is_imm16 is_imm16)
1817+
(decl is_rust_imm16 (u16) i32)
1818+
(extern extractor is_rust_imm16 is_rust_imm16)
18151819
(decl is_simm16 (i16) GprMemImm)
18161820
(extern extractor is_simm16 is_simm16)
18171821
(decl is_imm32 (u32) GprMemImm)
18181822
(extern extractor is_imm32 is_imm32)
1823+
(decl is_rust_imm32 (u32) i32)
1824+
(extern extractor is_rust_imm32 is_rust_imm32)
18191825
(decl is_simm32 (i32) GprMemImm)
18201826
(extern extractor is_simm32 is_simm32)
18211827
(decl is_gpr (Gpr) GprMemImm)
@@ -2693,6 +2699,8 @@
26932699
(decl asm_produce_flags (AssemblerOutputs) ProducesFlags)
26942700
(rule (asm_produce_flags (AssemblerOutputs.RetGpr inst gpr))
26952701
(ProducesFlags.ProducesFlagsReturnsResultWithConsumer inst gpr))
2702+
(rule (asm_produce_flags (AssemblerOutputs.RetValueRegs inst regs))
2703+
(ProducesFlags.ProducesFlagsReturnsResultWithConsumer inst (value_regs_get_gpr regs 0)))
26962704

26972705
;; Other operations consume _and_ produce flags--"chaining".
26982706
(type ChainFlagsOp (enum (Adc) (Sbb)))
@@ -2883,15 +2891,18 @@
28832891

28842892

28852893
;; Helper for creating `mul` instructions or `imul` instructions (depending
2886-
;; on `signed`)
2887-
(decl x64_mul (Type bool Gpr GprMem) ValueRegs)
2888-
(rule (x64_mul ty signed src1 src2)
2889-
(let ((dst_lo WritableGpr (temp_writable_gpr))
2890-
(dst_hi WritableGpr (temp_writable_gpr))
2891-
(size OperandSize (raw_operand_size_of_type ty))
2892-
(_ Unit (emit (MInst.Mul size signed src1 src2 dst_lo dst_hi))))
2893-
(value_gprs dst_lo dst_hi)))
2894+
;; on `signed`). For the 8-bit rules, see `x64_mul8`.
2895+
(decl x64_mul_raw (Type bool Gpr GprMem) AssemblerOutputs)
2896+
(rule (x64_mul_raw $I16 false src1 src2) (x64_mulw_m_raw src1 src2))
2897+
(rule (x64_mul_raw $I32 false src1 src2) (x64_mull_m_raw src1 src2))
2898+
(rule (x64_mul_raw $I64 false src1 src2) (x64_mulq_m_raw src1 src2))
2899+
(rule (x64_mul_raw $I16 true src1 src2) (x64_imulw_m_raw src1 src2))
2900+
(rule (x64_mul_raw $I32 true src1 src2) (x64_imull_m_raw src1 src2))
2901+
(rule (x64_mul_raw $I64 true src1 src2) (x64_imulq_m_raw src1 src2))
28942902

2903+
(decl x64_mul (Type bool Gpr GprMem) ValueRegs)
2904+
(rule 0 (x64_mul ty signed src1 src2)
2905+
(emit_ret_value_regs (x64_mul_raw ty signed src1 src2)))
28952906
;; Special case the `mulx` pattern with the BMI2 instruction set.
28962907
(rule 1 (x64_mul (ty_32_or_64 ty) false src1 src2)
28972908
(if-let true (use_bmi2))
@@ -2908,49 +2919,43 @@
29082919
(_ Unit (emit (MInst.MulX size src1 src2 (writable_invalid_gpr) dst))))
29092920
dst))
29102921

2922+
(decl x64_mul_lo_with_flags_paired (Type bool Gpr GprMem) ProducesFlags)
2923+
(rule (x64_mul_lo_with_flags_paired ty signed src1 src2)
2924+
(asm_produce_flags (x64_mul_raw ty signed src1 src2)))
2925+
29112926
;; Get the invalid register as writable
29122927
(decl writable_invalid_gpr () WritableGpr)
29132928
(extern constructor writable_invalid_gpr writable_invalid_gpr)
29142929

2915-
;; Helper for creating `mul` instructions or `imul` instructions (depending
2916-
;; on `signed`) for 8-bit operands.
2917-
(decl x64_mul8 (bool Gpr GprMem) Gpr)
2918-
(rule (x64_mul8 signed src1 src2)
2919-
(let ((dst WritableGpr (temp_writable_gpr))
2920-
(_ Unit (emit (MInst.Mul8 signed src1 src2 dst))))
2921-
dst))
2922-
29232930
;; Helper for creating `imul` instructions.
29242931
(decl x64_imul (Type Gpr GprMem) Gpr)
2925-
(rule (x64_imul ty src1 src2)
2926-
(let ((dst WritableGpr (temp_writable_gpr))
2927-
(size OperandSize (raw_operand_size_of_type ty))
2928-
(_ Unit (emit (MInst.IMul size src1 src2 dst))))
2929-
dst))
2932+
(rule (x64_imul $I16 src1 src2) (x64_imulw_rm src1 src2))
2933+
(rule (x64_imul $I32 src1 src2) (x64_imull_rm src1 src2))
2934+
(rule (x64_imul $I64 src1 src2) (x64_imulq_rm src1 src2))
29302935

2931-
;; Helper for creating `imul` instructions with an immediate operand.
2936+
;; Helper for creating `imul` instructions with an immediate operand. Match
2937+
;; 8-bit immediates first to allow a smaller instruction encoding.
29322938
(decl x64_imul_imm (Type GprMem i32) Gpr)
2933-
(rule (x64_imul_imm ty src1 src2)
2934-
(let ((dst WritableGpr (temp_writable_gpr))
2935-
(size OperandSize (raw_operand_size_of_type ty))
2936-
(_ Unit (emit (MInst.IMulImm size src1 src2 dst))))
2937-
dst))
2939+
(rule 2 (x64_imul_imm $I16 src1 (is_rust_simm8 src2)) (x64_imulw_rmi_sxb src1 src2))
2940+
(rule 2 (x64_imul_imm $I32 src1 (is_rust_simm8 src2)) (x64_imull_rmi_sxb src1 src2))
2941+
(rule 2 (x64_imul_imm $I64 src1 (is_rust_simm8 src2)) (x64_imulq_rmi_sxb src1 src2))
2942+
(rule 1 (x64_imul_imm $I16 src1 (is_rust_imm16 src2)) (x64_imulw_rmi src1 src2))
2943+
(rule 1 (x64_imul_imm $I32 src1 (is_rust_imm32 src2)) (x64_imull_rmi src1 src2))
2944+
(rule 1 (x64_imul_imm $I64 src1 src2) (x64_imulq_rmi_sxl src1 src2))
2945+
2946+
;; Helper for creating `mul` instructions or `imul` instructions (depending
2947+
;; on `signed`) for 8-bit operands.
2948+
(decl x64_mul8_raw (bool Gpr GprMem) AssemblerOutputs)
2949+
(rule (x64_mul8_raw false src1 src2) (x64_mulb_m_raw src1 src2))
2950+
(rule (x64_mul8_raw true src1 src2) (x64_imulb_m_raw src1 src2))
2951+
2952+
(decl x64_mul8 (bool Gpr GprMem) Gpr)
2953+
(rule (x64_mul8 signed src1 src2)
2954+
(emit_ret_gpr (x64_mul8_raw signed src1 src2)))
29382955

29392956
(decl x64_mul8_with_flags_paired (bool Gpr GprMem) ProducesFlags)
29402957
(rule (x64_mul8_with_flags_paired signed src1 src2)
2941-
(let ((dst WritableGpr (temp_writable_gpr)))
2942-
(ProducesFlags.ProducesFlagsReturnsResultWithConsumer
2943-
(MInst.Mul8 signed src1 src2 dst)
2944-
dst)))
2945-
2946-
(decl x64_mul_lo_with_flags_paired (Type bool Gpr GprMem) ProducesFlags)
2947-
(rule (x64_mul_lo_with_flags_paired ty signed src1 src2)
2948-
(let ((dst_lo WritableGpr (temp_writable_gpr))
2949-
(dst_hi WritableGpr (temp_writable_gpr))
2950-
(size OperandSize (raw_operand_size_of_type ty)))
2951-
(ProducesFlags.ProducesFlagsReturnsResultWithConsumer
2952-
(MInst.Mul size signed src1 src2 dst_lo dst_hi)
2953-
dst_lo)))
2958+
(asm_produce_flags (x64_mul8_raw signed src1 src2)))
29542959

29552960

29562961

cranelift/codegen/src/isa/x64/lower.isle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,7 @@
10441044
(rule -5 (lower (has_type (ty_int_ref_16_to_64 ty) (imul (sinkable_load x) y)))
10451045
(x64_imul ty y x))
10461046

1047-
;; lift out constants to use 3-operand form
1047+
;; Lift out constants to use 3-operand form.
10481048
(rule -4 (lower (has_type (ty_int_ref_16_to_64 ty) (imul x (i32_from_iconst y))))
10491049
(x64_imul_imm ty x y))
10501050
(rule -3 (lower (has_type (ty_int_ref_16_to_64 ty) (imul (i32_from_iconst x) y)))

cranelift/codegen/src/isa/x64/lower/isle.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,13 +1045,21 @@ impl Context for IsleContext<'_, '_, MInst, X64Backend> {
10451045
}
10461046
}
10471047

1048+
fn is_rust_simm8(&mut self, simm32: i32) -> Option<i8> {
1049+
Some(i8::try_from(simm32).ok()?)
1050+
}
1051+
10481052
fn is_imm16(&mut self, src: &GprMemImm) -> Option<u16> {
10491053
match src.clone().to_reg_mem_imm() {
10501054
RegMemImm::Imm { simm32 } => Some(u16::try_from(simm32).ok()?),
10511055
_ => None,
10521056
}
10531057
}
10541058

1059+
fn is_rust_imm16(&mut self, simm32: i32) -> Option<u16> {
1060+
Some(u16::try_from(simm32).ok()?)
1061+
}
1062+
10551063
fn is_simm16(&mut self, src: &GprMemImm) -> Option<i16> {
10561064
match src.clone().to_reg_mem_imm() {
10571065
RegMemImm::Imm { simm32 } => Some(i16::try_from(simm32).ok()?),
@@ -1066,6 +1074,10 @@ impl Context for IsleContext<'_, '_, MInst, X64Backend> {
10661074
}
10671075
}
10681076

1077+
fn is_rust_imm32(&mut self, simm32: i32) -> Option<u32> {
1078+
Some(simm32 as u32)
1079+
}
1080+
10691081
fn is_simm32(&mut self, src: &GprMemImm) -> Option<i32> {
10701082
match src.clone().to_reg_mem_imm() {
10711083
RegMemImm::Imm { simm32 } => Some(simm32 as i32),

cranelift/filetests/filetests/isa/x64/i128.clif

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,13 @@ block0(v0: i128, v1: i128):
201201
; block0:
202202
; movq %rdx, %rax
203203
; movq %rdi, %rdx
204-
; imulq %rdx, %rcx, %rdx
204+
; imulq %rcx, %rdx
205205
; movq %rax, %rcx
206-
; imulq %rsi, %rcx, %rsi
206+
; imulq %rcx, %rsi
207207
; addq %rsi, %rdx
208208
; movq %rdi, %rax
209209
; movq %rdx, %r8
210-
; mulq %rax, %rcx, %rax, %rdx
210+
; mulq %rcx
211211
; movq %rdx, %rcx
212212
; movq %r8, %rdx
213213
; addq %rcx, %rdx
@@ -774,7 +774,7 @@ block0(v0: i128):
774774
; movabsq $1085102592571150095, %rdi
775775
; andq %rdi, %rax
776776
; movabsq $72340172838076673, %rdx
777-
; imulq %rax, %rdx, %rax
777+
; imulq %rdx, %rax
778778
; shrq $56, %rax, %rax
779779
; movq %rsi, %rdi
780780
; shrq $1, %rdi, %rdi
@@ -793,7 +793,7 @@ block0(v0: i128):
793793
; movabsq $1085102592571150095, %r10
794794
; andq %r10, %rdi
795795
; movabsq $72340172838076673, %rcx
796-
; imulq %rdi, %rcx, %rdi
796+
; imulq %rcx, %rdi
797797
; shrq $56, %rdi, %rdi
798798
; addq %rdi, %rax
799799
; uninit %rdx
@@ -1904,7 +1904,7 @@ block0(v0: i64, v1: i64):
19041904
; movq %rsp, %rbp
19051905
; block0:
19061906
; movq %rdi, %rax
1907-
; mulq %rax, %rsi, %rax, %rdx
1907+
; mulq %rsi
19081908
; movq %rbp, %rsp
19091909
; popq %rbp
19101910
; ret
@@ -1968,7 +1968,7 @@ block0(v0: i64, v1: i64):
19681968
; movq %rsp, %rbp
19691969
; block0:
19701970
; movq %rdi, %rax
1971-
; mulq %rax, %rsi, %rax, %rdx
1971+
; mulq %rsi
19721972
; movq %rbp, %rsp
19731973
; popq %rbp
19741974
; ret
@@ -1997,7 +1997,7 @@ block0(v0: i64, v1: i64):
19971997
; movq %rsp, %rbp
19981998
; block0:
19991999
; movq %rdi, %rax
2000-
; imulq %rax, %rsi, %rax, %rdx
2000+
; imulq %rsi
20012001
; movq %rbp, %rsp
20022002
; popq %rbp
20032003
; ret

0 commit comments

Comments
 (0)