]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: optimize some patterns into revb2h/revb4h instruction on loong64
authorXiaolin Zhao <zhaoxiaolin@loongson.cn>
Fri, 15 Aug 2025 08:19:01 +0000 (16:19 +0800)
committerGopher Robot <gobot@golang.org>
Thu, 21 Aug 2025 18:19:34 +0000 (11:19 -0700)
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>

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
test/codegen/bitfield.go

index c7fb903d5d646094351e982a4eb7fe2a775aaba0..d9bf721565bd9d9f7042e5e18423bbc479815fef 100644 (file)
@@ -543,6 +543,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
                ssa.OpLOONG64SQRTF,
                ssa.OpLOONG64REVB2H,
                ssa.OpLOONG64REVB2W,
+               ssa.OpLOONG64REVB4H,
                ssa.OpLOONG64REVBV,
                ssa.OpLOONG64BITREV4B,
                ssa.OpLOONG64BITREVW,
index 75b5e3806b0bab47b9cdbfe8be98b3eefbdb083e..1b7d4049c64b5fd5b05cdf5b9ce3bb38c50a36c2 100644 (file)
 (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)))
 
+
+// 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
 
 // bstrpickv
index d6818e8592ee166bf444394e7a6e887263251977..277998efbbccb3b84b224230c628a03105c1caac 100644 (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: "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: "BITREV4B", argLength: 1, reg: gp11, asm: "BITREV4B"}, // Reverse the bits of each byte inside a 32-bit arg[0]
index 3536cfcd75d22f9e6997e9cc062401d3742fbc8f..6d9297acfd2746610782f28c0c43703432f33aff 100644 (file)
@@ -1780,6 +1780,7 @@ const (
        OpLOONG64CTZV
        OpLOONG64REVB2H
        OpLOONG64REVB2W
+       OpLOONG64REVB4H
        OpLOONG64REVBV
        OpLOONG64BITREV4B
        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",
                argLen: 1,
index df4ac818ddafb229f1bc9848075cf61d171b18a8..8d29912f4071154562a1efa41e3983d46926ac22 100644 (file)
@@ -1784,6 +1784,148 @@ func rewriteValueLOONG64_OpLOONG64ADDF(v *Value) bool {
 func rewriteValueLOONG64_OpLOONG64ADDV(v *Value) bool {
        v_1 := v.Args[1]
        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]))
        // cond: is32Bit(c) && !t.IsPtr()
        // result: (ADDVconst [c] x)
@@ -5774,6 +5916,148 @@ func rewriteValueLOONG64_OpLOONG64NORconst(v *Value) bool {
 func rewriteValueLOONG64_OpLOONG64OR(v *Value) bool {
        v_1 := v.Args[1]
        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]))
        // cond: is32Bit(c)
        // result: (ORconst [c] x)
@@ -7245,6 +7529,148 @@ func rewriteValueLOONG64_OpLOONG64SUBVconst(v *Value) bool {
 func rewriteValueLOONG64_OpLOONG64XOR(v *Value) bool {
        v_1 := v.Args[1]
        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]))
        // cond: is32Bit(c)
        // result: (XORconst [c] x)
index 44cf09f86f4e1f3bacb0f3c3a92da3ece30da6ee..6374d70650ce5502f7397a4bca967a2a1e3eff1b 100644 (file)
@@ -338,20 +338,26 @@ func shift_no_cmp(x int) int {
 
 func rev16(c uint64) (uint64, uint64, uint64) {
        // 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)
        // arm64:-`ADD\tR[0-9]+<<8`
+       // loong64:-`ADDV`
        b2 := ((c & 0xff00ff00ff00ff00) >> 8) + ((c & 0x00ff00ff00ff00ff) << 8)
        // arm64:-`EOR\tR[0-9]+<<8`
+       // loong64:-`XOR`
        b3 := ((c & 0xff00ff00ff00ff00) >> 8) ^ ((c & 0x00ff00ff00ff00ff) << 8)
        return b1, b2, b3
 }
 
 func rev16w(c uint32) (uint32, uint32, uint32) {
        // arm64:`REV16W`,-`AND`,-`UBFX`,-`AND`,-`ORR\tR[0-9]+<<8`
+       // loong64:`REVB2H`,-`AND`,-`SRL`,-`AND`,-`SLL`,-`OR`
        b1 := ((c & 0xff00ff00) >> 8) | ((c & 0x00ff00ff) << 8)
        // arm64:-`ADD\tR[0-9]+<<8`
+       // loong64:-`ADDV`
        b2 := ((c & 0xff00ff00) >> 8) + ((c & 0x00ff00ff) << 8)
        // arm64:-`EOR\tR[0-9]+<<8`
+       // loong64:-`XOR`
        b3 := ((c & 0xff00ff00) >> 8) ^ ((c & 0x00ff00ff) << 8)
        return b1, b2, b3
 }