Skip to content

Commit bc94e31

Browse files
committed
x64: convert scalar multiplications
1 parent 8386a1b commit bc94e31

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
@@ -1829,12 +1829,18 @@
18291829
(extern extractor is_imm8_xmm is_imm8_xmm)
18301830
(decl is_simm8 (i8) GprMemImm)
18311831
(extern extractor is_simm8 is_simm8)
1832+
(decl is_rust_simm8 (i8) i32)
1833+
(extern extractor is_rust_simm8 is_rust_simm8)
18321834
(decl is_imm16 (u16) GprMemImm)
18331835
(extern extractor is_imm16 is_imm16)
1836+
(decl is_rust_imm16 (u16) i32)
1837+
(extern extractor is_rust_imm16 is_rust_imm16)
18341838
(decl is_simm16 (i16) GprMemImm)
18351839
(extern extractor is_simm16 is_simm16)
18361840
(decl is_imm32 (u32) GprMemImm)
18371841
(extern extractor is_imm32 is_imm32)
1842+
(decl is_rust_imm32 (u32) i32)
1843+
(extern extractor is_rust_imm32 is_rust_imm32)
18381844
(decl is_simm32 (i32) GprMemImm)
18391845
(extern extractor is_simm32 is_simm32)
18401846
(decl is_gpr (Gpr) GprMemImm)
@@ -2718,6 +2724,8 @@
27182724
(decl asm_produce_flags (AssemblerOutputs) ProducesFlags)
27192725
(rule (asm_produce_flags (AssemblerOutputs.RetGpr inst gpr))
27202726
(ProducesFlags.ProducesFlagsReturnsResultWithConsumer inst gpr))
2727+
(rule (asm_produce_flags (AssemblerOutputs.RetValueRegs inst regs))
2728+
(ProducesFlags.ProducesFlagsReturnsResultWithConsumer inst (value_regs_get_gpr regs 0)))
27212729

27222730
;; Other operations consume _and_ produce flags--"chaining".
27232731
(type ChainFlagsOp (enum (Adc) (Sbb)))
@@ -2908,15 +2916,18 @@
29082916

29092917

29102918
;; Helper for creating `mul` instructions or `imul` instructions (depending
2911-
;; on `signed`)
2912-
(decl x64_mul (Type bool Gpr GprMem) ValueRegs)
2913-
(rule (x64_mul ty signed src1 src2)
2914-
(let ((dst_lo WritableGpr (temp_writable_gpr))
2915-
(dst_hi WritableGpr (temp_writable_gpr))
2916-
(size OperandSize (raw_operand_size_of_type ty))
2917-
(_ Unit (emit (MInst.Mul size signed src1 src2 dst_lo dst_hi))))
2918-
(value_gprs dst_lo dst_hi)))
2919+
;; on `signed`). For the 8-bit rules, see `x64_mul8`.
2920+
(decl x64_mul_raw (Type bool Gpr GprMem) AssemblerOutputs)
2921+
(rule (x64_mul_raw $I16 false src1 src2) (x64_mulw_m_raw src1 src2))
2922+
(rule (x64_mul_raw $I32 false src1 src2) (x64_mull_m_raw src1 src2))
2923+
(rule (x64_mul_raw $I64 false src1 src2) (x64_mulq_m_raw src1 src2))
2924+
(rule (x64_mul_raw $I16 true src1 src2) (x64_imulw_m_raw src1 src2))
2925+
(rule (x64_mul_raw $I32 true src1 src2) (x64_imull_m_raw src1 src2))
2926+
(rule (x64_mul_raw $I64 true src1 src2) (x64_imulq_m_raw src1 src2))
29192927

2928+
(decl x64_mul (Type bool Gpr GprMem) ValueRegs)
2929+
(rule 0 (x64_mul ty signed src1 src2)
2930+
(emit_ret_value_regs (x64_mul_raw ty signed src1 src2)))
29202931
;; Special case the `mulx` pattern with the BMI2 instruction set.
29212932
(rule 1 (x64_mul (ty_32_or_64 ty) false src1 src2)
29222933
(if-let true (use_bmi2))
@@ -2933,49 +2944,43 @@
29332944
(_ Unit (emit (MInst.MulX size src1 src2 (writable_invalid_gpr) dst))))
29342945
dst))
29352946

2947+
(decl x64_mul_lo_with_flags_paired (Type bool Gpr GprMem) ProducesFlags)
2948+
(rule (x64_mul_lo_with_flags_paired ty signed src1 src2)
2949+
(asm_produce_flags (x64_mul_raw ty signed src1 src2)))
2950+
29362951
;; Get the invalid register as writable
29372952
(decl writable_invalid_gpr () WritableGpr)
29382953
(extern constructor writable_invalid_gpr writable_invalid_gpr)
29392954

2940-
;; Helper for creating `mul` instructions or `imul` instructions (depending
2941-
;; on `signed`) for 8-bit operands.
2942-
(decl x64_mul8 (bool Gpr GprMem) Gpr)
2943-
(rule (x64_mul8 signed src1 src2)
2944-
(let ((dst WritableGpr (temp_writable_gpr))
2945-
(_ Unit (emit (MInst.Mul8 signed src1 src2 dst))))
2946-
dst))
2947-
29482955
;; Helper for creating `imul` instructions.
29492956
(decl x64_imul (Type Gpr GprMem) Gpr)
2950-
(rule (x64_imul ty src1 src2)
2951-
(let ((dst WritableGpr (temp_writable_gpr))
2952-
(size OperandSize (raw_operand_size_of_type ty))
2953-
(_ Unit (emit (MInst.IMul size src1 src2 dst))))
2954-
dst))
2957+
(rule (x64_imul $I16 src1 src2) (x64_imulw_rm src1 src2))
2958+
(rule (x64_imul $I32 src1 src2) (x64_imull_rm src1 src2))
2959+
(rule (x64_imul $I64 src1 src2) (x64_imulq_rm src1 src2))
29552960

