(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
{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
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
return rewriteValueLOONG64_OpLOONG64MOVWstore(v)
case OpLOONG64MOVWstorezero:
return rewriteValueLOONG64_OpLOONG64MOVWstorezero(v)
+ case OpLOONG64MULV:
+ return rewriteValueLOONG64_OpLOONG64MULV(v)
case OpLOONG64NEGV:
return rewriteValueLOONG64_OpLOONG64NEGV(v)
case OpLOONG64NOR:
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
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
}
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
}
}
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]))
}
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]
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))
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
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))
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 {
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])