]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: optimize multiplication on loong64
authorWayne Zuo <wdvxdr@golangcn.org>
Thu, 2 Mar 2023 05:33:21 +0000 (13:33 +0800)
committerWayne Zuo <wdvxdr@golangcn.org>
Fri, 3 Mar 2023 01:33:00 +0000 (01:33 +0000)
Previously, multiplication on loong64 architecture was performed using
MULV and MULHVU instructions to calculate the low 64-bit and high
64-bit of a multiplication respectively. However, in most cases, only
the low 64-bits are needed. This commit enalbes only computating the low
64-bit result with the MULV instruction.

Reduce the binary size slightly.

file      before    after     Δ       %
addr2line 2833777   2833849   +72     +0.003%
asm       5267499   5266963   -536    -0.010%
buildid   2579706   2579402   -304    -0.012%
cgo       4798260   4797444   -816    -0.017%
compile   25247419  25175030  -72389  -0.287%
cover     4973091   4972027   -1064   -0.021%
dist      3631013   3565653   -65360  -1.800%
doc       4076036   4074004   -2032   -0.050%
fix       3496378   3496066   -312    -0.009%
link      6984102   6983214   -888    -0.013%
nm        2743820   2743516   -304    -0.011%
objdump   4277171   4277035   -136    -0.003%
pack      2379248   2378872   -376    -0.016%
pprof     14419090  14419874  +784    +0.005%
test2json 2684386   2684018   -368    -0.014%
trace     13640018  13631034  -8984   -0.066%
vet       7748918   7752630   +3712   +0.048%
go        15643850  15638098  -5752   -0.037%
total     127423782 127268729 -155053 -0.122%

Change-Id: Ifce4a9a3ed1d03c170681e39cb6f3541db9882dc
Reviewed-on: https://go-review.googlesource.com/c/go/+/472775
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Wayne Zuo <wdvxdr@golangcn.org>
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/loong64/ssa.go
src/cmd/compile/internal/ssa/_gen/LOONG64.rules
src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteLOONG64.go

index 81ea25781e4e9cbded6153d09228b098df7598ac..54afacce7f91df49a3169ff146c7c5869d1d9414 100644 (file)
@@ -140,7 +140,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
                ssa.OpLOONG64MULF,
                ssa.OpLOONG64MULD,
                ssa.OpLOONG64DIVF,
-               ssa.OpLOONG64DIVD:
+               ssa.OpLOONG64DIVD,
+               ssa.OpLOONG64MULV, ssa.OpLOONG64MULHV, ssa.OpLOONG64MULHVU:
                p := s.Prog(v.Op.Asm())
                p.From.Type = obj.TYPE_REG
                p.From.Reg = v.Args[1].Reg()
@@ -174,32 +175,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
                p.Reg = v.Args[0].Reg()
                p.To.Type = obj.TYPE_REG
                p.To.Reg = v.Reg()
-       case ssa.OpLOONG64MULV:
-               p := s.Prog(loong64.AMULV)
-               p.From.Type = obj.TYPE_REG
-               p.From.Reg = v.Args[1].Reg()
-               p.Reg = v.Args[0].Reg()
-               p.To.Type = obj.TYPE_REG
-               p.To.Reg = v.Reg1()
-               p1 := s.Prog(loong64.AMULHV)
-               p1.From.Type = obj.TYPE_REG
-               p1.From.Reg = v.Args[1].Reg()
-               p1.Reg = v.Args[0].Reg()
-               p1.To.Type = obj.TYPE_REG
-               p1.To.Reg = v.Reg0()
-       case ssa.OpLOONG64MULVU:
-               p := s.Prog(loong64.AMULV)
-               p.From.Type = obj.TYPE_REG
-               p.From.Reg = v.Args[1].Reg()
-               p.Reg = v.Args[0].Reg()
-               p.To.Type = obj.TYPE_REG
-               p.To.Reg = v.Reg1()
-               p1 := s.Prog(loong64.AMULHVU)
-               p1.From.Type = obj.TYPE_REG
-               p1.From.Reg = v.Args[1].Reg()
-               p1.Reg = v.Args[0].Reg()
-               p1.To.Type = obj.TYPE_REG
-               p1.To.Reg = v.Reg0()
        case ssa.OpLOONG64DIVV:
                p := s.Prog(loong64.ADIVV)
                p.From.Type = obj.TYPE_REG
