Skip to content

Commit f285275

Browse files
committed
wip
1 parent 969f859 commit f285275

File tree

2 files changed

+59
-4
lines changed

2 files changed

+59
-4
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2871,6 +2871,19 @@
28712871
;; zero-extension for the `Value` input.
28722872
(decl put_value_in_reg_for_icmp (IntCC Value) XReg)
28732873

2874+
(decl madd_overflow64 (XReg XReg XReg) ValueRegs)
2875+
2876+
(rule (madd_overflow64 x y z)
2877+
(let ((one XReg (imm $I8 1))
2878+
(hi XReg (rv_mulhu x y))
2879+
(m XReg (rv_mul x y))
2880+
(of_mul XReg (gen_select_xreg (cmp_eqz hi) (zero_reg) one))
2881+
(sum XReg (rv_add m z))
2882+
(of_add XReg (gen_select_xreg (int_compare (IntCC.UnsignedLessThan) sum m) one (zero_reg)))
2883+
(of XReg (rv_or of_mul of_add)))
2884+
(value_regs sum of)))
2885+
2886+
28742887
;; Base cases, use the `cc` to determine whether to zero or sign extend.
28752888
(rule 0 (put_value_in_reg_for_icmp cc val)
28762889
(zext val))

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

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,14 +347,56 @@
347347
(rule 0 (lower (has_type (fits_in_32 ty) (umul_overflow x y)))
348348
(let ((tmp_x XReg (zext x))
349349
(tmp_y XReg (zext y))
350-
(res XReg (rv_mulhu tmp_x tmp_y))
351-
(hi XReg (rv_mul tmp_x tmp_y))
352-
(one XReg (imm $I32 1))
353-
(of XReg (gen_select_xreg (cmp_eqz res) one (zero_reg))))
350+
(res XReg (rv_mul tmp_x tmp_y))
351+
(hi XReg (rv_srli res (imm12_const (ty_bits ty))))
352+
(one XReg (imm $I8 1))
353+
(of XReg (gen_select_xreg (cmp_eqz hi) (zero_reg) one)))
354+
(output_pair
355+
(value_reg res)
356+
(value_reg of))))
357+
358+
(rule 1 (lower (has_type $I64 (umul_overflow x y)))
359+
(let ((hi XReg (rv_mulhu x y))
360+
(res XReg (rv_mul x y))
361+
(one XReg (imm $I8 1))
362+
(of XReg (gen_select_xreg (cmp_eqz hi) (zero_reg) one)))
354363
(output_pair
355364
(value_reg res)
356365
(value_reg of))))
357366

367+
;; TODO
368+
(rule 2 (lower (has_type $I128 (umul_overflow x y)))
369+
(let
370+
((x_regs ValueRegs x)
371+
(x_lo XReg (value_regs_get x_regs 0))
372+
(x_hi XReg (value_regs_get x_regs 1))
373+
374+
;; Get the high/low registers for `y`.
375+
(y_regs ValueRegs y)
376+
(y_lo XReg (value_regs_get y_regs 0))
377+
(y_hi XReg (value_regs_get y_regs 1))
378+
379+
;; 128bit mul formula:
380+
;; dst_lo = x_lo * y_lo
381+
;; dst_hi = mulhu(x_lo, y_lo) + (x_lo * y_hi) + (x_hi * y_lo)
382+
;;
383+
;; We can convert the above formula into the following
384+
;; mulhu dst_hi, x_lo, y_lo
385+
;; madd dst_hi, x_lo, y_hi, dst_hi
386+
;; madd dst_hi, x_hi, y_lo, dst_hi
387+
;; madd dst_lo, x_lo, y_lo, zero
388+
(dst_hi1 XReg (rv_mulhu x_lo y_lo))
389+
(one XReg (imm $I32 1))
390+
(dst_hi2 ValueRegs (madd_overflow64 x_lo y_hi (value_regs_get dst_hi1 0)))
391+
(dst_hi ValueRegs (madd_overflow64 x_hi y_lo (value_regs_get dst_hi2 0)))
392+
(dst_lo XReg (madd x_lo y_lo (zero_reg)))
393+
394+
(of_res1 XReg (rv_or (value_regs_get dst_hi1 1) (value_regs_get dst_hi2 1)))
395+
(of_res XReg (rv_or of_res1 (value_regs_get dst_hi 1))))
396+
(output_pair
397+
(value_regs dst_lo (value_regs_get dst_hi 0))
398+
(value_reg of_res))))
399+
358400
;;;; Rules for `isub` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
359401
;; Base case, simply subtracting things in registers.
360402

0 commit comments

Comments
 (0)