This is a follow up of CL 425101 on RISCV64.
According to RISCV Volume 1, Unprivileged Spec v.
20191213 Chapter 7.1:
If both the high and low bits of the same product are required, then the
recommended code sequence is: MULH[[S]U] rdh, rs1, rs2; MUL rdl, rs1, rs2
(source register specifiers must be in same order and rdh cannot be the
same as rs1 or rs2). Microarchitectures can then fuse these into a single
multiply operation instead of performing two separate multiplies.
So we should not split Muluhilo to separate instructions.
Updates #54607
Change-Id: If47461f3aaaf00e27cd583a9990e144fb8bcdb17
Reviewed-on: https://go-review.googlesource.com/c/go/+/425203
Auto-Submit: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Wayne Zuo <wdvxdr@golangcn.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
(SLTI [x] (MOVDconst [y])) => (MOVDconst [b2i(int64(y) < int64(x))])
(SLTIU [x] (MOVDconst [y])) => (MOVDconst [b2i(uint64(y) < uint64(x))])
+// deadcode for LoweredMuluhilo
+(Select0 m:(LoweredMuluhilo x y)) && m.Uses == 1 => (MULHU x y)
+(Select1 m:(LoweredMuluhilo x y)) && m.Uses == 1 => (MUL x y)
+
// Merge negation into fused multiply-add and multiply-subtract.
//
// Key:
return rewriteValueRISCV64_OpRsh8x64(v)
case OpRsh8x8:
return rewriteValueRISCV64_OpRsh8x8(v)
+ case OpSelect0:
+ return rewriteValueRISCV64_OpSelect0(v)
+ case OpSelect1:
+ return rewriteValueRISCV64_OpSelect1(v)
case OpSignExt16to32:
v.Op = OpRISCV64MOVHreg
return true
return true
}
}
+func rewriteValueRISCV64_OpSelect0(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Select0 m:(LoweredMuluhilo x y))
+ // cond: m.Uses == 1
+ // result: (MULHU x y)
+ for {
+ m := v_0
+ if m.Op != OpRISCV64LoweredMuluhilo {
+ break
+ }
+ y := m.Args[1]
+ x := m.Args[0]
+ if !(m.Uses == 1) {
+ break
+ }
+ v.reset(OpRISCV64MULHU)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
+func rewriteValueRISCV64_OpSelect1(v *Value) bool {
+ v_0 := v.Args[0]
+ // match: (Select1 m:(LoweredMuluhilo x y))
+ // cond: m.Uses == 1
+ // result: (MUL x y)
+ for {
+ m := v_0
+ if m.Op != OpRISCV64LoweredMuluhilo {
+ break
+ }
+ y := m.Args[1]
+ x := m.Args[0]
+ if !(m.Uses == 1) {
+ break
+ }
+ v.reset(OpRISCV64MUL)
+ v.AddArg2(x, y)
+ return true
+ }
+ return false
+}
func rewriteValueRISCV64_OpSlicemask(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
func Mul64HiOnly(x, y uint64) uint64 {
// arm64:"UMULH",-"MUL"
+ // riscv64:"MULHU",-"MUL\t"
hi, _ := bits.Mul64(x, y)
return hi
}
func Mul64LoOnly(x, y uint64) uint64 {
// arm64:"MUL",-"UMULH"
+ // riscv64:"MUL\t",-"MULHU"
_, lo := bits.Mul64(x, y)
return lo
}