]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: optimise branchs on riscv64
authorJoel Sing <joel@sing.id.au>
Mon, 30 Mar 2020 15:04:45 +0000 (02:04 +1100)
committerJoel Sing <joel@sing.id.au>
Sun, 10 May 2020 14:43:46 +0000 (14:43 +0000)
Make use of multi-control values and branch pseudo-instructions to optimise
compiler generated branches.

Change-Id: I7a8bf754db3c2082a390bf6a662ccf18cbcbee39
Reviewed-on: https://go-review.googlesource.com/c/go/+/226400
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/ssa/gen/RISCV64.rules
src/cmd/compile/internal/ssa/rewriteRISCV64.go

index fbd87360ac839047ddded22e3679af35dd6268d6..9437c8e9d4b33338ba12f0003d44c95f9833f038 100644 (file)
 (Addr {sym} base) => (MOVaddr {sym} [0] base)
 (LocalAddr {sym} base _) => (MOVaddr {sym} base)
 
-// Conditional branches
-//
-// cond is 1 if true.
-//
-// TODO(prattmic): RISCV branch instructions take two operands to compare,
-// so we could generate more efficient code by computing the condition in the
-// branch itself. This should be revisited now that the compiler has support
-// for two control values (https://golang.org/cl/196557).
-(If cond yes no) => (BNEZ cond yes no)
-
 // Calls
 (StaticCall  ...) => (CALLstatic  ...)
 (ClosureCall ...) => (CALLclosure ...)
 (AtomicExchange32 ...) => (LoweredAtomicExchange32 ...)
 (AtomicExchange64 ...) => (LoweredAtomicExchange64 ...)
 
+// Conditional branches
+(If cond yes no) => (BNEZ cond yes no)
+
 // Optimizations
 
-// Absorb SNEZ into branch.
+// Absorb SEQZ/SNEZ into branch.
+(BEQZ (SEQZ x) yes no) => (BNEZ x yes no)
+(BEQZ (SNEZ x) yes no) => (BEQZ x yes no)
+(BNEZ (SEQZ x) yes no) => (BEQZ x yes no)
 (BNEZ (SNEZ x) yes no) => (BNEZ x yes no)
 
+// Convert BEQZ/BNEZ into more optimal branch conditions.
+(BEQZ (SUB x y) yes no) => (BEQ x y yes no)
+(BNEZ (SUB x y) yes no) => (BNE x y yes no)
+(BEQZ (SLT x y) yes no) => (BGE x y yes no)
+(BNEZ (SLT x y) yes no) => (BLT x y yes no)
+(BEQZ (SLTU x y) yes no) => (BGEU x y yes no)
+(BNEZ (SLTU x y) yes no) => (BLTU x y yes no)
+
+// Convert branch with zero to BEQZ/BNEZ.
+(BEQ (MOVDconst [0]) cond yes no) => (BEQZ cond yes no)
+(BEQ cond (MOVDconst [0]) yes no) => (BEQZ cond yes no)
+(BNE (MOVDconst [0]) cond yes no) => (BNEZ cond yes no)
+(BNE cond (MOVDconst [0]) yes no) => (BNEZ cond yes no)
+
 // Store zero
 (MOVBstore [off] {sym} ptr (MOVBconst [0]) mem) => (MOVBstorezero [off] {sym} ptr mem)
 (MOVHstore [off] {sym} ptr (MOVHconst [0]) mem) => (MOVHstorezero [off] {sym} ptr mem)
