cmd/compile: on AMD64, turn x < 128 into x <= 127

x < 128 -> x <= 127
x >= 128 -> x > 127

This allows for shorter encoding as 127 fits into
a single-byte immediate.

archive/tar benchmark (Alder Lake 12600K)

name              old time/op    new time/op    delta
/Writer/USTAR-16    1.46µs ± 0%    1.32µs ± 0%  -9.43%  (p=0.008 n=5+5)
/Writer/GNU-16      1.85µs ± 1%    1.79µs ± 1%  -3.47%  (p=0.008 n=5+5)
/Writer/PAX-16      3.21µs ± 0%    3.11µs ± 2%  -2.96%  (p=0.008 n=5+5)
/Reader/USTAR-16    1.38µs ± 1%    1.37µs ± 0%    ~     (p=0.127 n=5+4)
/Reader/GNU-16       798ns ± 1%     800ns ± 2%    ~     (p=0.548 n=5+5)
/Reader/PAX-16      3.07µs ± 1%    3.00µs ± 0%  -2.35%  (p=0.008 n=5+5)
[Geo mean]          1.76µs         1.70µs       -3.15%

compilecmp:

hash/maphash
hash/maphash.(*Hash).Write 517 -> 510  (-1.35%)

runtime
runtime.traceReadCPU 1626 -> 1615  (-0.68%)

runtime [cmd/compile]
runtime.traceReadCPU 1626 -> 1615  (-0.68%)

math/rand/v2
type:.eq.[128]float32 65 -> 59  (-9.23%)

bytes
bytes.trimLeftUnicode 378 -> 373  (-1.32%)
bytes.IndexAny 1189 -> 1157  (-2.69%)
bytes.LastIndexAny 1256 -> 1239  (-1.35%)
bytes.lastIndexFunc 263 -> 261  (-0.76%)

strings
strings.FieldsFuncSeq.func1 411 -> 399  (-2.92%)
strings.EqualFold 625 -> 624  (-0.16%)
strings.trimLeftUnicode 248 -> 231  (-6.85%)

math/rand
type:.eq.[128]float32 65 -> 59  (-9.23%)

bytes [cmd/compile]
bytes.LastIndexAny 1256 -> 1239  (-1.35%)
bytes.lastIndexFunc 263 -> 261  (-0.76%)
bytes.trimLeftUnicode 378 -> 373  (-1.32%)
bytes.IndexAny 1189 -> 1157  (-2.69%)

regexp/syntax
regexp/syntax.(*parser).parseEscape 1113 -> 1102  (-0.99%)

math/rand/v2 [cmd/compile]
type:.eq.[128]float32 65 -> 59  (-9.23%)

strings [cmd/compile]
strings.EqualFold 625 -> 624  (-0.16%)
strings.FieldsFuncSeq.func1 411 -> 399  (-2.92%)
strings.trimLeftUnicode 248 -> 231  (-6.85%)

math/rand [cmd/compile]
type:.eq.[128]float32 65 -> 59  (-9.23%)

regexp
regexp.(*inputString).context 198 -> 197  (-0.51%)
regexp.(*inputBytes).context 221 -> 212  (-4.07%)

image/jpeg
image/jpeg.(*decoder).processDQT 500 -> 491  (-1.80%)

regexp/syntax [cmd/compile]
regexp/syntax.(*parser).parseEscape 1113 -> 1102  (-0.99%)

regexp [cmd/compile]
regexp.(*inputString).context 198 -> 197  (-0.51%)
regexp.(*inputBytes).context 221 -> 212  (-4.07%)

encoding/csv
encoding/csv.(*Writer).fieldNeedsQuotes 269 -> 266  (-1.12%)

cmd/vendor/golang.org/x/sys/unix
type:.eq.[131]struct 855 -> 823  (-3.74%)

vendor/golang.org/x/text/unicode/norm
vendor/golang.org/x/text/unicode/norm.nextDecomposed 4831 -> 4826  (-0.10%)
vendor/golang.org/x/text/unicode/norm.(*Iter).returnSlice 281 -> 275  (-2.14%)