2956-
;; Helper for creating `imul` instructions with an immediate operand.
2961+
;; Helper for creating `imul` instructions with an immediate operand. Match
2962+
;; 8-bit immediates first to allow a smaller instruction encoding.
29572963
(decl x64_imul_imm (Type GprMem i32) Gpr)
2958-
(rule (x64_imul_imm ty src1 src2)
2959-
(let ((dst WritableGpr (temp_writable_gpr))
2960-
(size OperandSize (raw_operand_size_of_type ty))
2961-
(_ Unit (emit (MInst.IMulImm size src1 src2 dst))))
2962-
dst))
2964+
(rule 2 (x64_imul_imm $I16 src1 (is_rust_simm8 src2)) (x64_imulw_rmi_sxb src1 src2))
2965+
(rule 2 (x64_imul_imm $I32 src1 (is_rust_simm8 src2)) (x64_imull_rmi_sxb src1 src2))
2966+
(rule 2 (x64_imul_imm $I64 src1 (is_rust_simm8 src2)) (x64_imulq_rmi_sxb src1 src2))
2967+
(rule 1 (x64_imul_imm $I16 src1 (is_rust_imm16 src2)) (x64_imulw_rmi src1 src2))
2968+
(rule 1 (x64_imul_imm $I32 src1 (is_rust_imm32 src2)) (x64_imull_rmi src1 src2))
2969+
(rule 1 (x64_imul_imm $I64 src1 src2) (x64_imulq_rmi_sxl src1 src2))
2970+
2971+
;; Helper for creating `mul` instructions or `imul` instructions (depending
2972+
;; on `signed`) for 8-bit operands.
2973+
(decl x64_mul8_raw (bool Gpr GprMem) AssemblerOutputs)
2974+
(rule (x64_mul8_raw false src1 src2) (x64_mulb_m_raw src1 src2))
2975+
(rule (x64_mul8_raw true src1 src2) (x64_imulb_m_raw src1 src2))
2976+
2977+
(decl x64_mul8 (bool Gpr GprMem) Gpr)
2978+
(rule (x64_mul8 signed src1 src2)
2979+
(emit_ret_gpr (x64_mul8_raw signed src1 src2)))
29632980

29642981
(decl x64_mul8_with_flags_paired (bool Gpr GprMem) ProducesFlags)
29652982
(rule (x64_mul8_with_flags_paired signed src1 src2)
2966-
(let ((dst WritableGpr (temp_writable_gpr)))
2967-
(ProducesFlags.ProducesFlagsReturnsResultWithConsumer
2968-
(MInst.Mul8 signed src1 src2 dst)
2969-
dst)))
2970-
2971-
(decl x64_mul_lo_with_flags_paired (Type bool Gpr GprMem) ProducesFlags)
2972-
(rule (x64_mul_lo_with_flags_paired ty signed src1 src2)
2973-
(let ((dst_lo WritableGpr (temp_writable_gpr))
2974-
(dst_hi WritableGpr (temp_writable_gpr))
2975-
(size OperandSize (raw_operand_size_of_type ty)))
2976-
(ProducesFlags.ProducesFlagsReturnsResultWithConsumer
2977-
(MInst.Mul size signed src1 src2 dst_lo dst_hi)
2978-
dst_lo)))
2983+
(asm_produce_flags (x64_mul8_raw signed src1 src2)))
29792984

29802985

29812986

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
@@ -1049,13 +1049,21 @@ impl Context for IsleContext<'_, '_, MInst, X64Backend> {
10491049
}
10501050
}
10511051

1052+
fn is_rust_simm8(&mut self, simm32: i32) -> Option<i8> {
1053+
Some(i8::try_from(simm32).ok()?)
1054+
}
1055+
10521056
fn is_imm16(&mut self, src: &GprMemImm) -> Option<u16> {
10531057
match src.clone().to_reg_mem_imm() {
10541058
RegMemImm::Imm { simm32 } => Some(u16::try_from(simm32).ok()?),
10551059
_ => None,
10561060
}
10571061
}
10581062

1063+
fn is_rust_imm16(&mut self, simm32: i32) -> Option<u16> {
1064+
Some(u16::try_from(simm32).ok()?)
1065+
}
1066+
10591067
fn is_simm16(&mut self, src: &GprMemImm) -> Option<i16> {
10601068
match src.clone().to_reg_mem_imm() {
10611069
RegMemImm::Imm { simm32 } => Some(i16::try_from(simm32).ok()?),
@@ -1070,6 +1078,10 @@ impl Context for IsleContext<'_, '_, MInst, X64Backend> {
10701078
}
10711079
}
10721080

1081+
fn is_rust_imm32(&mut self, simm32: i32) -> Option<u32> {
1082+
Some(simm32 as u32)
1083+
}
1084+
10731085
fn is_simm32(&mut self, src: &GprMemImm) -> Option<i32> {
10741086
match src.clone().to_reg_mem_imm() {
10751087
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)