From 9632ba8160dd93107af3577334bcadfe40068e42 Mon Sep 17 00:00:00 2001 From: Xiaolin Zhao Date: Fri, 15 Aug 2025 16:19:01 +0800 Subject: [PATCH] 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 Reviewed-by: Keith Randall Auto-Submit: Keith Randall Reviewed-by: Carlos Amedee Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI --- src/cmd/compile/internal/loong64/ssa.go | 1 + .../compile/internal/ssa/_gen/LOONG64.rules | 21 + .../compile/internal/ssa/_gen/LOONG64Ops.go | 1 + src/cmd/compile/internal/ssa/opGen.go | 14 + .../compile/internal/ssa/rewriteLOONG64.go | 426 ++++++++++++++++++ test/codegen/bitfield.go | 6 + 6 files changed, 469 insertions(+) diff --git a/src/cmd/compile/internal/loong64/ssa.go b/src/cmd/compile/internal/loong64/ssa.go index c7fb903d5d..d9bf721565 100644 --- a/src/cmd/compile/internal/loong64/ssa.go +++ b/src/cmd/compile/internal/loong64/ssa.go @@ -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, diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules index 75b5e3806b..1b7d4049c6 100644 --- a/src/cmd/compile/internal/ssa/_gen/LOONG64.rules +++ b/src/cmd/compile/internal/ssa/_gen/LOONG64.rules @@ -136,6 +136,27 @@ (Rsh8x16 x y) && !shiftIsBounded(v) => (SRAV (SignExt8to64 x) (OR (NEGV (SGTU (ZeroExt16to64 y) (MOVVconst [63]))) (ZeroExt16to64 y))) (Rsh8x8 x y) && !shiftIsBounded(v) => (SRAV (SignExt8to64 x) (OR (NEGV (SGTU (ZeroExt8to64 y) (MOVVconst [63]))) (ZeroExt8to64 y))) + +// revb2h +// ((x>>8) | (x<<8)) => (REVB2H x), the type of x is uint16 +((OR|XOR|ADDV) (SRLVconst [8] x) (SLLVconst [8] 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 [0xffffffff] x)) + // bitfield ops // bstrpickv diff --git a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go index d6818e8592..277998efbb 100644 --- a/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go +++ b/src/cmd/compile/internal/ssa/_gen/LOONG64Ops.go @@ -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] diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 3536cfcd75..6d9297acfd 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -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, diff --git a/src/cmd/compile/internal/ssa/rewriteLOONG64.go b/src/cmd/compile/internal/ssa/rewriteLOONG64.go index df4ac818dd..8d29912f40 100644 --- a/src/cmd/compile/internal/ssa/rewriteLOONG64.go +++ b/src/cmd/compile/internal/ssa/rewriteLOONG64.go @@ -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 (SRLVconst [8] x) (SLLVconst [8] 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 [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 [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 (SRLVconst [8] x) (SLLVconst [8] 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 [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 (SRLVconst [8] x) (SLLVconst [8] 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 [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) diff --git a/test/codegen/bitfield.go b/test/codegen/bitfield.go index 44cf09f86f..6374d70650 100644 --- a/test/codegen/bitfield.go +++ b/test/codegen/bitfield.go @@ -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 } -- 2.52.0