index e034fb2654acd09305cc35412b1ad31556c59ed3..e68baf07f6b8d3222b865356f65f050704740b5e 100644 (file)
@@ -8,16 +8,17 @@
 (Sub(Ptr|64|32|16|8) ...) => (SUBV ...)
 (Sub(32|64)F ...) => (SUB(F|D) ...)
 
-(Mul(64|32|16|8) x y) => (Select1 (MULVU x y))
+(Mul(64|32|16|8) ...) => (MULV ...)
 (Mul(32|64)F ...) => (MUL(F|D) ...)
-(Mul64uhilo ...) => (MULVU ...)
-(Select0 (Mul64uover x y)) => (Select1 <typ.UInt64> (MULVU x y))
-(Select1 (Mul64uover x y)) => (SGTU <typ.Bool> (Select0 <typ.UInt64> (MULVU x y)) (MOVVconst <typ.UInt64> [0]))
+(Select0 (Mul64uhilo x y)) => (MULHVU x y)
+(Select1 (Mul64uhilo x y)) => (MULV x y)
+(Select0 (Mul64uover x y)) => (MULV x y)
+(Select1 (Mul64uover x y)) => (SGTU <typ.Bool> (MULHVU x y) (MOVVconst <typ.UInt64> [0]))
 
-(Hmul64 x y) => (Select0 (MULV x y))
-(Hmul64u x y) => (Select0 (MULVU x y))
-(Hmul32 x y) => (SRAVconst (Select1 <typ.Int64> (MULV (SignExt32to64 x) (SignExt32to64 y))) [32])
-(Hmul32u x y) => (SRLVconst (Select1 <typ.UInt64> (MULVU (ZeroExt32to64 x) (ZeroExt32to64 y))) [32])
+(Hmul64 ...)  => (MULHV  ...)
+(Hmul64u ...) => (MULHVU ...)
+(Hmul32 x y)  => (SRAVconst (MULV (SignExt32to64 x) (SignExt32to64 y)) [32])
+(Hmul32u x y) => (SRLVconst (MULV (ZeroExt32to64 x) (ZeroExt32to64 y)) [32])
 
 (Div64 x y) => (Select1 (DIVV x y))
 (Div64u x y) => (Select1 (DIVVU x y))
 (SGTU (MOVVconst [c]) x) && is32Bit(c) => (SGTUconst [c] x)
 
 // mul by constant
-(Select1 (MULVU x (MOVVconst [-1]))) => (NEGV x)
-(Select1 (MULVU _ (MOVVconst [0]))) => (MOVVconst [0])
-(Select1 (MULVU x (MOVVconst [1]))) => x
-(Select1 (MULVU x (MOVVconst [c]))) && isPowerOfTwo64(c) => (SLLVconst [log64(c)] x)
+(MULV x (MOVVconst [-1])) => (NEGV x)
+(MULV _ (MOVVconst [0])) => (MOVVconst [0])
+(MULV x (MOVVconst [1])) => x
+(MULV x (MOVVconst [c])) && isPowerOfTwo64(c) => (SLLVconst [log64(c)] x)
 
 // div by constant
 (Select1 (DIVVU x (MOVVconst [1]))) => x
 (SLLVconst [c] (MOVVconst [d]))  => (MOVVconst [d<<uint64(c)])
 (SRLVconst [c] (MOVVconst [d]))  => (MOVVconst [int64(uint64(d)>>uint64(c))])
 (SRAVconst [c] (MOVVconst [d]))  => (MOVVconst [d>>uint64(c)])