vendor/golang.org/x/text/secure/bidirule
vendor/golang.org/x/text/secure/bidirule.init.0 85 -> 83  (-2.35%)

go/scanner
go/scanner.isDigit 100 -> 98  (-2.00%)
go/scanner.(*Scanner).next 431 -> 422  (-2.09%)
go/scanner.isLetter 142 -> 124  (-12.68%)

encoding/asn1
encoding/asn1.parseTagAndLength 1189 -> 1182  (-0.59%)
encoding/asn1.makeField 3481 -> 3463  (-0.52%)

text/scanner
text/scanner.(*Scanner).next 1242 -> 1236  (-0.48%)

archive/tar
archive/tar.isASCII 133 -> 127  (-4.51%)
archive/tar.(*Writer).writeRawFile 1206 -> 1198  (-0.66%)
archive/tar.(*Reader).readHeader.func1 9 -> 7  (-22.22%)
archive/tar.toASCII 393 -> 383  (-2.54%)
archive/tar.splitUSTARPath 405 -> 396  (-2.22%)
archive/tar.(*Writer).writePAXHeader.func1 627 -> 620  (-1.12%)

text/template
text/template.jsIsSpecial 59 -> 57  (-3.39%)

go/doc
go/doc.assumedPackageName 714 -> 701  (-1.82%)

vendor/golang.org/x/net/http/httpguts
vendor/golang.org/x/net/http/httpguts.headerValueContainsToken 965 -> 952  (-1.35%)
vendor/golang.org/x/net/http/httpguts.tokenEqual 280 -> 269  (-3.93%)
vendor/golang.org/x/net/http/httpguts.IsTokenRune 28 -> 26  (-7.14%)

net/mail
net/mail.isVchar 26 -> 24  (-7.69%)
net/mail.isAtext 106 -> 104  (-1.89%)
net/mail.(*Address).String 1084 -> 1052  (-2.95%)
net/mail.isQtext 39 -> 37  (-5.13%)
net/mail.isMultibyte 9 -> 7  (-22.22%)
net/mail.isDtext 45 -> 43  (-4.44%)
net/mail.(*addrParser).consumeQuotedString 1050 -> 1029  (-2.00%)
net/mail.quoteString 741 -> 714  (-3.64%)

cmd/internal/obj/s390x
cmd/internal/obj/s390x.preprocess 6405 -> 6393  (-0.19%)

cmd/internal/obj/x86
cmd/internal/obj/x86.toDisp8 303 -> 301  (-0.66%)

fmt [cmd/compile]
fmt.Fprintf 4726 -> 4662  (-1.35%)

go/scanner [cmd/compile]
go/scanner.(*Scanner).next 431 -> 422  (-2.09%)
go/scanner.isLetter 142 -> 124  (-12.68%)
go/scanner.isDigit 100 -> 98  (-2.00%)

cmd/compile/internal/syntax
cmd/compile/internal/syntax.(*source).nextch 879 -> 847  (-3.64%)

cmd/vendor/golang.org/x/mod/module
cmd/vendor/golang.org/x/mod/module.checkElem 1253 -> 1235  (-1.44%)
cmd/vendor/golang.org/x/mod/module.escapeString 519 -> 517  (-0.39%)

go/doc [cmd/compile]
go/doc.assumedPackageName 714 -> 701  (-1.82%)

cmd/compile/internal/syntax [cmd/compile]
cmd/compile/internal/syntax.(*scanner).escape 1965 -> 1933  (-1.63%)
cmd/compile/internal/syntax.(*scanner).next 8975 -> 8847  (-1.43%)

cmd/internal/obj/s390x [cmd/compile]
cmd/internal/obj/s390x.preprocess 6405 -> 6393  (-0.19%)

cmd/internal/obj/x86 [cmd/compile]
cmd/internal/obj/x86.toDisp8 303 -> 301  (-0.66%)

