cmd/compile: optimize some patterns into revb2h/revb4h instruction on loong64

Pattern1: (the type of c is uint16)
    c>>8 | c<<8
To:
    revb2h c

Pattern2: (the type of c is uint32)
    (c & 0xff00ff00)>>8 | (c & 0x00ff00ff)<<8
To:
    revb2h c

Pattern3: (the type of c is uint64)
    (c & 0xff00ff00ff00ff00)>>8 | (c & 0x00ff00ff00ff00ff)<<8
To:
    revb4h c

Change-Id: Ic6231a3f476cbacbea4bd00e31193d107cb86cda
Reviewed-on: https://go-review.googlesource.com/c/go/+/696335
Reviewed-by: Meidan Li <limeidan@loongson.cn>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Xiaolin Zhao 2025-08-15 16:19:01 +08:00 committed by Gopher Robot
parent 8dcab6f450
commit 9632ba8160
6 changed files with 469 additions and 0 deletions

View file

@ -543,6 +543,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
ssa.OpLOONG64SQRTF, ssa.OpLOONG64SQRTF,
ssa.OpLOONG64REVB2H, ssa.OpLOONG64REVB2H,
ssa.OpLOONG64REVB2W, ssa.OpLOONG64REVB2W,
ssa.OpLOONG64REVB4H,
ssa.OpLOONG64REVBV, ssa.OpLOONG64REVBV,
ssa.OpLOONG64BITREV4B, ssa.OpLOONG64BITREV4B,
ssa.OpLOONG64BITREVW, ssa.OpLOONG64BITREVW,

View file

@ -136,6 +136,27 @@
(Rsh8x16 <t> x y) && !shiftIsBounded(v) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y))) (Rsh8x16 <t> x y) && !shiftIsBounded(v) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
(Rsh8x8 <t> x y) && !shiftIsBounded(v) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y))) (Rsh8x8 <t> x y) && !shiftIsBounded(v) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
// revb2h
// ((x>>8) | (x<<8)) => (REVB2H x), the type of x is uint16
((OR|XOR|ADDV) <typ.UInt16> (SRLVconst [8] <typ.UInt16> x) (SLLVconst [8] <typ.UInt16> x)) => (REVB2H x)
// ((x & 0xff00ff00)>>8) | ((x & 0x00ff00ff)<<8), the type of x is uint32
((OR|XOR|ADDV) (SRLconst [8] (ANDconst [c1] x)) (SLLconst [8] (ANDconst [c2] x)))
&& uint32(c1) == 0xff00ff00 && uint32(c2) == 0x00ff00ff
=> (REVB2H x)
// revb4h
// ((x & 0xff00ff00ff00ff00)>>8) | ((x & 0x00ff00ff00ff00ff)<<8), the type of x is uint64
((OR|XOR|ADDV) (SRLVconst [8] (AND (MOVVconst [c1]) x)) (SLLVconst [8] (AND (MOVVconst [c2]) x)))
&& uint64(c1) == 0xff00ff00ff00ff00 && uint64(c2) == 0x00ff00ff00ff00ff
=> (REVB4H x)
// ((x & 0xff00ff00)>>8) | ((x & 0x00ff00ff)<<8), the type of x is uint64
((OR|XOR|ADDV) (SRLVconst [8] (AND (MOVVconst [c1]) x)) (SLLVconst [8] (ANDconst [c2] x)))
&& uint64(c1) == 0xff00ff00 && uint64(c2) == 0x00ff00ff
=> (REVB4H (ANDconst <x.Type> [0xffffffff] x))
// bitfield ops // bitfield ops
// bstrpickv // bstrpickv

View file

