From 4a1baf8bd11c8804a22aa8364028ce8d81b6e1f3 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 27 Apr 2018 08:50:39 -0700 Subject: [PATCH] cmd/compile: optimize a - b == 0 into a == b MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit These rules trigger 1141 times during make.bash. Shrinks a few object files a tiny bit: name old object-bytes new object-bytes delta Template 476kB ± 0% 476kB ± 0% +0.00% (p=0.008 n=5+5) Unicode 218kB ± 0% 218kB ± 0% ~ (all equal) GoTypes 1.58MB ± 0% 1.58MB ± 0% ~ (all equal) Compiler 6.25MB ± 0% 6.25MB ± 0% -0.00% (p=0.008 n=5+5) Flate 304kB ± 0% 304kB ± 0% -0.01% (p=0.008 n=5+5) GoParser 370kB ± 0% 370kB ± 0% ~ (all equal) Reflect 1.27MB ± 0% 1.27MB ± 0% ~ (all equal) Tar 421kB ± 0% 421kB ± 0% -0.05% (p=0.008 n=5+5) XML 518kB ± 0% 518kB ± 0% ~ (all equal) archive/tar benchmarks: name old time/op new time/op delta /Writer/USTAR-8 3.97µs ± 1% 3.88µs ± 0% -2.26% (p=0.000 n=26+26) /Writer/GNU-8 4.67µs ± 0% 4.54µs ± 1% -2.72% (p=0.000 n=28+27) /Writer/PAX-8 8.20µs ± 0% 8.01µs ± 0% -2.32% (p=0.000 n=29+29) /Reader/USTAR-8 3.61µs ± 0% 3.54µs ± 1% -2.04% (p=0.000 n=25+28) /Reader/GNU-8 2.27µs ± 2% 2.17µs ± 0% -4.08% (p=0.000 n=30+28) /Reader/PAX-8 7.75µs ± 0% 7.63µs ± 0% -1.60% (p=0.000 n=28+28) [Geo mean] 4.61µs 4.50µs -2.51% Change-Id: Ib4dfade5069a7463ccaba073ea91c8213e9714a0 Reviewed-on: https://go-review.googlesource.com/110235 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Ilya Tocar Reviewed-by: Keith Randall --- .../compile/internal/ssa/gen/generic.rules | 3 + .../compile/internal/ssa/rewritegeneric.go | 432 ++++++++++++++++++ 2 files changed, 435 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 16b2792a5e..f6a5f857e4 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -1072,6 +1072,9 @@ (Mod64u x (Const64 [c])) && x.Op != OpConst64 && c > 0 && umagicOK(64,c) -> (Sub64 x (Mul64 (Div64u x (Const64 [c])) (Const64 [c]))) +(Eq(8|16|32|64) s:(Sub(8|16|32|64) x y) (Const(8|16|32|64) [0])) && s.Uses == 1 -> (Eq(8|16|32|64) x y) +(Neq(8|16|32|64) s:(Sub(8|16|32|64) x y) (Const(8|16|32|64) [0])) && s.Uses == 1 -> (Neq(8|16|32|64) x y) + // Reassociate expressions involving // constants such that constants come first, // exposing obvious constant-folding opportunities. diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 7e1c56675e..d590a357d1 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -9451,6 +9451,60 @@ func rewriteValuegeneric_OpEq16_0(v *Value) bool { v.AuxInt = b2i(c == d) return true } + // match: (Eq16 s:(Sub16 x y) (Const16 [0])) + // cond: s.Uses == 1 + // result: (Eq16 x y) + for { + _ = v.Args[1] + s := v.Args[0] + if s.Op != OpSub16 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + v_1 := v.Args[1] + if v_1.Op != OpConst16 { + break + } + if v_1.AuxInt != 0 { + break + } + if !(s.Uses == 1) { + break + } + v.reset(OpEq16) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (Eq16 (Const16 [0]) s:(Sub16 x y)) + // cond: s.Uses == 1 + // result: (Eq16 x y) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + if v_0.AuxInt != 0 { + break + } + s := v.Args[1] + if s.Op != OpSub16 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + if !(s.Uses == 1) { + break + } + v.reset(OpEq16) + v.AddArg(x) + v.AddArg(y) + return true + } return false } func rewriteValuegeneric_OpEq32_0(v *Value) bool { @@ -9635,6 +9689,60 @@ func rewriteValuegeneric_OpEq32_0(v *Value) bool { v.AuxInt = b2i(c == d) return true } + // match: (Eq32 s:(Sub32 x y) (Const32 [0])) + // cond: s.Uses == 1 + // result: (Eq32 x y) + for { + _ = v.Args[1] + s := v.Args[0] + if s.Op != OpSub32 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + v_1 := v.Args[1] + if v_1.Op != OpConst32 { + break + } + if v_1.AuxInt != 0 { + break + } + if !(s.Uses == 1) { + break + } + v.reset(OpEq32) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (Eq32 (Const32 [0]) s:(Sub32 x y)) + // cond: s.Uses == 1 + // result: (Eq32 x y) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + if v_0.AuxInt != 0 { + break + } + s := v.Args[1] + if s.Op != OpSub32 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + if !(s.Uses == 1) { + break + } + v.reset(OpEq32) + v.AddArg(x) + v.AddArg(y) + return true + } return false } func rewriteValuegeneric_OpEq32F_0(v *Value) bool { @@ -9860,6 +9968,60 @@ func rewriteValuegeneric_OpEq64_0(v *Value) bool { v.AuxInt = b2i(c == d) return true } + // match: (Eq64 s:(Sub64 x y) (Const64 [0])) + // cond: s.Uses == 1 + // result: (Eq64 x y) + for { + _ = v.Args[1] + s := v.Args[0] + if s.Op != OpSub64 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + v_1 := v.Args[1] + if v_1.Op != OpConst64 { + break + } + if v_1.AuxInt != 0 { + break + } + if !(s.Uses == 1) { + break + } + v.reset(OpEq64) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (Eq64 (Const64 [0]) s:(Sub64 x y)) + // cond: s.Uses == 1 + // result: (Eq64 x y) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + if v_0.AuxInt != 0 { + break + } + s := v.Args[1] + if s.Op != OpSub64 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + if !(s.Uses == 1) { + break + } + v.reset(OpEq64) + v.AddArg(x) + v.AddArg(y) + return true + } return false } func rewriteValuegeneric_OpEq64F_0(v *Value) bool { @@ -10085,6 +10247,60 @@ func rewriteValuegeneric_OpEq8_0(v *Value) bool { v.AuxInt = b2i(c == d) return true } + // match: (Eq8 s:(Sub8 x y) (Const8 [0])) + // cond: s.Uses == 1 + // result: (Eq8 x y) + for { + _ = v.Args[1] + s := v.Args[0] + if s.Op != OpSub8 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + v_1 := v.Args[1] + if v_1.Op != OpConst8 { + break + } + if v_1.AuxInt != 0 { + break + } + if !(s.Uses == 1) { + break + } + v.reset(OpEq8) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (Eq8 (Const8 [0]) s:(Sub8 x y)) + // cond: s.Uses == 1 + // result: (Eq8 x y) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + if v_0.AuxInt != 0 { + break + } + s := v.Args[1] + if s.Op != OpSub8 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + if !(s.Uses == 1) { + break + } + v.reset(OpEq8) + v.AddArg(x) + v.AddArg(y) + return true + } return false } func rewriteValuegeneric_OpEqB_0(v *Value) bool { @@ -17525,6 +17741,60 @@ func rewriteValuegeneric_OpNeq16_0(v *Value) bool { v.AuxInt = b2i(c != d) return true } + // match: (Neq16 s:(Sub16 x y) (Const16 [0])) + // cond: s.Uses == 1 + // result: (Neq16 x y) + for { + _ = v.Args[1] + s := v.Args[0] + if s.Op != OpSub16 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + v_1 := v.Args[1] + if v_1.Op != OpConst16 { + break + } + if v_1.AuxInt != 0 { + break + } + if !(s.Uses == 1) { + break + } + v.reset(OpNeq16) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (Neq16 (Const16 [0]) s:(Sub16 x y)) + // cond: s.Uses == 1 + // result: (Neq16 x y) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + if v_0.AuxInt != 0 { + break + } + s := v.Args[1] + if s.Op != OpSub16 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + if !(s.Uses == 1) { + break + } + v.reset(OpNeq16) + v.AddArg(x) + v.AddArg(y) + return true + } return false } func rewriteValuegeneric_OpNeq32_0(v *Value) bool { @@ -17709,6 +17979,60 @@ func rewriteValuegeneric_OpNeq32_0(v *Value) bool { v.AuxInt = b2i(c != d) return true } + // match: (Neq32 s:(Sub32 x y) (Const32 [0])) + // cond: s.Uses == 1 + // result: (Neq32 x y) + for { + _ = v.Args[1] + s := v.Args[0] + if s.Op != OpSub32 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + v_1 := v.Args[1] + if v_1.Op != OpConst32 { + break + } + if v_1.AuxInt != 0 { + break + } + if !(s.Uses == 1) { + break + } + v.reset(OpNeq32) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (Neq32 (Const32 [0]) s:(Sub32 x y)) + // cond: s.Uses == 1 + // result: (Neq32 x y) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + if v_0.AuxInt != 0 { + break + } + s := v.Args[1] + if s.Op != OpSub32 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + if !(s.Uses == 1) { + break + } + v.reset(OpNeq32) + v.AddArg(x) + v.AddArg(y) + return true + } return false } func rewriteValuegeneric_OpNeq32F_0(v *Value) bool { @@ -17934,6 +18258,60 @@ func rewriteValuegeneric_OpNeq64_0(v *Value) bool { v.AuxInt = b2i(c != d) return true } + // match: (Neq64 s:(Sub64 x y) (Const64 [0])) + // cond: s.Uses == 1 + // result: (Neq64 x y) + for { + _ = v.Args[1] + s := v.Args[0] + if s.Op != OpSub64 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + v_1 := v.Args[1] + if v_1.Op != OpConst64 { + break + } + if v_1.AuxInt != 0 { + break + } + if !(s.Uses == 1) { + break + } + v.reset(OpNeq64) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (Neq64 (Const64 [0]) s:(Sub64 x y)) + // cond: s.Uses == 1 + // result: (Neq64 x y) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + if v_0.AuxInt != 0 { + break + } + s := v.Args[1] + if s.Op != OpSub64 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + if !(s.Uses == 1) { + break + } + v.reset(OpNeq64) + v.AddArg(x) + v.AddArg(y) + return true + } return false } func rewriteValuegeneric_OpNeq64F_0(v *Value) bool { @@ -18159,6 +18537,60 @@ func rewriteValuegeneric_OpNeq8_0(v *Value) bool { v.AuxInt = b2i(c != d) return true } + // match: (Neq8 s:(Sub8 x y) (Const8 [0])) + // cond: s.Uses == 1 + // result: (Neq8 x y) + for { + _ = v.Args[1] + s := v.Args[0] + if s.Op != OpSub8 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + v_1 := v.Args[1] + if v_1.Op != OpConst8 { + break + } + if v_1.AuxInt != 0 { + break + } + if !(s.Uses == 1) { + break + } + v.reset(OpNeq8) + v.AddArg(x) + v.AddArg(y) + return true + } + // match: (Neq8 (Const8 [0]) s:(Sub8 x y)) + // cond: s.Uses == 1 + // result: (Neq8 x y) + for { + _ = v.Args[1] + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + if v_0.AuxInt != 0 { + break + } + s := v.Args[1] + if s.Op != OpSub8 { + break + } + _ = s.Args[1] + x := s.Args[0] + y := s.Args[1] + if !(s.Uses == 1) { + break + } + v.reset(OpNeq8) + v.AddArg(x) + v.AddArg(y) + return true + } return false } func rewriteValuegeneric_OpNeqB_0(v *Value) bool { -- 2.50.0