compile: prefer an AND instead of SHR+SHL instructions

On modern 64bit CPUs a SHR, SHL or AND instruction take 1 cycle to execute.
A pair of shifts that operate on the same register will take 2 cycles
and needs to wait for the input register value to be available.

Large constants used to mask the high bits of a register with an AND
instruction can not be encoded as an immediate in the AND instruction
on amd64 and therefore need to be loaded into a register with a MOV
instruction.

However that MOV instruction is not dependent on the output register and
on many CPUs does not compete with the AND or shift instructions for
execution ports.

Using a pair of shifts to mask high bits instead of an AND to mask high
bits of a register has a shorter encoding and uses one less general
purpose register but is slower due to taking one clock cycle longer
if there is no register pressure that would make the AND variant need to
generate a spill.

For example the instructions emitted for (x & 1 << 63) before this CL are:
48c1ea3f                SHRQ $0x3f, DX
48c1e23f                SHLQ $0x3f, DX

after this CL the instructions are the same as GCC and LLVM use:
48b80000000000000080    MOVQ $0x8000000000000000, AX
4821d0                  ANDQ DX, AX

Some platforms such as arm64 already have SSA optimization rules to fuse
two shift instructions back into an AND.

Removing the general rule to rewrite AND to SHR+SHL speeds up this benchmark:

    var GlobalU uint

    func BenchmarkAndHighBits(b *testing.B) {
        x := uint(0)
        for i := 0; i < b.N; i++ {
                x &= 1 << 63
        }
        GlobalU = x
    }

amd64/darwin on Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz:
name           old time/op  new time/op  delta
AndHighBits-4  0.61ns ± 6%  0.42ns ± 6%  -31.42%  (p=0.000 n=25+25):

'go run run.go -all_codegen -v codegen' passes  with following adjustments:

ARM64: The BFXIL pattern ((x << lc) >> rc | y & ac) needed adjustment
       since ORshiftRL generation fusing '>> rc' and '|' interferes
       with matching ((x << lc) >> rc) to generate UBFX. Previously
       ORshiftLL was created first using the shifts generated for (y & ac).

S390X: Add rules for abs and copysign to match use of AND instead of SHIFTs.

Updates #33826
Updates #32781

Change-Id: I5a59f6239660d53c029cd22dfb44ddf39f93a56c
Reviewed-on: https://go-review.googlesource.com/c/go/+/196810
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Martin Möhrmann 2019-09-09 17:50:35 +02:00
parent 1804bbab62
commit f41451e7eb
7 changed files with 480 additions and 195 deletions

View File

@ -1863,9 +1863,8 @@
(XORshiftLL <t> [c] (UBFX [bfc] x) x2) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
-> (EXTRWconst [32-c] x2 x)
// Generic rules rewrite certain AND to a pair of shifts.
// However, on ARM64 the bitmask can fit into an instruction.
// Rewrite it back to AND.
// Rewrite special pairs of shifts to AND.
// On ARM64 the bitmask can fit into an instruction.
(SRLconst [c] (SLLconst [c] x)) && 0 < c && c < 64 -> (ANDconst [1<<uint(64-c)-1] x) // mask out high bits
(SLLconst [c] (SRLconst [c] x)) && 0 < c && c < 64 -> (ANDconst [^(1<<uint(c)-1)] x) // mask out low bits
@ -1971,6 +1970,8 @@
-> (BFXIL [bfc] y x)
(ORshiftLL [sc] (UBFX [bfc] x) (SRLconst [sc] y)) && sc == getARM64BFwidth(bfc)
-> (BFXIL [bfc] y x)
(ORshiftRL [rc] (ANDconst [ac] y) (SLLconst [lc] x)) && lc < rc && ac == ^((1<<uint(64-rc)-1))
-> (BFXIL [armBFAuxInt(rc-lc, 64-rc)] y x)
// do combined loads
// little endian loads

View File

@ -701,6 +701,8 @@
// may need to be reworked when NIHH/OIHH are added
(SRDconst [1] (SLDconst [1] (LGDR <t> x))) -> (LGDR <t> (LPDFR <x.Type> x))
(LDGR <t> (SRDconst [1] (SLDconst [1] x))) -> (LPDFR (LDGR <t> x))
(AND (MOVDconst [^(-1<<63)]) (LGDR <t> x)) -> (LGDR <t> (LPDFR <x.Type> x))
(LDGR <t> (AND (MOVDconst [^(-1<<63)]) x)) -> (LPDFR (LDGR <t> x))
(OR (MOVDconst [-1<<63]) (LGDR <t> x)) -> (LGDR <t> (LNDFR <x.Type> x))
(LDGR <t> (OR (MOVDconst [-1<<63]) x)) -> (LNDFR (LDGR <t> x))
@ -710,6 +712,8 @@
// detect copysign
(OR (SLDconst [63] (SRDconst [63] (LGDR x))) (LGDR (LPDFR <t> y))) -> (LGDR (CPSDR <t> y x))
(OR (SLDconst [63] (SRDconst [63] (LGDR x))) (MOVDconst [c])) && c & -1<<63 == 0 -> (LGDR (CPSDR <x.Type> (FMOVDconst <x.Type> [c]) x))
(OR (AND (MOVDconst [-1<<63]) (LGDR x)) (LGDR (LPDFR <t> y))) -> (LGDR (CPSDR <t> y x))
(OR (AND (MOVDconst [-1<<63]) (LGDR x)) (MOVDconst [c])) && c & -1<<63 == 0 -> (LGDR (CPSDR <x.Type> (FMOVDconst <x.Type> [c]) x))
(CPSDR y (FMOVDconst [c])) && c & -1<<63 == 0 -> (LPDFR y)
(CPSDR y (FMOVDconst [c])) && c & -1<<63 != 0 -> (LNDFR y)

