From: Stefan Date: Wed, 10 May 2023 01:34:47 +0000 (+0000) Subject: cmd/compile: add De Morgan's rewrite rule X-Git-Tag: go1.21rc1~610 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=95c4f320d55fabf04ba45685109691f182678c01;p=gostls13.git cmd/compile: add De Morgan's rewrite rule Adds rules that rewrites statements such as ~P&~Q as ~(P|Q) and ~P|~Q as ~(P&Q), removing an extraneous instruction. Change-Id: Icedb97df741680ddf9799df79df78657173aa500 GitHub-Last-Rev: f22e2350c95e9052e990b2351c3c2b0af810e381 GitHub-Pull-Request: golang/go#60018 Reviewed-on: https://go-review.googlesource.com/c/go/+/493175 Reviewed-by: Keith Randall TryBot-Result: Gopher Robot Reviewed-by: Stefan M Reviewed-by: Keith Randall Run-TryBot: Cherry Mui Reviewed-by: Cherry Mui --- diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules index c7a525abb7..2ee8010857 100644 --- a/src/cmd/compile/internal/ssa/_gen/generic.rules +++ b/src/cmd/compile/internal/ssa/_gen/generic.rules @@ -176,6 +176,10 @@ // Convert x * -1 to -x. (Mul(8|16|32|64) (Const(8|16|32|64) [-1]) x) => (Neg(8|16|32|64) x) +// DeMorgan's Laws +(And(8|16|32|64) (Com(8|16|32|64) x) (Com(8|16|32|64) y)) => (Com(8|16|32|64) (Or(8|16|32|64) x y)) +(Or(8|16|32|64) (Com(8|16|32|64) x) (Com(8|16|32|64) y)) => (Com(8|16|32|64) (And(8|16|32|64) x y)) + // Convert multiplication by a power of two to a shift. (Mul8 n (Const8 [c])) && isPowerOfTwo8(c) => (Lsh8x64 n (Const64 [log8(c)])) (Mul16 n (Const16 [c])) && isPowerOfTwo16(c) => (Lsh16x64 n (Const64 [log16(c)])) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 6026eac279..78f13e679d 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -3020,6 +3020,27 @@ func rewriteValuegeneric_OpAnd16(v *Value) bool { } break } + // match: (And16 (Com16 x) (Com16 y)) + // result: (Com16 (Or16 x y)) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpCom16 { + continue + } + x := v_0.Args[0] + if v_1.Op != OpCom16 { + continue + } + y := v_1.Args[0] + v.reset(OpCom16) + v0 := b.NewValue0(v.Pos, OpOr16, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } // match: (And16 (Const16 [m]) (Rsh16Ux64 _ (Const64 [c]))) // cond: c >= int64(16-ntz16(m)) // result: (Const16 [0]) @@ -3235,6 +3256,27 @@ func rewriteValuegeneric_OpAnd32(v *Value) bool { } break } + // match: (And32 (Com32 x) (Com32 y)) + // result: (Com32 (Or32 x y)) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpCom32 { + continue + } + x := v_0.Args[0] + if v_1.Op != OpCom32 { + continue + } + y := v_1.Args[0] + v.reset(OpCom32) + v0 := b.NewValue0(v.Pos, OpOr32, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } // match: (And32 (Const32 [m]) (Rsh32Ux64 _ (Const64 [c]))) // cond: c >= int64(32-ntz32(m)) // result: (Const32 [0]) @@ -3450,6 +3492,27 @@ func rewriteValuegeneric_OpAnd64(v *Value) bool { } break } + // match: (And64 (Com64 x) (Com64 y)) + // result: (Com64 (Or64 x y)) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpCom64 { + continue + } + x := v_0.Args[0] + if v_1.Op != OpCom64 { + continue + } + y := v_1.Args[0] + v.reset(OpCom64) + v0 := b.NewValue0(v.Pos, OpOr64, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } // match: (And64 (Const64 [m]) (Rsh64Ux64 _ (Const64 [c]))) // cond: c >= int64(64-ntz64(m)) // result: (Const64 [0]) @@ -3665,6 +3728,27 @@ func rewriteValuegeneric_OpAnd8(v *Value) bool { } break } + // match: (And8 (Com8 x) (Com8 y)) + // result: (Com8 (Or8 x y)) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpCom8 { + continue + } + x := v_0.Args[0] + if v_1.Op != OpCom8 { + continue + } + y := v_1.Args[0] + v.reset(OpCom8) + v0 := b.NewValue0(v.Pos, OpOr8, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } // match: (And8 (Const8 [m]) (Rsh8Ux64 _ (Const64 [c]))) // cond: c >= int64(8-ntz8(m)) // result: (Const8 [0]) @@ -11096,6 +11180,16 @@ func rewriteValuegeneric_OpIsNonNil(v *Value) bool { v.AuxInt = boolToAuxInt(true) return true } + // match: (IsNonNil (LocalAddr _ _)) + // result: (ConstBool [true]) + for { + if v_0.Op != OpLocalAddr { + break + } + v.reset(OpConstBool) + v.AuxInt = boolToAuxInt(true) + return true + } return false } func rewriteValuegeneric_OpIsSliceInBounds(v *Value) bool { @@ -19109,6 +19203,27 @@ func rewriteValuegeneric_OpOr16(v *Value) bool { } break } + // match: (Or16 (Com16 x) (Com16 y)) + // result: (Com16 (And16 x y)) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpCom16 { + continue + } + x := v_0.Args[0] + if v_1.Op != OpCom16 { + continue + } + y := v_1.Args[0] + v.reset(OpCom16) + v0 := b.NewValue0(v.Pos, OpAnd16, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } // match: (Or16 x x) // result: x for { @@ -19613,6 +19728,27 @@ func rewriteValuegeneric_OpOr32(v *Value) bool { } break } + // match: (Or32 (Com32 x) (Com32 y)) + // result: (Com32 (And32 x y)) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpCom32 { + continue + } + x := v_0.Args[0] + if v_1.Op != OpCom32 { + continue + } + y := v_1.Args[0] + v.reset(OpCom32) + v0 := b.NewValue0(v.Pos, OpAnd32, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } // match: (Or32 x x) // result: x for { @@ -20117,6 +20253,27 @@ func rewriteValuegeneric_OpOr64(v *Value) bool { } break } + // match: (Or64 (Com64 x) (Com64 y)) + // result: (Com64 (And64 x y)) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpCom64 { + continue + } + x := v_0.Args[0] + if v_1.Op != OpCom64 { + continue + } + y := v_1.Args[0] + v.reset(OpCom64) + v0 := b.NewValue0(v.Pos, OpAnd64, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } // match: (Or64 x x) // result: x for { @@ -20621,6 +20778,27 @@ func rewriteValuegeneric_OpOr8(v *Value) bool { } break } + // match: (Or8 (Com8 x) (Com8 y)) + // result: (Com8 (And8 x y)) + for { + t := v.Type + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + if v_0.Op != OpCom8 { + continue + } + x := v_0.Args[0] + if v_1.Op != OpCom8 { + continue + } + y := v_1.Args[0] + v.reset(OpCom8) + v0 := b.NewValue0(v.Pos, OpAnd8, t) + v0.AddArg2(x, y) + v.AddArg(v0) + return true + } + break + } // match: (Or8 x x) // result: x for { diff --git a/test/codegen/logic.go b/test/codegen/logic.go index 748c639d6b..ac33f91dad 100644 --- a/test/codegen/logic.go +++ b/test/codegen/logic.go @@ -25,3 +25,17 @@ func ornot(x, y int) int { z := x | ^y return z } + +// Verify that (OR (NOT x) (NOT y)) rewrites to (NOT (AND x y)) +func orDemorgans(x, y int) int { + // amd64:"AND",-"OR" + z := ^x | ^y + return z +} + +// Verify that (AND (NOT x) (NOT y)) rewrites to (NOT (OR x y)) +func andDemorgans(x, y int) int { + // amd64:"OR",-"AND" + z := ^x & ^y + return z +}