-(Select1 (MULVU (MOVVconst [c]) (MOVVconst [d]))) => (MOVVconst [c*d])
+(MULV (MOVVconst [c]) (MOVVconst [d])) => (MOVVconst [c*d])
 (Select1 (DIVV  (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c/d])
 (Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [int64(uint64(c)/uint64(d))])
 (Select0 (DIVV  (MOVVconst [c]) (MOVVconst [d]))) && d != 0 => (MOVVconst [c%d])   // mod
index b104660767aa4a1aec4df1c60a0bcca8a764af17..b593d3d41a7b0bccb8e593d4f07b014384661992 100644 (file)
@@ -163,10 +163,11 @@ func init() {
                {name: "SUBV", argLength: 2, reg: gp21, asm: "SUBVU"},                      // arg0 - arg1
                {name: "SUBVconst", argLength: 1, reg: gp11, asm: "SUBVU", aux: "Int64"},   // arg0 - auxInt
 
-               {name: "MULV", argLength: 2, reg: gp22, resultNotInArgs: true, commutative: true, typ: "(Int64,Int64)"},    // arg0 * arg1, signed
-               {name: "MULVU", argLength: 2, reg: gp22, resultNotInArgs: true, commutative: true, typ: "(UInt64,UInt64)"}, // arg0 * arg1, unsigned
-               {name: "DIVV", argLength: 2, reg: gp22, resultNotInArgs: true, typ: "(Int64,Int64)"},                       // arg0 / arg1, signed
-               {name: "DIVVU", argLength: 2, reg: gp22, resultNotInArgs: true, typ: "(UInt64,UInt64)"},                    // arg0 / arg1, unsigned
+               {name: "MULV", argLength: 2, reg: gp21, asm: "MULV", commutative: true, typ: "Int64"},      // arg0 * arg1
+               {name: "MULHV", argLength: 2, reg: gp21, asm: "MULHV", commutative: true, typ: "Int64"},    // (arg0 * arg1) >> 64, signed
+               {name: "MULHVU", argLength: 2, reg: gp21, asm: "MULHVU", commutative: true, typ: "UInt64"}, // (arg0 * arg1) >> 64, unsigned
+               {name: "DIVV", argLength: 2, reg: gp22, resultNotInArgs: true, typ: "(Int64,Int64)"},       // arg0 / arg1, signed
+               {name: "DIVVU", argLength: 2, reg: gp22, resultNotInArgs: true, typ: "(UInt64,UInt64)"},    // arg0 / arg1, unsigned
 
                {name: "ADDF", argLength: 2, reg: fp21, asm: "ADDF", commutative: true}, // arg0 + arg1
                {name: "ADDD", argLength: 2, reg: fp21, asm: "ADDD", commutative: true}, // arg0 + arg1
index 26ed4e552f8f44b84f10b14f86ff2bb39412328a..4a24012b1da9c72f5feb5ee66bc951a3ce38f59d 100644 (file)
@@ -1716,7 +1716,8 @@ const (
        OpLOONG64SUBV
        OpLOONG64SUBVconst
        OpLOONG64MULV
-       OpLOONG64MULVU
+       OpLOONG64MULHV
+       OpLOONG64MULHVU
        OpLOONG64DIVV
        OpLOONG64DIVVU
        OpLOONG64ADDF
@@ -22912,34 +22913,47 @@ var opcodeTable = [...]opInfo{
                },
        },
        {
-               name:            "MULV",
-               argLen:          2,
-               commutative:     true,
-               resultNotInArgs: true,
+               name:        "MULV",
+               argLen:      2,
+               commutative: true,
+               asm:         loong64.AMULV,
                reg: regInfo{
                        inputs: []inputInfo{
-                               {0, 1072496632}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
-                               {1, 1072496632}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+                               {0, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+                               {1, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
                        },
                        outputs: []outputInfo{
                                {0, 1070596088}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31
-                               {1, 1070596088}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31
                        },
                },
        },
        {
-               name:            "MULVU",
-               argLen:          2,
-               commutative:     true,
-               resultNotInArgs: true,
+               name:        "MULHV",
+               argLen:      2,
+               commutative: true,
+               asm:         loong64.AMULHV,
                reg: regInfo{
                        inputs: []inputInfo{
-                               {0, 1072496632}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
-                               {1, 1072496632}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+                               {0, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+                               {1, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+                       },
+                       outputs: []outputInfo{
+                               {0, 1070596088}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31
+                       },
+               },
+       },
+       {
+               name:        "MULHVU",
+               argLen:      2,
+               commutative: true,
+               asm:         loong64.AMULHVU,
+               reg: regInfo{
+                       inputs: []inputInfo{
+                               {0, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
+                               {1, 1072693240}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 g R23 R24 R25 R26 R27 R28 R29 R31
                        },
                        outputs: []outputInfo{
                                {0, 1070596088}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31
-                               {1, 1070596088}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R23 R24 R25 R26 R27 R28 R29 R31
                        },
                },
        },
index fdd19bf167e4fc4d11a35bdfcef5c62052540c88..8eacc1fda7d256382d2fd70c6b4195292f4e87e2 100644 (file)
@@ -201,9 +201,11 @@ func rewriteValueLOONG64(v *Value) bool {
        case OpHmul32u:
                return rewriteValueLOONG64_OpHmul32u(v)
        case OpHmul64:
-               return rewriteValueLOONG64_OpHmul64(v)
+               v.Op = OpLOONG64MULHV
+               return true
        case OpHmul64u:
-               return rewriteValueLOONG64_OpHmul64u(v)
+               v.Op = OpLOONG64MULHVU
+               return true
        case OpInterCall:
                v.Op = OpLOONG64CALLinter
                return true
@@ -285,6 +287,8 @@ func rewriteValueLOONG64(v *Value) bool {
                return rewriteValueLOONG64_OpLOONG64MOVWstore(v)
        case OpLOONG64MOVWstorezero:
                return rewriteValueLOONG64_OpLOONG64MOVWstorezero(v)
+       case OpLOONG64MULV:
+               return rewriteValueLOONG64_OpLOONG64MULV(v)
        case OpLOONG64NEGV:
                return rewriteValueLOONG64_OpLOONG64NEGV(v)
        case OpLOONG64NOR:
@@ -422,22 +426,23 @@ func rewriteValueLOONG64(v *Value) bool {
        case OpMove:
                return rewriteValueLOONG64_OpMove(v)
        case OpMul16:
-               return rewriteValueLOONG64_OpMul16(v)
+               v.Op = OpLOONG64MULV
+               return true
        case OpMul32:
-               return rewriteValueLOONG64_OpMul32(v)
+               v.Op = OpLOONG64MULV
+               return true
        case OpMul32F:
                v.Op = OpLOONG64MULF
                return true
        case OpMul64:
-               return rewriteValueLOONG64_OpMul64(v)
+               v.Op = OpLOONG64MULV
+               return true
        case OpMul64F:
                v.Op = OpLOONG64MULD
                return true
-       case OpMul64uhilo:
-               v.Op = OpLOONG64MULVU
-               return true
        case OpMul8:
-               return rewriteValueLOONG64_OpMul8(v)
+               v.Op = OpLOONG64MULV
+               return true
        case OpNeg16:
                v.Op = OpLOONG64NEGV
                return true
@@ -1228,20 +1233,18 @@ func rewriteValueLOONG64_OpHmul32(v *Value) bool {
        b := v.Block
        typ := &b.Func.Config.Types
        // match: (Hmul32 x y)
-       // result: (SRAVconst (Select1 <typ.Int64> (MULV (SignExt32to64 x) (SignExt32to64 y))) [32])
+       // result: (SRAVconst (MULV (SignExt32to64 x) (SignExt32to64 y)) [32])
        for {
                x := v_0
                y := v_1
                v.reset(OpLOONG64SRAVconst)
                v.AuxInt = int64ToAuxInt(32)
-               v0 := b.NewValue0(v.Pos, OpSelect1, typ.Int64)
-               v1 := b.NewValue0(v.Pos, OpLOONG64MULV, types.NewTuple(typ.Int64, typ.Int64))
+               v0 := b.NewValue0(v.Pos, OpLOONG64MULV, typ.Int64)
+               v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+               v1.AddArg(x)
                v2 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
-               v2.AddArg(x)
-               v3 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
-               v3.AddArg(y)
-               v1.AddArg2(v2, v3)
-               v0.AddArg(v1)
+               v2.AddArg(y)
+               v0.AddArg2(v1, v2)
                v.AddArg(v0)
                return true
        }
@@ -1252,54 +1255,18 @@ func rewriteValueLOONG64_OpHmul32u(v *Value) bool {
        b := v.Block
        typ := &b.Func.Config.Types
        // match: (Hmul32u x y)
-       // result: (SRLVconst (Select1 <typ.UInt64> (MULVU (ZeroExt32to64 x) (ZeroExt32to64 y))) [32])
+       // result: (SRLVconst (MULV (ZeroExt32to64 x) (ZeroExt32to64 y)) [32])
        for {
                x := v_0
                y := v_1
                v.reset(OpLOONG64SRLVconst)
                v.AuxInt = int64ToAuxInt(32)
-               v0 := b.NewValue0(v.Pos, OpSelect1, typ.UInt64)
-               v1 := b.NewValue0(v.Pos, OpLOONG64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
+               v0 := b.NewValue0(v.Pos, OpLOONG64MULV, typ.Int64)
+               v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+               v1.AddArg(x)
                v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
-               v2.AddArg(x)
-               v3 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
-               v3.AddArg(y)
-               v1.AddArg2(v2, v3)
-               v0.AddArg(v1)
-               v.AddArg(v0)
-               return true
-       }
-}
-func rewriteValueLOONG64_OpHmul64(v *Value) bool {
-       v_1 := v.Args[1]
-       v_0 := v.Args[0]
-       b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (Hmul64 x y)
-       // result: (Select0 (MULV x y))
-       for {
-               x := v_0
-               y := v_1
-               v.reset(OpSelect0)
-               v0 := b.NewValue0(v.Pos, OpLOONG64MULV, types.NewTuple(typ.Int64, typ.Int64))
-               v0.AddArg2(x, y)
-               v.AddArg(v0)
-               return true
-       }
-}
-func rewriteValueLOONG64_OpHmul64u(v *Value) bool {
-       v_1 := v.Args[1]
-       v_0 := v.Args[0]
-       b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (Hmul64u x y)
-       // result: (Select0 (MULVU x y))
-       for {
-               x := v_0
-               y := v_1
-               v.reset(OpSelect0)
-               v0 := b.NewValue0(v.Pos, OpLOONG64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
-               v0.AddArg2(x, y)
+               v2.AddArg(y)
+               v0.AddArg2(v1, v2)
                v.AddArg(v0)
                return true
        }
@@ -3272,6 +3239,89 @@ func rewriteValueLOONG64_OpLOONG64MOVWstorezero(v *Value) bool {
        }
        return false
 }
+func rewriteValueLOONG64_OpLOONG64MULV(v *Value) bool {
+       v_1 := v.Args[1]
+       v_0 := v.Args[0]
+       // match: (MULV x (MOVVconst [-1]))
+       // result: (NEGV x)
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       x := v_0
+                       if v_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_1.AuxInt) != -1 {
+                               continue
+                       }
+                       v.reset(OpLOONG64NEGV)
+                       v.AddArg(x)
+                       return true
+               }
+               break
+       }
+       // match: (MULV _ (MOVVconst [0]))
+       // result: (MOVVconst [0])
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       if v_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_1.AuxInt) != 0 {
+                               continue
+                       }
+                       v.reset(OpLOONG64MOVVconst)
+                       v.AuxInt = int64ToAuxInt(0)
+                       return true
+               }
+               break
+       }
+       // match: (MULV x (MOVVconst [1]))
+       // result: x
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       x := v_0
+                       if v_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_1.AuxInt) != 1 {
+                               continue
+                       }
+                       v.copyOf(x)
+                       return true
+               }
+               break
+       }
+       // match: (MULV x (MOVVconst [c]))
+       // cond: isPowerOfTwo64(c)
+       // result: (SLLVconst [log64(c)] x)
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       x := v_0
+                       if v_1.Op != OpLOONG64MOVVconst {
+                               continue
+                       }
+                       c := auxIntToInt64(v_1.AuxInt)
+                       if !(isPowerOfTwo64(c)) {
+                               continue
+                       }
+                       v.reset(OpLOONG64SLLVconst)
+                       v.AuxInt = int64ToAuxInt(log64(c))
+                       v.AddArg(x)
+                       return true
+               }
+               break
+       }
+       // match: (MULV (MOVVconst [c]) (MOVVconst [d]))
+       // result: (MOVVconst [c*d])
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       if v_0.Op != OpLOONG64MOVVconst {
+                               continue
+                       }
+                       c := auxIntToInt64(v_0.AuxInt)
+                       if v_1.Op != OpLOONG64MOVVconst {
+                               continue
+                       }
+                       d := auxIntToInt64(v_1.AuxInt)
+                       v.reset(OpLOONG64MOVVconst)
+                       v.AuxInt = int64ToAuxInt(c * d)
+                       return true
+               }
+               break
+       }
+       return false
+}
 func rewriteValueLOONG64_OpLOONG64NEGV(v *Value) bool {
        v_0 := v.Args[0]
        // match: (NEGV (MOVVconst [c]))
@@ -5659,74 +5709,6 @@ func rewriteValueLOONG64_OpMove(v *Value) bool {
        }
        return false
 }