@ -177,6 +177,7 @@ func init() {
{name: "REVB2H", argLength: 1, reg: gp11, asm: "REVB2H"}, // Swap bytes: 0x11223344 -> 0x22114433 (sign extends to 64 bits) {name: "REVB2H", argLength: 1, reg: gp11, asm: "REVB2H"}, // Swap bytes: 0x11223344 -> 0x22114433 (sign extends to 64 bits)
{name: "REVB2W", argLength: 1, reg: gp11, asm: "REVB2W"}, // Swap bytes: 0x1122334455667788 -> 0x4433221188776655 {name: "REVB2W", argLength: 1, reg: gp11, asm: "REVB2W"}, // Swap bytes: 0x1122334455667788 -> 0x4433221188776655
{name: "REVB4H", argLength: 1, reg: gp11, asm: "REVB4H"}, // Swap bytes: 0x1122334455667788 -> 0x2211443366558877
{name: "REVBV", argLength: 1, reg: gp11, asm: "REVBV"}, // Swap bytes: 0x1122334455667788 -> 0x8877665544332211 {name: "REVBV", argLength: 1, reg: gp11, asm: "REVBV"}, // Swap bytes: 0x1122334455667788 -> 0x8877665544332211
{name: "BITREV4B", argLength: 1, reg: gp11, asm: "BITREV4B"}, // Reverse the bits of each byte inside a 32-bit arg[0] {name: "BITREV4B", argLength: 1, reg: gp11, asm: "BITREV4B"}, // Reverse the bits of each byte inside a 32-bit arg[0]

View file

@ -1780,6 +1780,7 @@ const (
OpLOONG64CTZV OpLOONG64CTZV
OpLOONG64REVB2H OpLOONG64REVB2H
OpLOONG64REVB2W OpLOONG64REVB2W
OpLOONG64REVB4H
OpLOONG64REVBV OpLOONG64REVBV
OpLOONG64BITREV4B OpLOONG64BITREV4B
OpLOONG64BITREVW OpLOONG64BITREVW
@ -23938,6 +23939,19 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "REVB4H",
argLen: 1,
asm: loong64.AREVB4H,
reg: regInfo{
inputs: []inputInfo{
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
},
outputs: []outputInfo{
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
},
},
},
{ {
name: "REVBV", name: "REVBV",
argLen: 1, argLen: 1,

View file

@ -1784,6 +1784,148 @@ func rewriteValueLOONG64_OpLOONG64ADDF(v *Value) bool {
func rewriteValueLOONG64_OpLOONG64ADDV(v *Value) bool { func rewriteValueLOONG64_OpLOONG64ADDV(v *Value) bool {
v_1 := v.Args[1] v_1 := v.Args[1]
v_0 := v.Args[0] v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (ADDV <typ.UInt16> (SRLVconst [8] <typ.UInt16> x) (SLLVconst [8] <typ.UInt16> x))
// result: (REVB2H x)
for {
if v.Type != typ.UInt16 {
break
}
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLVconst || v_0.Type != typ.UInt16 || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
x := v_0.Args[0]
if v_1.Op != OpLOONG64SLLVconst || v_1.Type != typ.UInt16 || auxIntToInt64(v_1.AuxInt) != 8 || x != v_1.Args[0] {
continue
}
v.reset(OpLOONG64REVB2H)
v.AddArg(x)
return true
}
break
}
// match: (ADDV (SRLconst [8] (ANDconst [c1] x)) (SLLconst [8] (ANDconst [c2] x)))
// cond: uint32(c1) == 0xff00ff00 && uint32(c2) == 0x00ff00ff
// result: (REVB2H x)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLconst || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64ANDconst {
continue
}
c1 := auxIntToInt64(v_0_0.AuxInt)
x := v_0_0.Args[0]
if v_1.Op != OpLOONG64SLLconst || auxIntToInt64(v_1.AuxInt) != 8 {
continue
}
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpLOONG64ANDconst {
continue
}
c2 := auxIntToInt64(v_1_0.AuxInt)
if x != v_1_0.Args[0] || !(uint32(c1) == 0xff00ff00 && uint32(c2) == 0x00ff00ff) {
continue
}
v.reset(OpLOONG64REVB2H)
v.AddArg(x)
return true
}
break
}
// match: (ADDV (SRLVconst [8] (AND (MOVVconst [c1]) x)) (SLLVconst [8] (AND (MOVVconst [c2]) x)))
// cond: uint64(c1) == 0xff00ff00ff00ff00 && uint64(c2) == 0x00ff00ff00ff00ff
// result: (REVB4H x)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLVconst || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64AND {
continue
}
_ = v_0_0.Args[1]
v_0_0_0 := v_0_0.Args[0]
v_0_0_1 := v_0_0.Args[1]
for _i1 := 0; _i1 <= 1; _i1, v_0_0_0, v_0_0_1 = _i1+1, v_0_0_1, v_0_0_0 {
if v_0_0_0.Op != OpLOONG64MOVVconst {
continue
}
c1 := auxIntToInt64(v_0_0_0.AuxInt)
x := v_0_0_1
if v_1.Op != OpLOONG64SLLVconst || auxIntToInt64(v_1.AuxInt) != 8 {
continue
}
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpLOONG64AND {
continue
}
_ = v_1_0.Args[1]
v_1_0_0 := v_1_0.Args[0]
v_1_0_1 := v_1_0.Args[1]
for _i2 := 0; _i2 <= 1; _i2, v_1_0_0, v_1_0_1 = _i2+1, v_1_0_1, v_1_0_0 {
if v_1_0_0.Op != OpLOONG64MOVVconst {
continue
}
c2 := auxIntToInt64(v_1_0_0.AuxInt)
if x != v_1_0_1 || !(uint64(c1) == 0xff00ff00ff00ff00 && uint64(c2) == 0x00ff00ff00ff00ff) {
continue
}
v.reset(OpLOONG64REVB4H)
v.AddArg(x)
return true
}
}
}
break
}
// match: (ADDV (SRLVconst [8] (AND (MOVVconst [c1]) x)) (SLLVconst [8] (ANDconst [c2] x)))
// cond: uint64(c1) == 0xff00ff00 && uint64(c2) == 0x00ff00ff
// result: (REVB4H (ANDconst <x.Type> [0xffffffff] x))
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLVconst || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64AND {
continue
}
_ = v_0_0.Args[1]
v_0_0_0 := v_0_0.Args[0]
v_0_0_1 := v_0_0.Args[1]
for _i1 := 0; _i1 <= 1; _i1, v_0_0_0, v_0_0_1 = _i1+1, v_0_0_1, v_0_0_0 {
if v_0_0_0.Op != OpLOONG64MOVVconst {
continue
}
c1 := auxIntToInt64(v_0_0_0.AuxInt)
x := v_0_0_1
if v_1.Op != OpLOONG64SLLVconst || auxIntToInt64(v_1.AuxInt) != 8 {
continue
}
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpLOONG64ANDconst {
continue
}
c2 := auxIntToInt64(v_1_0.AuxInt)
if x != v_1_0.Args[0] || !(uint64(c1) == 0xff00ff00 && uint64(c2) == 0x00ff00ff) {
continue
}
v.reset(OpLOONG64REVB4H)
v0 := b.NewValue0(v.Pos, OpLOONG64ANDconst, x.Type)
v0.AuxInt = int64ToAuxInt(0xffffffff)
v0.AddArg(x)
v.AddArg(v0)
return true
}
}
break
}
// match: (ADDV x (MOVVconst <t> [c])) // match: (ADDV x (MOVVconst <t> [c]))
// cond: is32Bit(c) && !t.IsPtr() // cond: is32Bit(c) && !t.IsPtr()
// result: (ADDVconst [c] x) // result: (ADDVconst [c] x)
@ -5774,6 +5916,148 @@ func rewriteValueLOONG64_OpLOONG64NORconst(v *Value) bool {
func rewriteValueLOONG64_OpLOONG64OR(v *Value) bool { func rewriteValueLOONG64_OpLOONG64OR(v *Value) bool {
v_1 := v.Args[1] v_1 := v.Args[1]
v_0 := v.Args[0] v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (OR <typ.UInt16> (SRLVconst [8] <typ.UInt16> x) (SLLVconst [8] <typ.UInt16> x))
// result: (REVB2H x)
for {
if v.Type != typ.UInt16 {
break
}
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLVconst || v_0.Type != typ.UInt16 || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
x := v_0.Args[0]
if v_1.Op != OpLOONG64SLLVconst || v_1.Type != typ.UInt16 || auxIntToInt64(v_1.AuxInt) != 8 || x != v_1.Args[0] {
continue
}
v.reset(OpLOONG64REVB2H)
v.AddArg(x)
return true
}
break
}
// match: (OR (SRLconst [8] (ANDconst [c1] x)) (SLLconst [8] (ANDconst [c2] x)))
// cond: uint32(c1) == 0xff00ff00 && uint32(c2) == 0x00ff00ff
// result: (REVB2H x)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLconst || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64ANDconst {
continue
}
c1 := auxIntToInt64(v_0_0.AuxInt)
x := v_0_0.Args[0]
if v_1.Op != OpLOONG64SLLconst || auxIntToInt64(v_1.AuxInt) != 8 {
continue
}
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpLOONG64ANDconst {
continue
}
c2 := auxIntToInt64(v_1_0.AuxInt)
if x != v_1_0.Args[0] || !(uint32(c1) == 0xff00ff00 && uint32(c2) == 0x00ff00ff) {
continue
}
v.reset(OpLOONG64REVB2H)
v.AddArg(x)
return true
}
break
}
// match: (OR (SRLVconst [8] (AND (MOVVconst [c1]) x)) (SLLVconst [8] (AND (MOVVconst [c2]) x)))
// cond: uint64(c1) == 0xff00ff00ff00ff00 && uint64(c2) == 0x00ff00ff00ff00ff
// result: (REVB4H x)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLVconst || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64AND {
continue
}
_ = v_0_0.Args[1]
v_0_0_0 := v_0_0.Args[0]
v_0_0_1 := v_0_0.Args[1]
for _i1 := 0; _i1 <= 1; _i1, v_0_0_0, v_0_0_1 = _i1+1, v_0_0_1, v_0_0_0 {
if v_0_0_0.Op != OpLOONG64MOVVconst {
continue
}
c1 := auxIntToInt64(v_0_0_0.AuxInt)
x := v_0_0_1
if v_1.Op != OpLOONG64SLLVconst || auxIntToInt64(v_1.AuxInt) != 8 {
continue
}
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpLOONG64AND {
continue
}
_ = v_1_0.Args[1]
v_1_0_0 := v_1_0.Args[0]
v_1_0_1 := v_1_0.Args[1]
for _i2 := 0; _i2 <= 1; _i2, v_1_0_0, v_1_0_1 = _i2+1, v_1_0_1, v_1_0_0 {
if v_1_0_0.Op != OpLOONG64MOVVconst {
continue
}
c2 := auxIntToInt64(v_1_0_0.AuxInt)
if x != v_1_0_1 || !(uint64(c1) == 0xff00ff00ff00ff00 && uint64(c2) == 0x00ff00ff00ff00ff) {
continue
}
v.reset(OpLOONG64REVB4H)
v.AddArg(x)
return true
}
}
}
break
}
// match: (OR (SRLVconst [8] (AND (MOVVconst [c1]) x)) (SLLVconst [8] (ANDconst [c2] x)))
// cond: uint64(c1) == 0xff00ff00 && uint64(c2) == 0x00ff00ff
// result: (REVB4H (ANDconst <x.Type> [0xffffffff] x))
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLVconst || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64AND {
continue
}
_ = v_0_0.Args[1]
v_0_0_0 := v_0_0.Args[0]
v_0_0_1 := v_0_0.Args[1]
for _i1 := 0; _i1 <= 1; _i1, v_0_0_0, v_0_0_1 = _i1+1, v_0_0_1, v_0_0_0 {
if v_0_0_0.Op != OpLOONG64MOVVconst {
continue
}
c1 := auxIntToInt64(v_0_0_0.AuxInt)
x := v_0_0_1
if v_1.Op != OpLOONG64SLLVconst || auxIntToInt64(v_1.AuxInt) != 8 {
continue
}
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpLOONG64ANDconst {
continue
}
c2 := auxIntToInt64(v_1_0.AuxInt)
if x != v_1_0.Args[0] || !(uint64(c1) == 0xff00ff00 && uint64(c2) == 0x00ff00ff) {
continue
}
v.reset(OpLOONG64REVB4H)
v0 := b.NewValue0(v.Pos, OpLOONG64ANDconst, x.Type)
v0.AuxInt = int64ToAuxInt(0xffffffff)
v0.AddArg(x)
v.AddArg(v0)
return true
}
}
break
}
// match: (OR x (MOVVconst [c])) // match: (OR x (MOVVconst [c]))
// cond: is32Bit(c) // cond: is32Bit(c)
// result: (ORconst [c] x) // result: (ORconst [c] x)
@ -7245,6 +7529,148 @@ func rewriteValueLOONG64_OpLOONG64SUBVconst(v *Value) bool {
func rewriteValueLOONG64_OpLOONG64XOR(v *Value) bool { func rewriteValueLOONG64_OpLOONG64XOR(v *Value) bool {
v_1 := v.Args[1] v_1 := v.Args[1]
v_0 := v.Args[0] v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (XOR <typ.UInt16> (SRLVconst [8] <typ.UInt16> x) (SLLVconst [8] <typ.UInt16> x))
// result: (REVB2H x)
for {
if v.Type != typ.UInt16 {
break
}
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLVconst || v_0.Type != typ.UInt16 || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
x := v_0.Args[0]
if v_1.Op != OpLOONG64SLLVconst || v_1.Type != typ.UInt16 || auxIntToInt64(v_1.AuxInt) != 8 || x != v_1.Args[0] {
continue
}
v.reset(OpLOONG64REVB2H)
v.AddArg(x)
return true
}
break
}
// match: (XOR (SRLconst [8] (ANDconst [c1] x)) (SLLconst [8] (ANDconst [c2] x)))
// cond: uint32(c1) == 0xff00ff00 && uint32(c2) == 0x00ff00ff
// result: (REVB2H x)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLconst || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64ANDconst {
continue
}
c1 := auxIntToInt64(v_0_0.AuxInt)
x := v_0_0.Args[0]
if v_1.Op != OpLOONG64SLLconst || auxIntToInt64(v_1.AuxInt) != 8 {
continue
}
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpLOONG64ANDconst {
continue
}
c2 := auxIntToInt64(v_1_0.AuxInt)
if x != v_1_0.Args[0] || !(uint32(c1) == 0xff00ff00 && uint32(c2) == 0x00ff00ff) {
continue
}
v.reset(OpLOONG64REVB2H)
v.AddArg(x)
return true
}
break
}
// match: (XOR (SRLVconst [8] (AND (MOVVconst [c1]) x)) (SLLVconst [8] (AND (MOVVconst [c2]) x)))
// cond: uint64(c1) == 0xff00ff00ff00ff00 && uint64(c2) == 0x00ff00ff00ff00ff
// result: (REVB4H x)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLVconst || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64AND {
continue
}
_ = v_0_0.Args[1]
v_0_0_0 := v_0_0.Args[0]
v_0_0_1 := v_0_0.Args[1]
for _i1 := 0; _i1 <= 1; _i1, v_0_0_0, v_0_0_1 = _i1+1, v_0_0_1, v_0_0_0 {
if v_0_0_0.Op != OpLOONG64MOVVconst {
continue
}
c1 := auxIntToInt64(v_0_0_0.AuxInt)
x := v_0_0_1
if v_1.Op != OpLOONG64SLLVconst || auxIntToInt64(v_1.AuxInt) != 8 {
continue
}
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpLOONG64AND {
continue
}
_ = v_1_0.Args[1]
v_1_0_0 := v_1_0.Args[0]
v_1_0_1 := v_1_0.Args[1]
for _i2 := 0; _i2 <= 1; _i2, v_1_0_0, v_1_0_1 = _i2+1, v_1_0_1, v_1_0_0 {
if v_1_0_0.Op != OpLOONG64MOVVconst {
continue
}
c2 := auxIntToInt64(v_1_0_0.AuxInt)
if x != v_1_0_1 || !(uint64(c1) == 0xff00ff00ff00ff00 && uint64(c2) == 0x00ff00ff00ff00ff) {
continue
}
v.reset(OpLOONG64REVB4H)
v.AddArg(x)
return true
}
}
}
break
}
// match: (XOR (SRLVconst [8] (AND (MOVVconst [c1]) x)) (SLLVconst [8] (ANDconst [c2] x)))
// cond: uint64(c1) == 0xff00ff00 && uint64(c2) == 0x00ff00ff
// result: (REVB4H (ANDconst <x.Type> [0xffffffff] x))
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
if v_0.Op != OpLOONG64SRLVconst || auxIntToInt64(v_0.AuxInt) != 8 {
continue
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpLOONG64AND {
continue
}
_ = v_0_0.Args[1]
v_0_0_0 := v_0_0.Args[0]
v_0_0_1 := v_0_0.Args[1]
for _i1 := 0; _i1 <= 1; _i1, v_0_0_0, v_0_0_1 = _i1+1, v_0_0_1, v_0_0_0 {
if v_0_0_0.Op != OpLOONG64MOVVconst {
continue
}
c1 := auxIntToInt64(v_0_0_0.AuxInt)
x := v_0_0_1
if v_1.Op != OpLOONG64SLLVconst || auxIntToInt64(v_1.AuxInt) != 8 {
continue
}
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpLOONG64ANDconst {
continue
}
c2 := auxIntToInt64(v_1_0.AuxInt)
if x != v_1_0.Args[0] || !(uint64(c1) == 0xff00ff00 && uint64(c2) == 0x00ff00ff) {
continue
}
v.reset(OpLOONG64REVB4H)
v0 := b.NewValue0(v.Pos, OpLOONG64ANDconst, x.Type)
v0.AuxInt = int64ToAuxInt(0xffffffff)
v0.AddArg(x)
v.AddArg(v0)
return true
}
}
break
}
// match: (XOR x (MOVVconst [c])) // match: (XOR x (MOVVconst [c]))
// cond: is32Bit(c) // cond: is32Bit(c)
// result: (XORconst [c] x) // result: (XORconst [c] x)

