]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: sign or zero extend for 32 bit equality on riscv64
authorJoel Sing <joel@sing.id.au>
Wed, 19 Oct 2022 05:43:22 +0000 (16:43 +1100)
committerJoel Sing <joel@sing.id.au>
Tue, 15 Aug 2023 03:29:11 +0000 (03:29 +0000)
For 32 bit equality (Eq32), rather than always zero extending to 64 bits,
sign extend for signed types and zero extend for unsigned types. This makes
no difference to the equality test (via SUB), however it increases the
likelihood of avoiding unnecessary sign or zero extension simply for the
purpose of equality testing.

While here, replace the Neq* rules with (Not (Eq*)) - this makes no
difference to the generated code (as the intermediates get expanded and
eliminated), however it means that changes to the equality rules also
reflect in the inequality rules.

As an example, the following:

   lw      t0,956(t0)
   slli    t0,t0,0x20
   srli    t0,t0,0x20
   li      t1,1
   bne     t1,t0,278fc

Becomes:

   lw      t0,1024(t0)
   li      t1,1
   bne     t1,t0,278b0

Removes almost 1000 instructions from the Go binary on riscv64.

Change-Id: Iac60635f494f6db87faa47752bd1cc16e6b5967f
Reviewed-on: https://go-review.googlesource.com/c/go/+/516595
Run-TryBot: Joel Sing <joel@sing.id.au>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: M Zhuo <mzh@golangcn.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/cmd/compile/internal/ssa/_gen/RISCV64.rules
src/cmd/compile/internal/ssa/rewriteRISCV64.go

index d90427132ca26a4b1969429af024c5b1eaf0616a..181b46a7ced98db8c96a51c03a8629acfa6dca12 100644 (file)
 
 (EqPtr x y) => (SEQZ (SUB <typ.Uintptr> x y))
 (Eq64  x y) => (SEQZ (SUB <x.Type> x y))
-(Eq32  x y) => (SEQZ (SUB <x.Type> (ZeroExt32to64 x) (ZeroExt32to64 y)))
+(Eq32  x y) &&  x.Type.IsSigned() => (SEQZ (SUB <x.Type> (SignExt32to64 x) (SignExt32to64 y)))
+(Eq32  x y) && !x.Type.IsSigned() => (SEQZ (SUB <x.Type> (ZeroExt32to64 x) (ZeroExt32to64 y)))
 (Eq16  x y) => (SEQZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
 (Eq8   x y) => (SEQZ (SUB <x.Type> (ZeroExt8to64  x) (ZeroExt8to64  y)))
 (Eq(64|32)F ...) => (FEQ(D|S) ...)
 
-(NeqPtr x y) => (SNEZ (SUB <typ.Uintptr> x y))
-(Neq64  x y) => (SNEZ (SUB <x.Type> x y))
-(Neq32  x y) => (SNEZ (SUB <x.Type> (ZeroExt32to64 x) (ZeroExt32to64 y)))
-(Neq16  x y) => (SNEZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
-(Neq8   x y) => (SNEZ (SUB <x.Type> (ZeroExt8to64  x) (ZeroExt8to64  y)))
+(NeqPtr x y) => (Not (EqPtr x y))
+(Neq64  x y) => (Not (Eq64  x y))
+(Neq32  x y) => (Not (Eq32  x y))
+(Neq16  x y) => (Not (Eq16  x y))
+(Neq8   x y) => (Not (Eq8   x y))
 (Neq(64|32)F ...) => (FNE(D|S) ...)
 
 // Loads
index ffbeb1df47618fc7c6bc5b789676624da8ccd5e2..e8002599efe88e5a15af668c3205487137acb2b7 100644 (file)
@@ -1081,20 +1081,50 @@ func rewriteValueRISCV64_OpEq32(v *Value) bool {
        b := v.Block
        typ := &b.Func.Config.Types
        // match: (Eq32 x y)
+       // cond: x.Type.IsSigned()
+       // result: (SEQZ (SUB <x.Type> (SignExt32to64 x) (SignExt32to64 y)))
+       for {
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       x := v_0
+                       y := v_1
+                       if !(x.Type.IsSigned()) {
+                               continue
+                       }
+                       v.reset(OpRISCV64SEQZ)
+                       v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+                       v1 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+                       v1.AddArg(x)
+                       v2 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64)
+                       v2.AddArg(y)
+                       v0.AddArg2(v1, v2)
+                       v.AddArg(v0)
+                       return true
+               }
+               break
+       }
+       // match: (Eq32 x y)
+       // cond: !x.Type.IsSigned()
        // result: (SEQZ (SUB <x.Type> (ZeroExt32to64 x) (ZeroExt32to64 y)))
        for {
-               x := v_0
-               y := v_1
-               v.reset(OpRISCV64SEQZ)
-               v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
-               v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
-               v1.AddArg(x)
-               v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
-               v2.AddArg(y)
-               v0.AddArg2(v1, v2)
-               v.AddArg(v0)
-               return true
+               for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+                       x := v_0
+                       y := v_1
+                       if !(!x.Type.IsSigned()) {
+                               continue
+                       }
+                       v.reset(OpRISCV64SEQZ)
+                       v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+                       v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+                       v1.AddArg(x)
+                       v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
+                       v2.AddArg(y)
+                       v0.AddArg2(v1, v2)
+                       v.AddArg(v0)
+                       return true
+               }
+               break
        }