-func rewriteValueLOONG64_OpMul16(v *Value) bool {
-       v_1 := v.Args[1]
-       v_0 := v.Args[0]
-       b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (Mul16 x y)
-       // result: (Select1 (MULVU x y))
-       for {
-               x := v_0
-               y := v_1
-               v.reset(OpSelect1)
-               v0 := b.NewValue0(v.Pos, OpLOONG64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
-               v0.AddArg2(x, y)
-               v.AddArg(v0)
-               return true
-       }
-}
-func rewriteValueLOONG64_OpMul32(v *Value) bool {
-       v_1 := v.Args[1]
-       v_0 := v.Args[0]
-       b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (Mul32 x y)
-       // result: (Select1 (MULVU x y))
-       for {
-               x := v_0
-               y := v_1
-               v.reset(OpSelect1)
-               v0 := b.NewValue0(v.Pos, OpLOONG64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
-               v0.AddArg2(x, y)
-               v.AddArg(v0)
-               return true
-       }
-}
-func rewriteValueLOONG64_OpMul64(v *Value) bool {
-       v_1 := v.Args[1]
-       v_0 := v.Args[0]
-       b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (Mul64 x y)
-       // result: (Select1 (MULVU x y))
-       for {
-               x := v_0
-               y := v_1
-               v.reset(OpSelect1)
-               v0 := b.NewValue0(v.Pos, OpLOONG64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
-               v0.AddArg2(x, y)
-               v.AddArg(v0)
-               return true
-       }
-}
-func rewriteValueLOONG64_OpMul8(v *Value) bool {
-       v_1 := v.Args[1]
-       v_0 := v.Args[0]
-       b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (Mul8 x y)
-       // result: (Select1 (MULVU x y))
-       for {
-               x := v_0
-               y := v_1
-               v.reset(OpSelect1)
-               v0 := b.NewValue0(v.Pos, OpLOONG64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
-               v0.AddArg2(x, y)
-               v.AddArg(v0)
-               return true
-       }
-}
 func rewriteValueLOONG64_OpNeq16(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
@@ -6881,20 +6863,28 @@ func rewriteValueLOONG64_OpRsh8x8(v *Value) bool {
 func rewriteValueLOONG64_OpSelect0(v *Value) bool {
        v_0 := v.Args[0]
        b := v.Block
-       typ := &b.Func.Config.Types
+       // match: (Select0 (Mul64uhilo x y))
+       // result: (MULHVU x y)
+       for {
+               if v_0.Op != OpMul64uhilo {
+                       break
+               }
+               y := v_0.Args[1]
+               x := v_0.Args[0]
+               v.reset(OpLOONG64MULHVU)
+               v.AddArg2(x, y)
+               return true
+       }
        // match: (Select0 (Mul64uover x y))
-       // result: (Select1 <typ.UInt64> (MULVU x y))
+       // result: (MULV x y)
        for {
                if v_0.Op != OpMul64uover {
                        break
                }
                y := v_0.Args[1]
                x := v_0.Args[0]
-               v.reset(OpSelect1)
-               v.Type = typ.UInt64
-               v0 := b.NewValue0(v.Pos, OpLOONG64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
-               v0.AddArg2(x, y)
-               v.AddArg(v0)
+               v.reset(OpLOONG64MULV)
+               v.AddArg2(x, y)
                return true
        }
        // match: (Select0 <t> (Add64carry x y c))
@@ -7022,8 +7012,20 @@ func rewriteValueLOONG64_OpSelect1(v *Value) bool {
        v_0 := v.Args[0]
        b := v.Block
        typ := &b.Func.Config.Types
+       // match: (Select1 (Mul64uhilo x y))
+       // result: (MULV x y)
+       for {
+               if v_0.Op != OpMul64uhilo {
+                       break
+               }
+               y := v_0.Args[1]
+               x := v_0.Args[0]
+               v.reset(OpLOONG64MULV)
+               v.AddArg2(x, y)
+               return true
+       }
        // match: (Select1 (Mul64uover x y))
-       // result: (SGTU <typ.Bool> (Select0 <typ.UInt64> (MULVU x y)) (MOVVconst <typ.UInt64> [0]))
+       // result: (SGTU <typ.Bool> (MULHVU x y) (MOVVconst <typ.UInt64> [0]))
        for {
                if v_0.Op != OpMul64uover {
                        break
@@ -7032,13 +7034,11 @@ func rewriteValueLOONG64_OpSelect1(v *Value) bool {
                x := v_0.Args[0]
                v.reset(OpLOONG64SGTU)
                v.Type = typ.Bool
-               v0 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64)
-               v1 := b.NewValue0(v.Pos, OpLOONG64MULVU, types.NewTuple(typ.UInt64, typ.UInt64))
-               v1.AddArg2(x, y)
-               v0.AddArg(v1)
-               v2 := b.NewValue0(v.Pos, OpLOONG64MOVVconst, typ.UInt64)
-               v2.AuxInt = int64ToAuxInt(0)
-               v.AddArg2(v0, v2)
+               v0 := b.NewValue0(v.Pos, OpLOONG64MULHVU, typ.UInt64)
+               v0.AddArg2(x, y)
+               v1 := b.NewValue0(v.Pos, OpLOONG64MOVVconst, typ.UInt64)
+               v1.AuxInt = int64ToAuxInt(0)
+               v.AddArg2(v0, v1)
                return true
        }
        // match: (Select1 <t> (Add64carry x y c))
@@ -7085,90 +7085,6 @@ func rewriteValueLOONG64_OpSelect1(v *Value) bool {
                v.AddArg2(v0, v2)
                return true
        }
-       // match: (Select1 (MULVU x (MOVVconst [-1])))
-       // result: (NEGV x)
-       for {
-               if v_0.Op != OpLOONG64MULVU {
-                       break
-               }
-               _ = v_0.Args[1]
-               v_0_0 := v_0.Args[0]
-               v_0_1 := v_0.Args[1]
-               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
-                       x := v_0_0
-                       if v_0_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != -1 {
-                               continue
-                       }
-                       v.reset(OpLOONG64NEGV)
-                       v.AddArg(x)
-                       return true
-               }
-               break
-       }
-       // match: (Select1 (MULVU _ (MOVVconst [0])))
-       // result: (MOVVconst [0])
-       for {
-               if v_0.Op != OpLOONG64MULVU {
-                       break
-               }
-               _ = v_0.Args[1]
-               v_0_0 := v_0.Args[0]
-               v_0_1 := v_0.Args[1]
-               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
-                       if v_0_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 0 {
-                               continue
-                       }
-                       v.reset(OpLOONG64MOVVconst)
-                       v.AuxInt = int64ToAuxInt(0)
-                       return true
-               }
-               break
-       }
-       // match: (Select1 (MULVU x (MOVVconst [1])))
-       // result: x
-       for {
-               if v_0.Op != OpLOONG64MULVU {
-                       break
-               }
-               _ = v_0.Args[1]
-               v_0_0 := v_0.Args[0]
-               v_0_1 := v_0.Args[1]
-               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
-                       x := v_0_0
-                       if v_0_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 1 {
-                               continue
-                       }
-                       v.copyOf(x)
-                       return true
-               }
-               break
-       }
-       // match: (Select1 (MULVU x (MOVVconst [c])))
-       // cond: isPowerOfTwo64(c)
-       // result: (SLLVconst [log64(c)] x)
-       for {
-               if v_0.Op != OpLOONG64MULVU {
-                       break
-               }
-               _ = v_0.Args[1]
-               v_0_0 := v_0.Args[0]
-               v_0_1 := v_0.Args[1]
-               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
-                       x := v_0_0
-                       if v_0_1.Op != OpLOONG64MOVVconst {
-                               continue
-                       }
-                       c := auxIntToInt64(v_0_1.AuxInt)
-                       if !(isPowerOfTwo64(c)) {
-                               continue
-                       }
-                       v.reset(OpLOONG64SLLVconst)
-                       v.AuxInt = int64ToAuxInt(log64(c))
-                       v.AddArg(x)
-                       return true
-               }
-               break
-       }
        // match: (Select1 (DIVVU x (MOVVconst [1])))
        // result: x
        for {
@@ -7206,30 +7122,6 @@ func rewriteValueLOONG64_OpSelect1(v *Value) bool {
                v.AddArg(x)
                return true
        }
-       // match: (Select1 (MULVU (MOVVconst [c]) (MOVVconst [d])))
-       // result: (MOVVconst [c*d])
-       for {
-               if v_0.Op != OpLOONG64MULVU {
-                       break
-               }
-               _ = v_0.Args[1]
-               v_0_0 := v_0.Args[0]
-               v_0_1 := v_0.Args[1]
-               for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
-                       if v_0_0.Op != OpLOONG64MOVVconst {
-                               continue
-                       }
-                       c := auxIntToInt64(v_0_0.AuxInt)
-                       if v_0_1.Op != OpLOONG64MOVVconst {
-                               continue
-                       }
-                       d := auxIntToInt64(v_0_1.AuxInt)
-                       v.reset(OpLOONG64MOVVconst)
-                       v.AuxInt = int64ToAuxInt(c * d)
-                       return true
-               }
-               break
-       }
        // match: (Select1 (DIVV (MOVVconst [c]) (MOVVconst [d])))
        // cond: d != 0
        // result: (MOVVconst [c/d])