View File

@ -542,14 +542,6 @@
(Slicemask (Const64 [x])) && x > 0 -> (Const64 [-1])
(Slicemask (Const64 [0])) -> (Const64 [0])
// Rewrite AND of consts as shifts if possible, slightly faster for 64 bit operands
// leading zeros can be shifted left, then right
(And64 <t> (Const64 [y]) x) && nlz(y) + nto(y) == 64 && nto(y) >= 32
-> (Rsh64Ux64 (Lsh64x64 <t> x (Const64 <t> [nlz(y)])) (Const64 <t> [nlz(y)]))
// trailing zeros can be shifted right, then left
(And64 <t> (Const64 [y]) x) && nlo(y) + ntz(y) == 64 && ntz(y) >= 32
-> (Lsh64x64 (Rsh64Ux64 <t> x (Const64 <t> [ntz(y)])) (Const64 <t> [ntz(y)]))
// simplifications often used for lengths. e.g. len(s[i:i+5])==5
(Sub(64|32|16|8) (Add(64|32|16|8) x y) x) -> y
(Sub(64|32|16|8) (Add(64|32|16|8) x y) y) -> x

View File

@ -24258,6 +24258,33 @@ func rewriteValueARM64_OpARM64ORshiftRL_0(v *Value) bool {
v.AddArg(y)
return true
}
// match: (ORshiftRL [rc] (ANDconst [ac] y) (SLLconst [lc] x))
// cond: lc < rc && ac == ^((1<<uint(64-rc)-1))
// result: (BFXIL [armBFAuxInt(rc-lc, 64-rc)] y x)
for {
rc := v.AuxInt
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpARM64ANDconst {
break
}
ac := v_0.AuxInt
y := v_0.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpARM64SLLconst {
break
}
lc := v_1.AuxInt
x := v_1.Args[0]
if !(lc < rc && ac == ^(1<<uint(64-rc)-1)) {
break
}
v.reset(OpARM64BFXIL)
v.AuxInt = armBFAuxInt(rc-lc, 64-rc)
v.AddArg(y)
v.AddArg(x)
return true
}
return false
}
func rewriteValueARM64_OpARM64RORWconst_0(v *Value) bool {

View File

@ -664,7 +664,7 @@ func rewriteValueS390X(v *Value) bool {
case OpS390XNOTW:
return rewriteValueS390X_OpS390XNOTW_0(v)
case OpS390XOR:
return rewriteValueS390X_OpS390XOR_0(v) || rewriteValueS390X_OpS390XOR_10(v) || rewriteValueS390X_OpS390XOR_20(v) || rewriteValueS390X_OpS390XOR_30(v) || rewriteValueS390X_OpS390XOR_40(v) || rewriteValueS390X_OpS390XOR_50(v) || rewriteValueS390X_OpS390XOR_60(v) || rewriteValueS390X_OpS390XOR_70(v) || rewriteValueS390X_OpS390XOR_80(v) || rewriteValueS390X_OpS390XOR_90(v) || rewriteValueS390X_OpS390XOR_100(v) || rewriteValueS390X_OpS390XOR_110(v) || rewriteValueS390X_OpS390XOR_120(v) || rewriteValueS390X_OpS390XOR_130(v) || rewriteValueS390X_OpS390XOR_140(v) || rewriteValueS390X_OpS390XOR_150(v)
return rewriteValueS390X_OpS390XOR_0(v) || rewriteValueS390X_OpS390XOR_10(v) || rewriteValueS390X_OpS390XOR_20(v) || rewriteValueS390X_OpS390XOR_30(v) || rewriteValueS390X_OpS390XOR_40(v) || rewriteValueS390X_OpS390XOR_50(v) || rewriteValueS390X_OpS390XOR_60(v) || rewriteValueS390X_OpS390XOR_70(v) || rewriteValueS390X_OpS390XOR_80(v) || rewriteValueS390X_OpS390XOR_90(v) || rewriteValueS390X_OpS390XOR_100(v) || rewriteValueS390X_OpS390XOR_110(v) || rewriteValueS390X_OpS390XOR_120(v) || rewriteValueS390X_OpS390XOR_130(v) || rewriteValueS390X_OpS390XOR_140(v) || rewriteValueS390X_OpS390XOR_150(v) || rewriteValueS390X_OpS390XOR_160(v)
case OpS390XORW:
return rewriteValueS390X_OpS390XORW_0(v) || rewriteValueS390X_OpS390XORW_10(v) || rewriteValueS390X_OpS390XORW_20(v) || rewriteValueS390X_OpS390XORW_30(v) || rewriteValueS390X_OpS390XORW_40(v) || rewriteValueS390X_OpS390XORW_50(v) || rewriteValueS390X_OpS390XORW_60(v) || rewriteValueS390X_OpS390XORW_70(v) || rewriteValueS390X_OpS390XORW_80(v) || rewriteValueS390X_OpS390XORW_90(v)
case OpS390XORWconst:
@ -7585,6 +7585,49 @@ func rewriteValueS390X_OpS390XAND_0(v *Value) bool {
return false
}
func rewriteValueS390X_OpS390XAND_10(v *Value) bool {
b := v.Block
// match: (AND (MOVDconst [^(-1<<63)]) (LGDR <t> x))
// result: (LGDR <t> (LPDFR <x.Type> x))
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpS390XMOVDconst || v_0.AuxInt != ^(-1<<63) {
break
}
v_1 := v.Args[1]
if v_1.Op != OpS390XLGDR {
break
}
t := v_1.Type
x := v_1.Args[0]
v.reset(OpS390XLGDR)
v.Type = t
v0 := b.NewValue0(v.Pos, OpS390XLPDFR, x.Type)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (AND (LGDR <t> x) (MOVDconst [^(-1<<63)]))
// result: (LGDR <t> (LPDFR <x.Type> x))
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpS390XLGDR {
break
}
t := v_0.Type
x := v_0.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpS390XMOVDconst || v_1.AuxInt != ^(-1<<63) {
break
}
v.reset(OpS390XLGDR)
v.Type = t
v0 := b.NewValue0(v.Pos, OpS390XLPDFR, x.Type)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (AND (MOVDconst [c]) (MOVDconst [d]))
// result: (MOVDconst [c&d])
for {
@ -10134,6 +10177,45 @@ func rewriteValueS390X_OpS390XLDGR_0(v *Value) bool {
v.AddArg(v0)
return true
}
// match: (LDGR <t> (AND (MOVDconst [^(-1<<63)]) x))
// result: (LPDFR (LDGR <t> x))
for {
t := v.Type
v_0 := v.Args[0]
if v_0.Op != OpS390XAND {
break
}
x := v_0.Args[1]
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpS390XMOVDconst || v_0_0.AuxInt != ^(-1<<63) {
break
}
v.reset(OpS390XLPDFR)
v0 := b.NewValue0(v.Pos, OpS390XLDGR, t)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (LDGR <t> (AND x (MOVDconst [^(-1<<63)])))
// result: (LPDFR (LDGR <t> x))
for {
t := v.Type
v_0 := v.Args[0]
if v_0.Op != OpS390XAND {
break
}
_ = v_0.Args[1]
x := v_0.Args[0]
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpS390XMOVDconst || v_0_1.AuxInt != ^(-1<<63) {
break
}
v.reset(OpS390XLPDFR)
v0 := b.NewValue0(v.Pos, OpS390XLDGR, t)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (LDGR <t> (OR (MOVDconst [-1<<63]) x))
// result: (LNDFR (LDGR <t> x))
for {
@ -20469,7 +20551,287 @@ func rewriteValueS390X_OpS390XOR_0(v *Value) bool {
}
func rewriteValueS390X_OpS390XOR_10(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR (AND (MOVDconst [-1<<63]) (LGDR x)) (LGDR (LPDFR <t> y)))
// result: (LGDR (CPSDR <t> y x))
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpS390XAND {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpS390XMOVDconst || v_0_0.AuxInt != -1<<63 {
break
}
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpS390XLGDR {
break
}
x := v_0_1.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpS390XLGDR {
break
}
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpS390XLPDFR {
break
}
t := v_1_0.Type
y := v_1_0.Args[0]
v.reset(OpS390XLGDR)
v0 := b.NewValue0(v.Pos, OpS390XCPSDR, t)
v0.AddArg(y)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (OR (AND (LGDR x) (MOVDconst [-1<<63])) (LGDR (LPDFR <t> y)))
// result: (LGDR (CPSDR <t> y x))
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpS390XAND {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpS390XLGDR {
break
}
x := v_0_0.Args[0]
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpS390XMOVDconst || v_0_1.AuxInt != -1<<63 {
break
}
v_1 := v.Args[1]
if v_1.Op != OpS390XLGDR {
break
}
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpS390XLPDFR {
break
}
t := v_1_0.Type
y := v_1_0.Args[0]
v.reset(OpS390XLGDR)
v0 := b.NewValue0(v.Pos, OpS390XCPSDR, t)
v0.AddArg(y)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (OR (LGDR (LPDFR <t> y)) (AND (MOVDconst [-1<<63]) (LGDR x)))
// result: (LGDR (CPSDR <t> y x))
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpS390XLGDR {
break
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpS390XLPDFR {
break
}
t := v_0_0.Type
y := v_0_0.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpS390XAND {
break
}
_ = v_1.Args[1]
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpS390XMOVDconst || v_1_0.AuxInt != -1<<63 {
break
}
v_1_1 := v_1.Args[1]
if v_1_1.Op != OpS390XLGDR {
break
}
x := v_1_1.Args[0]
v.reset(OpS390XLGDR)
v0 := b.NewValue0(v.Pos, OpS390XCPSDR, t)
v0.AddArg(y)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (OR (LGDR (LPDFR <t> y)) (AND (LGDR x) (MOVDconst [-1<<63])))
// result: (LGDR (CPSDR <t> y x))
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpS390XLGDR {
break
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpS390XLPDFR {
break
}
t := v_0_0.Type
y := v_0_0.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpS390XAND {
break
}
_ = v_1.Args[1]
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpS390XLGDR {
break
}
x := v_1_0.Args[0]
v_1_1 := v_1.Args[1]
if v_1_1.Op != OpS390XMOVDconst || v_1_1.AuxInt != -1<<63 {
break
}
v.reset(OpS390XLGDR)
v0 := b.NewValue0(v.Pos, OpS390XCPSDR, t)
v0.AddArg(y)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (OR (AND (MOVDconst [-1<<63]) (LGDR x)) (MOVDconst [c]))
// cond: c & -1<<63 == 0
// result: (LGDR (CPSDR <x.Type> (FMOVDconst <x.Type> [c]) x))
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpS390XAND {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpS390XMOVDconst || v_0_0.AuxInt != -1<<63 {
break
}
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpS390XLGDR {
break
}
x := v_0_1.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpS390XMOVDconst {
break
}
c := v_1.AuxInt
if !(c&-1<<63 == 0) {
break
}
v.reset(OpS390XLGDR)
v0 := b.NewValue0(v.Pos, OpS390XCPSDR, x.Type)
v1 := b.NewValue0(v.Pos, OpS390XFMOVDconst, x.Type)
v1.AuxInt = c
v0.AddArg(v1)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (OR (AND (LGDR x) (MOVDconst [-1<<63])) (MOVDconst [c]))
// cond: c & -1<<63 == 0
// result: (LGDR (CPSDR <x.Type> (FMOVDconst <x.Type> [c]) x))
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpS390XAND {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpS390XLGDR {
break
}
x := v_0_0.Args[0]
v_0_1 := v_0.Args[1]
if v_0_1.Op != OpS390XMOVDconst || v_0_1.AuxInt != -1<<63 {
break
}
v_1 := v.Args[1]
if v_1.Op != OpS390XMOVDconst {
break
}
c := v_1.AuxInt
if !(c&-1<<63 == 0) {
break
}
v.reset(OpS390XLGDR)
v0 := b.NewValue0(v.Pos, OpS390XCPSDR, x.Type)
v1 := b.NewValue0(v.Pos, OpS390XFMOVDconst, x.Type)
v1.AuxInt = c
v0.AddArg(v1)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (OR (MOVDconst [c]) (AND (MOVDconst [-1<<63]) (LGDR x)))
// cond: c & -1<<63 == 0
// result: (LGDR (CPSDR <x.Type> (FMOVDconst <x.Type> [c]) x))
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpS390XMOVDconst {
break
}
c := v_0.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpS390XAND {
break
}
_ = v_1.Args[1]
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpS390XMOVDconst || v_1_0.AuxInt != -1<<63 {
break
}
v_1_1 := v_1.Args[1]
if v_1_1.Op != OpS390XLGDR {
break
}
x := v_1_1.Args[0]
if !(c&-1<<63 == 0) {
break
}
v.reset(OpS390XLGDR)
v0 := b.NewValue0(v.Pos, OpS390XCPSDR, x.Type)
v1 := b.NewValue0(v.Pos, OpS390XFMOVDconst, x.Type)
v1.AuxInt = c
v0.AddArg(v1)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (OR (MOVDconst [c]) (AND (LGDR x) (MOVDconst [-1<<63])))
// cond: c & -1<<63 == 0
// result: (LGDR (CPSDR <x.Type> (FMOVDconst <x.Type> [c]) x))
for {
_ = v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpS390XMOVDconst {
break
}
c := v_0.AuxInt
v_1 := v.Args[1]
if v_1.Op != OpS390XAND {
break
}
_ = v_1.Args[1]
v_1_0 := v_1.Args[0]
if v_1_0.Op != OpS390XLGDR {
break
}
x := v_1_0.Args[0]
v_1_1 := v_1.Args[1]
if v_1_1.Op != OpS390XMOVDconst || v_1_1.AuxInt != -1<<63 || !(c&-1<<63 == 0) {
break
}
v.reset(OpS390XLGDR)
v0 := b.NewValue0(v.Pos, OpS390XCPSDR, x.Type)
v1 := b.NewValue0(v.Pos, OpS390XFMOVDconst, x.Type)
v1.AuxInt = c
v0.AddArg(v1)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (OR (MOVDconst [c]) (MOVDconst [d]))
// result: (MOVDconst [c|d])
for {
@ -20506,6 +20868,11 @@ func rewriteValueS390X_OpS390XOR_10(v *Value) bool {
v.AuxInt = c | d
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_20(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR x x)
// result: x
for {
@ -20741,11 +21108,6 @@ func rewriteValueS390X_OpS390XOR_10(v *Value) bool {
v0.AddArg(mem)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_20(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR sh:(SLDconst [16] x0:(MOVHZload [i0] {s} p mem)) x1:(MOVHZload [i1] {s} p mem))
// cond: i1 == i0+2 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVWZload [i0] {s} p mem)
@ -20824,6 +21186,11 @@ func rewriteValueS390X_OpS390XOR_20(v *Value) bool {
v0.AddArg(mem)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_30(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR sh:(SLDconst [32] x0:(MOVWZload [i0] {s} p mem)) x1:(MOVWZload [i1] {s} p mem))
// cond: i1 == i0+4 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVDload [i0] {s} p mem)
@ -21258,11 +21625,6 @@ func rewriteValueS390X_OpS390XOR_20(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_30(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR or:(OR y s1:(SLDconst [j1] x1:(MOVHZload [i1] {s} p mem))) s0:(SLDconst [j0] x0:(MOVHZload [i0] {s} p mem)))
// cond: i1 == i0+2 && j1 == j0-16 && j1 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j1] (MOVWZload [i0] {s} p mem)) y)
@ -21361,6 +21723,11 @@ func rewriteValueS390X_OpS390XOR_30(v *Value) bool {
v0.AddArg(mem)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_40(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR x1:(MOVBZloadidx [i1] {s} idx p mem) sh:(SLDconst [8] x0:(MOVBZloadidx [i0] {s} p idx mem)))
// cond: i1 == i0+1 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVHZloadidx [i0] {s} p idx mem)
@ -21689,11 +22056,6 @@ func rewriteValueS390X_OpS390XOR_30(v *Value) bool {
v0.AddArg(mem)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_40(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR x1:(MOVHZloadidx [i1] {s} idx p mem) sh:(SLDconst [16] x0:(MOVHZloadidx [i0] {s} p idx mem)))
// cond: i1 == i0+2 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVWZloadidx [i0] {s} p idx mem)
@ -21776,6 +22138,11 @@ func rewriteValueS390X_OpS390XOR_40(v *Value) bool {
v0.AddArg(mem)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_50(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR x1:(MOVHZloadidx [i1] {s} idx p mem) sh:(SLDconst [16] x0:(MOVHZloadidx [i0] {s} idx p mem)))
// cond: i1 == i0+2 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVWZloadidx [i0] {s} p idx mem)
@ -22104,11 +22471,6 @@ func rewriteValueS390X_OpS390XOR_40(v *Value) bool {
v0.AddArg(mem)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_50(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR x1:(MOVWZloadidx [i1] {s} idx p mem) sh:(SLDconst [32] x0:(MOVWZloadidx [i0] {s} idx p mem)))
// cond: i1 == i0+4 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVDloadidx [i0] {s} p idx mem)
@ -22191,6 +22553,11 @@ func rewriteValueS390X_OpS390XOR_50(v *Value) bool {
v0.AddArg(mem)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_60(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR sh:(SLDconst [32] x0:(MOVWZloadidx [i0] {s} idx p mem)) x1:(MOVWZloadidx [i1] {s} p idx mem))
// cond: i1 == i0+4 && p.Op != OpSB && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVDloadidx [i0] {s} p idx mem)
@ -22605,11 +22972,6 @@ func rewriteValueS390X_OpS390XOR_50(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_60(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR s0:(SLDconst [j0] x0:(MOVBZloadidx [i0] {s} idx p mem)) or:(OR y s1:(SLDconst [j1] x1:(MOVBZloadidx [i1] {s} p idx mem))))
// cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j1] (MOVHZloadidx [i0] {s} p idx mem)) y)
@ -22728,6 +23090,11 @@ func rewriteValueS390X_OpS390XOR_60(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_70(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR s0:(SLDconst [j0] x0:(MOVBZloadidx [i0] {s} idx p mem)) or:(OR y s1:(SLDconst [j1] x1:(MOVBZloadidx [i1] {s} idx p mem))))
// cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j1] (MOVHZloadidx [i0] {s} p idx mem)) y)
@ -23196,11 +23563,6 @@ func rewriteValueS390X_OpS390XOR_60(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_70(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR or:(OR y s1:(SLDconst [j1] x1:(MOVBZloadidx [i1] {s} idx p mem))) s0:(SLDconst [j0] x0:(MOVBZloadidx [i0] {s} idx p mem)))
// cond: i1 == i0+1 && j1 == j0-8 && j1 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j1] (MOVHZloadidx [i0] {s} p idx mem)) y)
@ -23318,6 +23680,11 @@ func rewriteValueS390X_OpS390XOR_70(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_80(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR s0:(SLDconst [j0] x0:(MOVHZloadidx [i0] {s} idx p mem)) or:(OR s1:(SLDconst [j1] x1:(MOVHZloadidx [i1] {s} p idx mem)) y))
// cond: i1 == i0+2 && j1 == j0-16 && j1 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j1] (MOVWZloadidx [i0] {s} p idx mem)) y)
@ -23786,11 +24153,6 @@ func rewriteValueS390X_OpS390XOR_70(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_80(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR or:(OR s1:(SLDconst [j1] x1:(MOVHZloadidx [i1] {s} idx p mem)) y) s0:(SLDconst [j0] x0:(MOVHZloadidx [i0] {s} p idx mem)))
// cond: i1 == i0+2 && j1 == j0-16 && j1 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j1] (MOVWZloadidx [i0] {s} p idx mem)) y)
@ -23908,6 +24270,11 @@ func rewriteValueS390X_OpS390XOR_80(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_90(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR or:(OR y s1:(SLDconst [j1] x1:(MOVHZloadidx [i1] {s} idx p mem))) s0:(SLDconst [j0] x0:(MOVHZloadidx [i0] {s} p idx mem)))
// cond: i1 == i0+2 && j1 == j0-16 && j1 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j1] (MOVWZloadidx [i0] {s} p idx mem)) y)
@ -24332,11 +24699,6 @@ func rewriteValueS390X_OpS390XOR_80(v *Value) bool {
v0.AddArg(v1)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_90(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR sh:(SLDconst [16] r1:(MOVHZreg x1:(MOVHBRload [i1] {s} p mem))) r0:(MOVHZreg x0:(MOVHBRload [i0] {s} p mem)))
// cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(r0) && clobber(r1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVWZreg (MOVWBRload [i0] {s} p mem))
@ -24433,6 +24795,11 @@ func rewriteValueS390X_OpS390XOR_90(v *Value) bool {
v0.AddArg(mem)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_100(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR sh:(SLDconst [32] r1:(MOVWZreg x1:(MOVWBRload [i1] {s} p mem))) r0:(MOVWZreg x0:(MOVWBRload [i0] {s} p mem)))
// cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(r0) && clobber(r1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVDBRload [i0] {s} p mem)
@ -24913,11 +25280,6 @@ func rewriteValueS390X_OpS390XOR_90(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_100(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR or:(OR y s0:(SLDconst [j0] r0:(MOVHZreg x0:(MOVHBRload [i0] {s} p mem)))) s1:(SLDconst [j1] r1:(MOVHZreg x1:(MOVHBRload [i1] {s} p mem))))
// cond: i1 == i0+2 && j1 == j0+16 && j0 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(r0) && clobber(r1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j0] (MOVWZreg (MOVWBRload [i0] {s} p mem))) y)
@ -25028,6 +25390,11 @@ func rewriteValueS390X_OpS390XOR_100(v *Value) bool {
v0.AddArg(v1)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_110(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR x0:(MOVBZloadidx [i0] {s} idx p mem) sh:(SLDconst [8] x1:(MOVBZloadidx [i1] {s} p idx mem)))
// cond: p.Op != OpSB && i1 == i0+1 && x0.Uses == 1 && x1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVHZreg (MOVHBRloadidx [i0] {s} p idx mem))
@ -25380,11 +25747,6 @@ func rewriteValueS390X_OpS390XOR_100(v *Value) bool {
v0.AddArg(v1)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_110(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR r0:(MOVHZreg x0:(MOVHBRloadidx [i0] {s} idx p mem)) sh:(SLDconst [16] r1:(MOVHZreg x1:(MOVHBRloadidx [i1] {s} p idx mem))))
// cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(r0) && clobber(r1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVWZreg (MOVWBRloadidx [i0] {s} p idx mem))
@ -25487,6 +25849,11 @@ func rewriteValueS390X_OpS390XOR_110(v *Value) bool {
v0.AddArg(v1)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_120(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR r0:(MOVHZreg x0:(MOVHBRloadidx [i0] {s} idx p mem)) sh:(SLDconst [16] r1:(MOVHZreg x1:(MOVHBRloadidx [i1] {s} idx p mem))))
// cond: i1 == i0+2 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(r0) && clobber(r1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVWZreg (MOVWBRloadidx [i0] {s} p idx mem))
@ -25889,11 +26256,6 @@ func rewriteValueS390X_OpS390XOR_110(v *Value) bool {
v0.AddArg(mem)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_120(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR r0:(MOVWZreg x0:(MOVWBRloadidx [i0] {s} idx p mem)) sh:(SLDconst [32] r1:(MOVWZreg x1:(MOVWBRloadidx [i1] {s} idx p mem))))
// cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(r0) && clobber(r1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVDBRloadidx [i0] {s} p idx mem)
@ -25992,6 +26354,11 @@ func rewriteValueS390X_OpS390XOR_120(v *Value) bool {
v0.AddArg(mem)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_130(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR sh:(SLDconst [32] r1:(MOVWZreg x1:(MOVWBRloadidx [i1] {s} idx p mem))) r0:(MOVWZreg x0:(MOVWBRloadidx [i0] {s} p idx mem)))
// cond: i1 == i0+4 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && sh.Uses == 1 && mergePoint(b,x0,x1) != nil && clobber(x0) && clobber(x1) && clobber(r0) && clobber(r1) && clobber(sh)
// result: @mergePoint(b,x0,x1) (MOVDBRloadidx [i0] {s} p idx mem)
@ -26440,11 +26807,6 @@ func rewriteValueS390X_OpS390XOR_120(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_130(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR s1:(SLDconst [j1] x1:(MOVBZloadidx [i1] {s} idx p mem)) or:(OR y s0:(SLDconst [j0] x0:(MOVBZloadidx [i0] {s} p idx mem))))
// cond: p.Op != OpSB && i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j0] (MOVHZreg (MOVHBRloadidx [i0] {s} p idx mem))) y)
@ -26567,6 +26929,11 @@ func rewriteValueS390X_OpS390XOR_130(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_140(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR s1:(SLDconst [j1] x1:(MOVBZloadidx [i1] {s} idx p mem)) or:(OR y s0:(SLDconst [j0] x0:(MOVBZloadidx [i0] {s} idx p mem))))
// cond: p.Op != OpSB && i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j0] (MOVHZreg (MOVHBRloadidx [i0] {s} p idx mem))) y)
@ -27051,11 +27418,6 @@ func rewriteValueS390X_OpS390XOR_130(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_140(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR or:(OR y s0:(SLDconst [j0] x0:(MOVBZloadidx [i0] {s} idx p mem))) s1:(SLDconst [j1] x1:(MOVBZloadidx [i1] {s} idx p mem)))
// cond: p.Op != OpSB && i1 == i0+1 && j1 == j0+8 && j0 % 16 == 0 && x0.Uses == 1 && x1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j0] (MOVHZreg (MOVHBRloadidx [i0] {s} p idx mem))) y)
@ -27185,6 +27547,11 @@ func rewriteValueS390X_OpS390XOR_140(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_150(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR s1:(SLDconst [j1] r1:(MOVHZreg x1:(MOVHBRloadidx [i1] {s} idx p mem))) or:(OR s0:(SLDconst [j0] r0:(MOVHZreg x0:(MOVHBRloadidx [i0] {s} p idx mem))) y))
// cond: i1 == i0+2 && j1 == j0+16 && j0 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(r0) && clobber(r1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j0] (MOVWZreg (MOVWBRloadidx [i0] {s} p idx mem))) y)
@ -27733,11 +28100,6 @@ func rewriteValueS390X_OpS390XOR_140(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_150(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR or:(OR s0:(SLDconst [j0] r0:(MOVHZreg x0:(MOVHBRloadidx [i0] {s} idx p mem))) y) s1:(SLDconst [j1] r1:(MOVHZreg x1:(MOVHBRloadidx [i1] {s} p idx mem))))
// cond: i1 == i0+2 && j1 == j0+16 && j0 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(r0) && clobber(r1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j0] (MOVWZreg (MOVWBRloadidx [i0] {s} p idx mem))) y)
@ -27875,6 +28237,11 @@ func rewriteValueS390X_OpS390XOR_150(v *Value) bool {
v0.AddArg(y)
return true
}
return false
}
func rewriteValueS390X_OpS390XOR_160(v *Value) bool {
b := v.Block
typ := &b.Func.Config.Types
// match: (OR or:(OR y s0:(SLDconst [j0] r0:(MOVHZreg x0:(MOVHBRloadidx [i0] {s} idx p mem)))) s1:(SLDconst [j1] r1:(MOVHZreg x1:(MOVHBRloadidx [i1] {s} p idx mem))))
// cond: i1 == i0+2 && j1 == j0+16 && j0 % 32 == 0 && x0.Uses == 1 && x1.Uses == 1 && r0.Uses == 1 && r1.Uses == 1 && s0.Uses == 1 && s1.Uses == 1 && or.Uses == 1 && mergePoint(b,x0,x1,y) != nil && clobber(x0) && clobber(x1) && clobber(r0) && clobber(r1) && clobber(s0) && clobber(s1) && clobber(or)
// result: @mergePoint(b,x0,x1,y) (OR <v.Type> (SLDconst <v.Type> [j0] (MOVWZreg (MOVWBRloadidx [i0] {s} p idx mem))) y)

View File

@ -5396,112 +5396,6 @@ func rewriteValuegeneric_OpAnd64_10(v *Value) bool {
v.AddArg(y)
return true
}
// match: (And64 <t> (Const64 [y]) x)
// cond: nlz(y) + nto(y) == 64 && nto(y) >= 32
// result: (Rsh64Ux64 (Lsh64x64 <t> x (Const64 <t> [nlz(y)])) (Const64 <t> [nlz(y)]))
for {
t := v.Type
x := v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpConst64 {
break
}
y := v_0.AuxInt
if !(nlz(y)+nto(y) == 64 && nto(y) >= 32) {
break
}
v.reset(OpRsh64Ux64)
v0 := b.NewValue0(v.Pos, OpLsh64x64, t)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpConst64, t)
v1.AuxInt = nlz(y)
v0.AddArg(v1)
v.AddArg(v0)
v2 := b.NewValue0(v.Pos, OpConst64, t)
v2.AuxInt = nlz(y)
v.AddArg(v2)
return true
}
// match: (And64 <t> x (Const64 [y]))
// cond: nlz(y) + nto(y) == 64 && nto(y) >= 32
// result: (Rsh64Ux64 (Lsh64x64 <t> x (Const64 <t> [nlz(y)])) (Const64 <t> [nlz(y)]))
for {
t := v.Type
_ = v.Args[1]
x := v.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
y := v_1.AuxInt
if !(nlz(y)+nto(y) == 64 && nto(y) >= 32) {
break
}
v.reset(OpRsh64Ux64)
v0 := b.NewValue0(v.Pos, OpLsh64x64, t)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpConst64, t)
v1.AuxInt = nlz(y)
v0.AddArg(v1)
v.AddArg(v0)
v2 := b.NewValue0(v.Pos, OpConst64, t)
v2.AuxInt = nlz(y)
v.AddArg(v2)
return true
}
// match: (And64 <t> (Const64 [y]) x)
// cond: nlo(y) + ntz(y) == 64 && ntz(y) >= 32
// result: (Lsh64x64 (Rsh64Ux64 <t> x (Const64 <t> [ntz(y)])) (Const64 <t> [ntz(y)]))
for {
t := v.Type
x := v.Args[1]
v_0 := v.Args[0]
if v_0.Op != OpConst64 {
break
}
y := v_0.AuxInt
if !(nlo(y)+ntz(y) == 64 && ntz(y) >= 32) {
break
}
v.reset(OpLsh64x64)
v0 := b.NewValue0(v.Pos, OpRsh64Ux64, t)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpConst64, t)
v1.AuxInt = ntz(y)
v0.AddArg(v1)
v.AddArg(v0)
v2 := b.NewValue0(v.Pos, OpConst64, t)
v2.AuxInt = ntz(y)
v.AddArg(v2)
return true
}
// match: (And64 <t> x (Const64 [y]))
// cond: nlo(y) + ntz(y) == 64 && ntz(y) >= 32
// result: (Lsh64x64 (Rsh64Ux64 <t> x (Const64 <t> [ntz(y)])) (Const64 <t> [ntz(y)]))
for {
t := v.Type
_ = v.Args[1]
x := v.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
y := v_1.AuxInt
if !(nlo(y)+ntz(y) == 64 && ntz(y) >= 32) {
break
}
v.reset(OpLsh64x64)
v0 := b.NewValue0(v.Pos, OpRsh64Ux64, t)
v0.AddArg(x)
v1 := b.NewValue0(v.Pos, OpConst64, t)
v1.AuxInt = ntz(y)
v0.AddArg(v1)
v.AddArg(v0)
v2 := b.NewValue0(v.Pos, OpConst64, t)
v2.AuxInt = ntz(y)
v.AddArg(v2)
return true
}
// match: (And64 (And64 i:(Const64 <t>) z) x)
// cond: (z.Op != OpConst64 && x.Op != OpConst64)
// result: (And64 i (And64 <t> z x))
@ -5528,10 +5422,6 @@ func rewriteValuegeneric_OpAnd64_10(v *Value) bool {
v.AddArg(v0)
return true
}
return false
}
func rewriteValuegeneric_OpAnd64_20(v *Value) bool {
b := v.Block
// match: (And64 (And64 z i:(Const64 <t>)) x)
// cond: (z.Op != OpConst64 && x.Op != OpConst64)
// result: (And64 i (And64 <t> z x))
@ -5641,6 +5531,10 @@ func rewriteValuegeneric_OpAnd64_20(v *Value) bool {
v.AddArg(x)
return true
}
return false
}
func rewriteValuegeneric_OpAnd64_20(v *Value) bool {
b := v.Block
// match: (And64 (Const64 <t> [c]) (And64 x (Const64 <t> [d])))
// result: (And64 (Const64 <t> [c&d]) x)
for {

View File

@ -81,7 +81,7 @@ func abs32(x float32) float32 {
// Check that it's using integer registers
func copysign(a, b, c float64) {
// amd64:"BTRQ\t[$]63","SHRQ\t[$]63","SHLQ\t[$]63","ORQ"
// amd64:"BTRQ\t[$]63","ANDQ","ORQ"
// s390x:"CPSDR",-"MOVD" (no integer load/store)
// ppc64:"FCPSGN"
// ppc64le:"FCPSGN"
@ -100,7 +100,7 @@ func copysign(a, b, c float64) {
// s390x:"LNDFR\t",-"MOVD\t" (no integer load/store)
sink64[2] = math.Float64frombits(math.Float64bits(a) | 1<<63)
// amd64:-"SHLQ\t[$]1",-"SHRQ\t[$]1","SHRQ\t[$]63","SHLQ\t[$]63","ORQ"
// amd64:"ANDQ","ORQ"
// s390x:"CPSDR\t",-"MOVD\t" (no integer load/store)
// ppc64:"FCPSGN"
// ppc64le:"FCPSGN"