cmd/internal/gcprog
cmd/internal/gcprog.(*Writer).Repeat 688 -> 677  (-1.60%)
cmd/internal/gcprog.(*Writer).varint 442 -> 439  (-0.68%)

cmd/compile/internal/ir
cmd/compile/internal/ir.splitPkg 331 -> 325  (-1.81%)

cmd/compile/internal/ir [cmd/compile]
cmd/compile/internal/ir.splitPkg 331 -> 325  (-1.81%)

net/http
net/http.containsDotDot.FieldsFuncSeq.func1 411 -> 399  (-2.92%)
net/http.isNotToken 33 -> 30  (-9.09%)
net/http.containsDotDot 606 -> 588  (-2.97%)
net/http.isCookieNameValid 197 -> 191  (-3.05%)
net/http.parsePattern 4330 -> 4317  (-0.30%)
net/http.ParseCookie 1099 -> 1096  (-0.27%)
net/http.validMethod 197 -> 187  (-5.08%)

cmd/vendor/golang.org/x/text/unicode/norm
cmd/vendor/golang.org/x/text/unicode/norm.(*Iter).returnSlice 281 -> 275  (-2.14%)
cmd/vendor/golang.org/x/text/unicode/norm.nextDecomposed 4831 -> 4826  (-0.10%)

net/http/cookiejar
net/http/cookiejar.encode 1936 -> 1918  (-0.93%)

expvar
expvar.appendJSONQuote 972 -> 965  (-0.72%)

cmd/cgo/internal/test
cmd/cgo/internal/test.stack128 116 -> 114  (-1.72%)

cmd/vendor/rsc.io/markdown
cmd/vendor/rsc.io/markdown.newATXHeading 1637 -> 1628  (-0.55%)
cmd/vendor/rsc.io/markdown.isUnicodePunct 197 -> 179  (-9.14%)

Change-Id: I578bdf42ef229d687d526e378d697ced51e1880c
Reviewed-on: https://go-review.googlesource.com/c/go/+/639935
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
Jakub Ciolek 2025-01-03 13:52:11 +01:00 committed by Keith Randall
parent d5b75e4046
commit d524e1eccd
3 changed files with 462 additions and 0 deletions

View File

@ -628,6 +628,21 @@
// x & 1 == 0 -> (x & 1) ^ 1
(SETAE (BT(L|Q)const [0] x)) => (XORLconst [1] (ANDLconst <typ.Bool> [1] x))
// Shorten compare by rewriting x < 128 as x <= 127, which can be encoded in a single-byte immediate on x86.
(SETL c:(CMP(Q|L)const [128] x)) && c.Uses == 1 => (SETLE (CMP(Q|L)const [127] x))
(SETB c:(CMP(Q|L)const [128] x)) && c.Uses == 1 => (SETBE (CMP(Q|L)const [127] x))
// x >= 128 -> x > 127
(SETGE c:(CMP(Q|L)const [128] x)) && c.Uses == 1 => (SETG (CMP(Q|L)const [127] x))
(SETAE c:(CMP(Q|L)const [128] x)) && c.Uses == 1 => (SETA (CMP(Q|L)const [127] x))
(CMOVQLT x y c:(CMP(Q|L)const [128] z)) && c.Uses == 1 => (CMOVQLE x y (CMP(Q|L)const [127] z))
(CMOVLLT x y c:(CMP(Q|L)const [128] z)) && c.Uses == 1 => (CMOVLLE x y (CMP(Q|L)const [127] z))
(LT c:(CMP(Q|L)const [128] z) yes no) && c.Uses == 1 => (LE (CMP(Q|L)const [127] z) yes no)
(CMOVQGE x y c:(CMP(Q|L)const [128] z)) && c.Uses == 1 => (CMOVQGT x y (CMP(Q|L)const [127] z))
(CMOVLGE x y c:(CMP(Q|L)const [128] z)) && c.Uses == 1 => (CMOVLGT x y (CMP(Q|L)const [127] z))
(GE c:(CMP(Q|L)const [128] z) yes no) && c.Uses == 1 => (GT (CMP(Q|L)const [127] z) yes no)
// Recognize bit tests: a&(1<<b) != 0 for b suitably bounded
// Note that BTx instructions use the carry bit, so we need to convert tests for zero flag
// into tests for carry flags.

