From 5bb59b6d1645144dade71e8d19ccf39338788a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Mon, 9 Sep 2019 07:22:14 +0000 Subject: Revert "compile: prefer an AND instead of SHR+SHL instructions" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 9ec7074a946b7c2812a1a044e84276a36f46d14d. Reason for revert: broke s390x (copysign, abs) and arm64 (bitfield) tests. Change-Id: I16c1b389c062e8c4aa5de079f1d46c9b25b0db52 Reviewed-on: https://go-review.googlesource.com/c/go/+/193850 Run-TryBot: Martin Möhrmann Reviewed-by: Agniva De Sarker TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/ssa/gen/ARM64.rules | 5 +- src/cmd/compile/internal/ssa/gen/generic.rules | 8 ++ src/cmd/compile/internal/ssa/rewritegeneric.go | 114 ++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 6539a0ce7b..d4b47bfb0b 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -1863,8 +1863,9 @@ (XORshiftLL [c] (UBFX [bfc] x) x2) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c) -> (EXTRWconst [32-c] x2 x) -// Rewrite special pairs of shifts to AND. -// On ARM64 the bitmask can fit into an instruction. +// 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. (SRLconst [c] (SLLconst [c] x)) && 0 < c && c < 64 -> (ANDconst [1< (ANDconst [^(1< 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 (Const64 [y]) x) && nlz(y) + nto(y) == 64 && nto(y) >= 32 + -> (Rsh64Ux64 (Lsh64x64 x (Const64 [nlz(y)])) (Const64 [nlz(y)])) +// trailing zeros can be shifted right, then left +(And64 (Const64 [y]) x) && nlo(y) + ntz(y) == 64 && ntz(y) >= 32 + -> (Lsh64x64 (Rsh64Ux64 x (Const64 [ntz(y)])) (Const64 [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 diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index a2d091d3d6..8aa07d20db 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -5735,6 +5735,112 @@ func rewriteValuegeneric_OpAnd64_10(v *Value) bool { v.AddArg(y) return true } + // match: (And64 (Const64 [y]) x) + // cond: nlz(y) + nto(y) == 64 && nto(y) >= 32 + // result: (Rsh64Ux64 (Lsh64x64 x (Const64 [nlz(y)])) (Const64 [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 x (Const64 [y])) + // cond: nlz(y) + nto(y) == 64 && nto(y) >= 32 + // result: (Rsh64Ux64 (Lsh64x64 x (Const64 [nlz(y)])) (Const64 [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 (Const64 [y]) x) + // cond: nlo(y) + ntz(y) == 64 && ntz(y) >= 32 + // result: (Lsh64x64 (Rsh64Ux64 x (Const64 [ntz(y)])) (Const64 [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 x (Const64 [y])) + // cond: nlo(y) + ntz(y) == 64 && ntz(y) >= 32 + // result: (Lsh64x64 (Rsh64Ux64 x (Const64 [ntz(y)])) (Const64 [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 ) z) x) // cond: (z.Op != OpConst64 && x.Op != OpConst64) // result: (And64 i (And64 z x)) @@ -5761,6 +5867,10 @@ 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 )) x) // cond: (z.Op != OpConst64 && x.Op != OpConst64) // result: (And64 i (And64 z x)) @@ -5874,10 +5984,6 @@ func rewriteValuegeneric_OpAnd64_10(v *Value) bool { v.AddArg(x) return true } - return false -} -func rewriteValuegeneric_OpAnd64_20(v *Value) bool { - b := v.Block // match: (And64 (Const64 [c]) (And64 x (Const64 [d]))) // cond: // result: (And64 (Const64 [c&d]) x) -- cgit v1.2.1