View file

@ -338,20 +338,26 @@ func shift_no_cmp(x int) int {
func rev16(c uint64) (uint64, uint64, uint64) { func rev16(c uint64) (uint64, uint64, uint64) {
// arm64:`REV16`,-`AND`,-`LSR`,-`AND`,-`ORR\tR[0-9]+<<8` // arm64:`REV16`,-`AND`,-`LSR`,-`AND`,-`ORR\tR[0-9]+<<8`
// loong64:`REVB4H`,-`MOVV`,-`AND`,-`SRLV`,-`AND`,-`SLLV`,-`OR`
b1 := ((c & 0xff00ff00ff00ff00) >> 8) | ((c & 0x00ff00ff00ff00ff) << 8) b1 := ((c & 0xff00ff00ff00ff00) >> 8) | ((c & 0x00ff00ff00ff00ff) << 8)
// arm64:-`ADD\tR[0-9]+<<8` // arm64:-`ADD\tR[0-9]+<<8`
// loong64:-`ADDV`
b2 := ((c & 0xff00ff00ff00ff00) >> 8) + ((c & 0x00ff00ff00ff00ff) << 8) b2 := ((c & 0xff00ff00ff00ff00) >> 8) + ((c & 0x00ff00ff00ff00ff) << 8)
// arm64:-`EOR\tR[0-9]+<<8` // arm64:-`EOR\tR[0-9]+<<8`
// loong64:-`XOR`
b3 := ((c & 0xff00ff00ff00ff00) >> 8) ^ ((c & 0x00ff00ff00ff00ff) << 8) b3 := ((c & 0xff00ff00ff00ff00) >> 8) ^ ((c & 0x00ff00ff00ff00ff) << 8)
return b1, b2, b3 return b1, b2, b3
} }
func rev16w(c uint32) (uint32, uint32, uint32) { func rev16w(c uint32) (uint32, uint32, uint32) {
// arm64:`REV16W`,-`AND`,-`UBFX`,-`AND`,-`ORR\tR[0-9]+<<8` // arm64:`REV16W`,-`AND`,-`UBFX`,-`AND`,-`ORR\tR[0-9]+<<8`
// loong64:`REVB2H`,-`AND`,-`SRL`,-`AND`,-`SLL`,-`OR`
b1 := ((c & 0xff00ff00) >> 8) | ((c & 0x00ff00ff) << 8) b1 := ((c & 0xff00ff00) >> 8) | ((c & 0x00ff00ff) << 8)
// arm64:-`ADD\tR[0-9]+<<8` // arm64:-`ADD\tR[0-9]+<<8`
// loong64:-`ADDV`
b2 := ((c & 0xff00ff00) >> 8) + ((c & 0x00ff00ff) << 8) b2 := ((c & 0xff00ff00) >> 8) + ((c & 0x00ff00ff) << 8)
// arm64:-`EOR\tR[0-9]+<<8` // arm64:-`EOR\tR[0-9]+<<8`
// loong64:-`XOR`
b3 := ((c & 0xff00ff00) >> 8) ^ ((c & 0x00ff00ff) << 8) b3 := ((c & 0xff00ff00) >> 8) ^ ((c & 0x00ff00ff) << 8)
return b1, b2, b3 return b1, b2, b3
} }