+       return false
 }
 func rewriteValueRISCV64_OpEq64(v *Value) bool {
        v_1 := v.Args[1]
@@ -2942,17 +2972,13 @@ func rewriteValueRISCV64_OpNeq16(v *Value) bool {
        b := v.Block
        typ := &b.Func.Config.Types
        // match: (Neq16 x y)
-       // result: (SNEZ (SUB <x.Type> (ZeroExt16to64 x) (ZeroExt16to64 y)))
+       // result: (Not (Eq16 x y))
        for {
                x := v_0
                y := v_1
-               v.reset(OpRISCV64SNEZ)
-               v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
-               v1 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
-               v1.AddArg(x)
-               v2 := b.NewValue0(v.Pos, OpZeroExt16to64, typ.UInt64)
-               v2.AddArg(y)
-               v0.AddArg2(v1, v2)
+               v.reset(OpNot)
+               v0 := b.NewValue0(v.Pos, OpEq16, typ.Bool)
+               v0.AddArg2(x, y)
                v.AddArg(v0)
                return true
        }
@@ -2963,17 +2989,13 @@ func rewriteValueRISCV64_OpNeq32(v *Value) bool {
        b := v.Block
        typ := &b.Func.Config.Types
        // match: (Neq32 x y)
-       // result: (SNEZ (SUB <x.Type> (ZeroExt32to64 x) (ZeroExt32to64 y)))
+       // result: (Not (Eq32 x y))
        for {
                x := v_0
                y := v_1
-               v.reset(OpRISCV64SNEZ)
-               v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
-               v1 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
-               v1.AddArg(x)
-               v2 := b.NewValue0(v.Pos, OpZeroExt32to64, typ.UInt64)
-               v2.AddArg(y)
-               v0.AddArg2(v1, v2)
+               v.reset(OpNot)
+               v0 := b.NewValue0(v.Pos, OpEq32, typ.Bool)
+               v0.AddArg2(x, y)
                v.AddArg(v0)
                return true
        }
@@ -2982,13 +3004,14 @@ func rewriteValueRISCV64_OpNeq64(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
        b := v.Block
+       typ := &b.Func.Config.Types
        // match: (Neq64 x y)
-       // result: (SNEZ (SUB <x.Type> x y))
+       // result: (Not (Eq64 x y))
        for {
                x := v_0
                y := v_1
-               v.reset(OpRISCV64SNEZ)
-               v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
+               v.reset(OpNot)
+               v0 := b.NewValue0(v.Pos, OpEq64, typ.Bool)
                v0.AddArg2(x, y)
                v.AddArg(v0)
                return true
@@ -3000,17 +3023,13 @@ func rewriteValueRISCV64_OpNeq8(v *Value) bool {
        b := v.Block
        typ := &b.Func.Config.Types
        // match: (Neq8 x y)
-       // result: (SNEZ (SUB <x.Type> (ZeroExt8to64 x) (ZeroExt8to64 y)))
+       // result: (Not (Eq8 x y))
        for {
                x := v_0
                y := v_1
-               v.reset(OpRISCV64SNEZ)
-               v0 := b.NewValue0(v.Pos, OpRISCV64SUB, x.Type)
-               v1 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
-               v1.AddArg(x)
-               v2 := b.NewValue0(v.Pos, OpZeroExt8to64, typ.UInt64)
-               v2.AddArg(y)
-               v0.AddArg2(v1, v2)
+               v.reset(OpNot)
+               v0 := b.NewValue0(v.Pos, OpEq8, typ.Bool)
+               v0.AddArg2(x, y)
                v.AddArg(v0)
                return true
        }
@@ -3038,12 +3057,12 @@ func rewriteValueRISCV64_OpNeqPtr(v *Value) bool {
        b := v.Block
        typ := &b.Func.Config.Types
        // match: (NeqPtr x y)
-       // result: (SNEZ (SUB <typ.Uintptr> x y))
+       // result: (Not (EqPtr x y))
        for {
                x := v_0
                y := v_1
-               v.reset(OpRISCV64SNEZ)
-               v0 := b.NewValue0(v.Pos, OpRISCV64SUB, typ.Uintptr)
+               v.reset(OpNot)
+               v0 := b.NewValue0(v.Pos, OpEqPtr, typ.Bool)
                v0.AddArg2(x, y)
                v.AddArg(v0)
                return true