index 6b91c08628b544399da4782144257dfd1ccb1bfc..c178290343ab8c19627f20c866fb2d7b78d0c0fc 100644 (file)
@@ -5120,7 +5120,105 @@ func rewriteValueRISCV64_OpZeroExt8to64(v *Value) bool {
 }
 func rewriteBlockRISCV64(b *Block) bool {
        switch b.Kind {
+       case BlockRISCV64BEQ:
+               // match: (BEQ (MOVDconst [0]) cond yes no)
+               // result: (BEQZ cond yes no)
+               for b.Controls[0].Op == OpRISCV64MOVDconst {
+                       v_0 := b.Controls[0]
+                       if auxIntToInt64(v_0.AuxInt) != 0 {
+                               break
+                       }
+                       cond := b.Controls[1]
+                       b.resetWithControl(BlockRISCV64BEQZ, cond)
+                       return true
+               }
+               // match: (BEQ cond (MOVDconst [0]) yes no)
+               // result: (BEQZ cond yes no)
+               for b.Controls[1].Op == OpRISCV64MOVDconst {
+                       cond := b.Controls[0]
+                       v_1 := b.Controls[1]
+                       if auxIntToInt64(v_1.AuxInt) != 0 {
+                               break
+                       }
+                       b.resetWithControl(BlockRISCV64BEQZ, cond)
+                       return true
+               }
+       case BlockRISCV64BEQZ:
+               // match: (BEQZ (SEQZ x) yes no)
+               // result: (BNEZ x yes no)
+               for b.Controls[0].Op == OpRISCV64SEQZ {
+                       v_0 := b.Controls[0]
+                       x := v_0.Args[0]
+                       b.resetWithControl(BlockRISCV64BNEZ, x)
+                       return true
+               }
+               // match: (BEQZ (SNEZ x) yes no)
+               // result: (BEQZ x yes no)
+               for b.Controls[0].Op == OpRISCV64SNEZ {
+                       v_0 := b.Controls[0]
+                       x := v_0.Args[0]
+                       b.resetWithControl(BlockRISCV64BEQZ, x)
+                       return true
+               }
+               // match: (BEQZ (SUB x y) yes no)
+               // result: (BEQ x y yes no)
+               for b.Controls[0].Op == OpRISCV64SUB {
+                       v_0 := b.Controls[0]
+                       y := v_0.Args[1]
+                       x := v_0.Args[0]
+                       b.resetWithControl2(BlockRISCV64BEQ, x, y)
+                       return true
+               }
+               // match: (BEQZ (SLT x y) yes no)
+               // result: (BGE x y yes no)
+               for b.Controls[0].Op == OpRISCV64SLT {
+                       v_0 := b.Controls[0]
+                       y := v_0.Args[1]
+                       x := v_0.Args[0]
+                       b.resetWithControl2(BlockRISCV64BGE, x, y)
+                       return true
+               }
+               // match: (BEQZ (SLTU x y) yes no)
+               // result: (BGEU x y yes no)
+               for b.Controls[0].Op == OpRISCV64SLTU {
+                       v_0 := b.Controls[0]
+                       y := v_0.Args[1]
+                       x := v_0.Args[0]
+                       b.resetWithControl2(BlockRISCV64BGEU, x, y)
+                       return true
+               }
+       case BlockRISCV64BNE:
+               // match: (BNE (MOVDconst [0]) cond yes no)
+               // result: (BNEZ cond yes no)
+               for b.Controls[0].Op == OpRISCV64MOVDconst {
+                       v_0 := b.Controls[0]
+                       if auxIntToInt64(v_0.AuxInt) != 0 {
+                               break
+                       }
+                       cond := b.Controls[1]
+                       b.resetWithControl(BlockRISCV64BNEZ, cond)
+                       return true
+               }
+               // match: (BNE cond (MOVDconst [0]) yes no)
+               // result: (BNEZ cond yes no)
+               for b.Controls[1].Op == OpRISCV64MOVDconst {
+                       cond := b.Controls[0]
+                       v_1 := b.Controls[1]
+                       if auxIntToInt64(v_1.AuxInt) != 0 {
+                               break
+                       }
+                       b.resetWithControl(BlockRISCV64BNEZ, cond)
+                       return true
+               }
        case BlockRISCV64BNEZ:
+               // match: (BNEZ (SEQZ x) yes no)
+               // result: (BEQZ x yes no)
+               for b.Controls[0].Op == OpRISCV64SEQZ {
+                       v_0 := b.Controls[0]
+                       x := v_0.Args[0]
+                       b.resetWithControl(BlockRISCV64BEQZ, x)
+                       return true
+               }
                // match: (BNEZ (SNEZ x) yes no)
                // result: (BNEZ x yes no)
                for b.Controls[0].Op == OpRISCV64SNEZ {
@@ -5129,6 +5227,33 @@ func rewriteBlockRISCV64(b *Block) bool {
                        b.resetWithControl(BlockRISCV64BNEZ, x)
                        return true
                }
+               // match: (BNEZ (SUB x y) yes no)
+               // result: (BNE x y yes no)
+               for b.Controls[0].Op == OpRISCV64SUB {
+                       v_0 := b.Controls[0]
+                       y := v_0.Args[1]
+                       x := v_0.Args[0]
+                       b.resetWithControl2(BlockRISCV64BNE, x, y)
+                       return true
+               }
+               // match: (BNEZ (SLT x y) yes no)
+               // result: (BLT x y yes no)
+               for b.Controls[0].Op == OpRISCV64SLT {
+                       v_0 := b.Controls[0]
+                       y := v_0.Args[1]
+                       x := v_0.Args[0]
+                       b.resetWithControl2(BlockRISCV64BLT, x, y)
+                       return true
+               }
+               // match: (BNEZ (SLTU x y) yes no)
+               // result: (BLTU x y yes no)
+               for b.Controls[0].Op == OpRISCV64SLTU {
+                       v_0 := b.Controls[0]
+                       y := v_0.Args[1]
+                       x := v_0.Args[0]
+                       b.resetWithControl2(BlockRISCV64BLTU, x, y)
+                       return true
+               }
        case BlockIf:
                // match: (If cond yes no)
                // result: (BNEZ cond yes no)