View File

@ -4246,6 +4246,7 @@ func rewriteValueAMD64_OpAMD64CMOVLGE(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
// match: (CMOVLGE x y (InvertFlags cond))
// result: (CMOVLLE x y cond)
for {
@ -4309,6 +4310,48 @@ func rewriteValueAMD64_OpAMD64CMOVLGE(v *Value) bool {
v.copyOf(y)
return true
}
// match: (CMOVLGE x y c:(CMPQconst [128] z))
// cond: c.Uses == 1
// result: (CMOVLGT x y (CMPQconst [127] z))
for {
x := v_0
y := v_1
c := v_2
if c.Op != OpAMD64CMPQconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64CMOVLGT)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
v.AddArg3(x, y, v0)
return true
}
// match: (CMOVLGE x y c:(CMPLconst [128] z))
// cond: c.Uses == 1
// result: (CMOVLGT x y (CMPLconst [127] z))
for {
x := v_0
y := v_1
c := v_2
if c.Op != OpAMD64CMPLconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64CMOVLGT)
v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
v.AddArg3(x, y, v0)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64CMOVLGT(v *Value) bool {
@ -4591,6 +4634,7 @@ func rewriteValueAMD64_OpAMD64CMOVLLT(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
// match: (CMOVLLT x y (InvertFlags cond))
// result: (CMOVLGT x y cond)
for {
@ -4654,6 +4698,48 @@ func rewriteValueAMD64_OpAMD64CMOVLLT(v *Value) bool {
v.copyOf(x)
return true
}
// match: (CMOVLLT x y c:(CMPQconst [128] z))
// cond: c.Uses == 1
// result: (CMOVLLE x y (CMPQconst [127] z))
for {
x := v_0
y := v_1
c := v_2
if c.Op != OpAMD64CMPQconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64CMOVLLE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
v.AddArg3(x, y, v0)
return true
}
// match: (CMOVLLT x y c:(CMPLconst [128] z))
// cond: c.Uses == 1
// result: (CMOVLLE x y (CMPLconst [127] z))
for {
x := v_0
y := v_1
c := v_2
if c.Op != OpAMD64CMPLconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64CMOVLLE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
v.AddArg3(x, y, v0)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64CMOVLNE(v *Value) bool {
@ -5096,6 +5182,7 @@ func rewriteValueAMD64_OpAMD64CMOVQGE(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
// match: (CMOVQGE x y (InvertFlags cond))
// result: (CMOVQLE x y cond)
for {
@ -5159,6 +5246,48 @@ func rewriteValueAMD64_OpAMD64CMOVQGE(v *Value) bool {
v.copyOf(y)
return true
}
// match: (CMOVQGE x y c:(CMPQconst [128] z))
// cond: c.Uses == 1
// result: (CMOVQGT x y (CMPQconst [127] z))
for {
x := v_0
y := v_1
c := v_2
if c.Op != OpAMD64CMPQconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64CMOVQGT)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
v.AddArg3(x, y, v0)
return true
}
// match: (CMOVQGE x y c:(CMPLconst [128] z))
// cond: c.Uses == 1
// result: (CMOVQGT x y (CMPLconst [127] z))
for {
x := v_0
y := v_1
c := v_2
if c.Op != OpAMD64CMPLconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64CMOVQGT)
v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
v.AddArg3(x, y, v0)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64CMOVQGT(v *Value) bool {
@ -5441,6 +5570,7 @@ func rewriteValueAMD64_OpAMD64CMOVQLT(v *Value) bool {
v_2 := v.Args[2]
v_1 := v.Args[1]
v_0 := v.Args[0]
b := v.Block
// match: (CMOVQLT x y (InvertFlags cond))
// result: (CMOVQGT x y cond)
for {
@ -5504,6 +5634,48 @@ func rewriteValueAMD64_OpAMD64CMOVQLT(v *Value) bool {
v.copyOf(x)
return true
}
// match: (CMOVQLT x y c:(CMPQconst [128] z))
// cond: c.Uses == 1
// result: (CMOVQLE x y (CMPQconst [127] z))
for {
x := v_0
y := v_1
c := v_2
if c.Op != OpAMD64CMPQconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64CMOVQLE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
v.AddArg3(x, y, v0)
return true
}
// match: (CMOVQLT x y c:(CMPLconst [128] z))
// cond: c.Uses == 1
// result: (CMOVQLE x y (CMPLconst [127] z))
for {
x := v_0
y := v_1
c := v_2
if c.Op != OpAMD64CMPLconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64CMOVQLE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
v.AddArg3(x, y, v0)
return true
}
return false
}
func rewriteValueAMD64_OpAMD64CMOVQNE(v *Value) bool {
@ -16789,6 +16961,44 @@ func rewriteValueAMD64_OpAMD64SETAE(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (SETAE c:(CMPQconst [128] x))
// cond: c.Uses == 1
// result: (SETA (CMPQconst [127] x))
for {
c := v_0
if c.Op != OpAMD64CMPQconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
x := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64SETA)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (SETAE c:(CMPLconst [128] x))
// cond: c.Uses == 1
// result: (SETA (CMPLconst [127] x))
for {
c := v_0
if c.Op != OpAMD64CMPLconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
x := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64SETA)
v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (SETAE (InvertFlags x))
// result: (SETBE x)
for {
@ -17174,6 +17384,7 @@ func rewriteValueAMD64_OpAMD64SETAstore(v *Value) bool {
}
func rewriteValueAMD64_OpAMD64SETB(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
// match: (SETB (TESTQ x x))
// result: (ConstBool [false])
for {
@ -17254,6 +17465,44 @@ func rewriteValueAMD64_OpAMD64SETB(v *Value) bool {
v.AddArg(x)
return true
}
// match: (SETB c:(CMPQconst [128] x))
// cond: c.Uses == 1
// result: (SETBE (CMPQconst [127] x))
for {
c := v_0
if c.Op != OpAMD64CMPQconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
x := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64SETBE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (SETB c:(CMPLconst [128] x))
// cond: c.Uses == 1
// result: (SETBE (CMPLconst [127] x))
for {
c := v_0
if c.Op != OpAMD64CMPLconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
x := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64SETBE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (SETB (InvertFlags x))
// result: (SETA x)
for {
@ -18813,6 +19062,45 @@ func rewriteValueAMD64_OpAMD64SETG(v *Value) bool {
}
func rewriteValueAMD64_OpAMD64SETGE(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
// match: (SETGE c:(CMPQconst [128] x))
// cond: c.Uses == 1
// result: (SETG (CMPQconst [127] x))
for {
c := v_0
if c.Op != OpAMD64CMPQconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
x := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64SETG)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (SETGE c:(CMPLconst [128] x))
// cond: c.Uses == 1
// result: (SETG (CMPLconst [127] x))
for {
c := v_0
if c.Op != OpAMD64CMPLconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
x := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64SETG)
v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (SETGE (InvertFlags x))
// result: (SETLE x)
for {
@ -19198,6 +19486,45 @@ func rewriteValueAMD64_OpAMD64SETGstore(v *Value) bool {
}
func rewriteValueAMD64_OpAMD64SETL(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
// match: (SETL c:(CMPQconst [128] x))
// cond: c.Uses == 1
// result: (SETLE (CMPQconst [127] x))
for {
c := v_0
if c.Op != OpAMD64CMPQconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
x := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64SETLE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (SETL c:(CMPLconst [128] x))
// cond: c.Uses == 1
// result: (SETLE (CMPLconst [127] x))
for {
c := v_0
if c.Op != OpAMD64CMPLconst || auxIntToInt32(c.AuxInt) != 128 {
break
}
x := c.Args[0]
if !(c.Uses == 1) {
break
}
v.reset(OpAMD64SETLE)
v0 := b.NewValue0(v.Pos, OpAMD64CMPLconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (SETL (InvertFlags x))
// result: (SETG x)
for {
@ -31015,6 +31342,42 @@ func rewriteBlockAMD64(b *Block) bool {
break
}
case BlockAMD64GE:
// match: (GE c:(CMPQconst [128] z) yes no)
// cond: c.Uses == 1
// result: (GT (CMPQconst [127] z) yes no)
for b.Controls[0].Op == OpAMD64CMPQconst {
c := b.Controls[0]
if auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v0 := b.NewValue0(c.Pos, OpAMD64CMPQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
b.resetWithControl(BlockAMD64GT, v0)
return true
}
// match: (GE c:(CMPLconst [128] z) yes no)
// cond: c.Uses == 1
// result: (GT (CMPLconst [127] z) yes no)
for b.Controls[0].Op == OpAMD64CMPLconst {
c := b.Controls[0]
if auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v0 := b.NewValue0(c.Pos, OpAMD64CMPLconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
b.resetWithControl(BlockAMD64GT, v0)
return true
}
// match: (GE (InvertFlags cmp) yes no)
// result: (LE cmp yes no)
for b.Controls[0].Op == OpAMD64InvertFlags {
@ -31282,6 +31645,42 @@ func rewriteBlockAMD64(b *Block) bool {
return true
}
case BlockAMD64LT:
// match: (LT c:(CMPQconst [128] z) yes no)
// cond: c.Uses == 1
// result: (LE (CMPQconst [127] z) yes no)
for b.Controls[0].Op == OpAMD64CMPQconst {
c := b.Controls[0]
if auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v0 := b.NewValue0(c.Pos, OpAMD64CMPQconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
b.resetWithControl(BlockAMD64LE, v0)
return true
}
// match: (LT c:(CMPLconst [128] z) yes no)
// cond: c.Uses == 1
// result: (LE (CMPLconst [127] z) yes no)
for b.Controls[0].Op == OpAMD64CMPLconst {
c := b.Controls[0]
if auxIntToInt32(c.AuxInt) != 128 {
break
}
z := c.Args[0]
if !(c.Uses == 1) {
break
}
v0 := b.NewValue0(c.Pos, OpAMD64CMPLconst, types.TypeFlags)
v0.AuxInt = int32ToAuxInt(127)
v0.AddArg(z)
b.resetWithControl(BlockAMD64LE, v0)
return true
}
// match: (LT (InvertFlags cmp) yes no)
// result: (GT cmp yes no)
for b.Controls[0].Op == OpAMD64InvertFlags {

View File

@ -730,6 +730,54 @@ func cmpToCmnLessThan(a, b, c, d int) int {
return c1 + c2 + c3 + c4
}
func less128Signed32(x int32) bool {
// amd64:`CMPL.*127`
// amd64:`SETLE`
return x < 128
}
func less128Signed64(x int64) bool {
// amd64:`CMPQ.*127`
// amd64:`SETLE`
return x < 128
}
func less128Unsigned32(x uint32) bool {
// amd64:`CMPL.*127`
// amd64:`SETLS`
return x < 128
}
func less128Unsigned64(x uint64) bool {
// amd64:`CMPQ.*127`
// amd64:`SETLS`
return x < 128
}
func ge128Unsigned32(x uint32) bool {
// amd64:`CMPL.*127`
// amd64:`SETHI`
return x >= 128
}
func ge128Unsigned64(x uint64) bool {
// amd64:`CMPQ.*127`
// amd64:`SETHI`
return x >= 128
}
func ge128Signed32(x int32) bool {
// amd64:`CMPL.*127`
// amd64:`SETGT`
return x >= 128
}
func ge128Signed64(x int64) bool {
// amd64:`CMPQ.*127`
// amd64:`SETGT`
return x >= 128
}
func cmpToCmnGreaterThanEqual(a, b, c, d int) int {
var c1, c2, c3, c4 int
// arm64:`CMN`,`CSET\tPL`,-`CMP`