diff options
author | Michael Munday <mike.munday@ibm.com> | 2020-04-17 05:05:07 -0700 |
---|---|---|
committer | Michael Munday <mike.munday@ibm.com> | 2020-04-21 19:23:51 +0000 |
commit | e464d7d7970be972a17a98c7ad996c2db4a04997 (patch) | |
tree | cb93a31efb12684ab2c3fc36ee09dc9538e0518e /src/cmd/compile/internal/ssa/rewriteS390X.go | |
parent | 099c6116ccb11595620148cd1a321bd216d37e2b (diff) | |
download | go-e464d7d7970be972a17a98c7ad996c2db4a04997.tar.gz go-e464d7d7970be972a17a98c7ad996c2db4a04997.zip |
cmd/compile: optimize comparisons with immediates on s390x
When generating code for unsigned equals (==) and not equals (!=)
comparisons we currently, on s390x, always use signed comparisons.
This mostly works well, however signed comparisons on s390x sign
extend their immediates and unsigned comparisons zero extend them.
For compare-and-branch instructions which can only have 8-bit
immediates this significantly changes the range of immediate values
we can represent: [-128, 127] for signed comparisons and [0, 255]
for unsigned comparisons.
When generating equals and not equals checks we don't neet to worry
about whether the comparison is signed or unsigned. This CL
therefore adds rules to allow us to switch signedness for such
comparisons if it means that it brings a constant into range for an
8-bit immediate.
For example, a signed equals with an integer in the range [128, 255]
will now be implemented using an unsigned compare-and-branch
instruction rather than separate compare and branch instructions.
As part of this change I've also added support for adding a name
to block control values using the same `x:(...)` syntax we use for
value rules.
Triggers 792 times when compiling cmd and std.
Change-Id: I77fa80a128f0a8ce51a2888d1e384bd5e9b61a77
Reviewed-on: https://go-review.googlesource.com/c/go/+/228642
Run-TryBot: Michael Munday <mike.munday@ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/ssa/rewriteS390X.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/rewriteS390X.go | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/rewriteS390X.go b/src/cmd/compile/internal/ssa/rewriteS390X.go index 29a6cb67fa..01b654ac95 100644 --- a/src/cmd/compile/internal/ssa/rewriteS390X.go +++ b/src/cmd/compile/internal/ssa/rewriteS390X.go @@ -19020,6 +19020,110 @@ func rewriteBlockS390X(b *Block) bool { typ := &b.Func.Config.Types switch b.Kind { case BlockS390XBRC: + // match: (BRC {c} x:(CMP _ _) yes no) + // cond: c&s390x.Unordered != 0 + // result: (BRC {c&^s390x.Unordered} x yes no) + for b.Controls[0].Op == OpS390XCMP { + x := b.Controls[0] + c := auxToS390xCCMask(b.Aux) + if !(c&s390x.Unordered != 0) { + break + } + b.resetWithControl(BlockS390XBRC, x) + b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered) + return true + } + // match: (BRC {c} x:(CMPW _ _) yes no) + // cond: c&s390x.Unordered != 0 + // result: (BRC {c&^s390x.Unordered} x yes no) + for b.Controls[0].Op == OpS390XCMPW { + x := b.Controls[0] + c := auxToS390xCCMask(b.Aux) + if !(c&s390x.Unordered != 0) { + break + } + b.resetWithControl(BlockS390XBRC, x) + b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered) + return true + } + // match: (BRC {c} x:(CMPU _ _) yes no) + // cond: c&s390x.Unordered != 0 + // result: (BRC {c&^s390x.Unordered} x yes no) + for b.Controls[0].Op == OpS390XCMPU { + x := b.Controls[0] + c := auxToS390xCCMask(b.Aux) + if !(c&s390x.Unordered != 0) { + break + } + b.resetWithControl(BlockS390XBRC, x) + b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered) + return true + } + // match: (BRC {c} x:(CMPWU _ _) yes no) + // cond: c&s390x.Unordered != 0 + // result: (BRC {c&^s390x.Unordered} x yes no) + for b.Controls[0].Op == OpS390XCMPWU { + x := b.Controls[0] + c := auxToS390xCCMask(b.Aux) + if !(c&s390x.Unordered != 0) { + break + } + b.resetWithControl(BlockS390XBRC, x) + b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered) + return true + } + // match: (BRC {c} x:(CMPconst _) yes no) + // cond: c&s390x.Unordered != 0 + // result: (BRC {c&^s390x.Unordered} x yes no) + for b.Controls[0].Op == OpS390XCMPconst { + x := b.Controls[0] + c := auxToS390xCCMask(b.Aux) + if !(c&s390x.Unordered != 0) { + break + } + b.resetWithControl(BlockS390XBRC, x) + b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered) + return true + } + // match: (BRC {c} x:(CMPWconst _) yes no) + // cond: c&s390x.Unordered != 0 + // result: (BRC {c&^s390x.Unordered} x yes no) + for b.Controls[0].Op == OpS390XCMPWconst { + x := b.Controls[0] + c := auxToS390xCCMask(b.Aux) + if !(c&s390x.Unordered != 0) { + break + } + b.resetWithControl(BlockS390XBRC, x) + b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered) + return true + } + // match: (BRC {c} x:(CMPUconst _) yes no) + // cond: c&s390x.Unordered != 0 + // result: (BRC {c&^s390x.Unordered} x yes no) + for b.Controls[0].Op == OpS390XCMPUconst { + x := b.Controls[0] + c := auxToS390xCCMask(b.Aux) + if !(c&s390x.Unordered != 0) { + break + } + b.resetWithControl(BlockS390XBRC, x) + b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered) + return true + } + // match: (BRC {c} x:(CMPWUconst _) yes no) + // cond: c&s390x.Unordered != 0 + // result: (BRC {c&^s390x.Unordered} x yes no) + for b.Controls[0].Op == OpS390XCMPWUconst { + x := b.Controls[0] + c := auxToS390xCCMask(b.Aux) + if !(c&s390x.Unordered != 0) { + break + } + b.resetWithControl(BlockS390XBRC, x) + b.Aux = s390xCCMaskToAux(c &^ s390x.Unordered) + return true + } // match: (BRC {c} (CMP x y) yes no) // result: (CGRJ {c&^s390x.Unordered} x y yes no) for b.Controls[0].Op == OpS390XCMP { @@ -19320,6 +19424,70 @@ func rewriteBlockS390X(b *Block) bool { b.Aux = s390xCCMaskToAux(s390x.Greater) return true } + // match: (BRC {c} (CMPconst x [y]) yes no) + // cond: y == int32(uint8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater) + // result: (CLGIJ {c} x [uint8(y)] yes no) + for b.Controls[0].Op == OpS390XCMPconst { + v_0 := b.Controls[0] + y := auxIntToInt32(v_0.AuxInt) + x := v_0.Args[0] + c := auxToS390xCCMask(b.Aux) + if !(y == int32(uint8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)) { + break + } + b.resetWithControl(BlockS390XCLGIJ, x) + b.AuxInt = uint8ToAuxInt(uint8(y)) + b.Aux = s390xCCMaskToAux(c) + return true + } + // match: (BRC {c} (CMPWconst x [y]) yes no) + // cond: y == int32(uint8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater) + // result: (CLIJ {c} x [uint8(y)] yes no) + for b.Controls[0].Op == OpS390XCMPWconst { + v_0 := b.Controls[0] + y := auxIntToInt32(v_0.AuxInt) + x := v_0.Args[0] + c := auxToS390xCCMask(b.Aux) + if !(y == int32(uint8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)) { + break + } + b.resetWithControl(BlockS390XCLIJ, x) + b.AuxInt = uint8ToAuxInt(uint8(y)) + b.Aux = s390xCCMaskToAux(c) + return true + } + // match: (BRC {c} (CMPUconst x [y]) yes no) + // cond: y == int32( int8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater) + // result: (CGIJ {c} x [ int8(y)] yes no) + for b.Controls[0].Op == OpS390XCMPUconst { + v_0 := b.Controls[0] + y := auxIntToInt32(v_0.AuxInt) + x := v_0.Args[0] + c := auxToS390xCCMask(b.Aux) + if !(y == int32(int8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)) { + break + } + b.resetWithControl(BlockS390XCGIJ, x) + b.AuxInt = int8ToAuxInt(int8(y)) + b.Aux = s390xCCMaskToAux(c) + return true + } + // match: (BRC {c} (CMPWUconst x [y]) yes no) + // cond: y == int32( int8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater) + // result: (CIJ {c} x [ int8(y)] yes no) + for b.Controls[0].Op == OpS390XCMPWUconst { + v_0 := b.Controls[0] + y := auxIntToInt32(v_0.AuxInt) + x := v_0.Args[0] + c := auxToS390xCCMask(b.Aux) + if !(y == int32(int8(y)) && (c == s390x.Equal || c == s390x.LessOrGreater)) { + break + } + b.resetWithControl(BlockS390XCIJ, x) + b.AuxInt = int8ToAuxInt(int8(y)) + b.Aux = s390xCCMaskToAux(c) + return true + } // match: (BRC {c} (InvertFlags cmp) yes no) // result: (BRC {c.ReverseComparison()} cmp yes no) for b.Controls[0].Op == OpS390XInvertFlags { |