mirror of
https://github.com/golang/go
synced 2024-11-12 08:10:21 -07:00
[dev.ssa] cmd/compile/internal/ssa: handle rewrite of Phis.
* Phis can have variable number of arguments, but rulegen assumed that each operation has fixed number of arguments. * Rewriting Phis is necessary to handle the following case: func f1_ssa(a bool, x int) int { v := 0 if a { v = -1 } else { v = -1 } return x|v } Change-Id: Iff6bd411b854f3d1d6d3ce21934bf566757094f2 Reviewed-on: https://go-review.googlesource.com/19412 Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
7f7f7cddec
commit
d0d04d2d6c
@ -358,6 +358,26 @@ func testSubConst() {
|
||||
}
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func orPhi_ssa(a bool, x int) int {
|
||||
v := 0
|
||||
if a {
|
||||
v = -1
|
||||
} else {
|
||||
v = -1
|
||||
}
|
||||
return x | v
|
||||
}
|
||||
|
||||
func testOrPhi() {
|
||||
if want, got := -1, orPhi_ssa(true, 4); got != want {
|
||||
println("orPhi_ssa(true, 4)=", got, " want ", want)
|
||||
}
|
||||
if want, got := -1, orPhi_ssa(false, 0); got != want {
|
||||
println("orPhi_ssa(false, 0)=", got, " want ", want)
|
||||
}
|
||||
}
|
||||
|
||||
var failed = false
|
||||
|
||||
func main() {
|
||||
|
@ -263,6 +263,12 @@
|
||||
(Sub8 (Add8 x y) x) -> y
|
||||
(Sub8 (Add8 x y) y) -> x
|
||||
|
||||
// basic phi simplifications
|
||||
(Phi (Const8 [c]) (Const8 [d])) && int8(c) == int8(d) -> (Const8 [c])
|
||||
(Phi (Const16 [c]) (Const16 [d])) && int16(c) == int16(d) -> (Const16 [c])
|
||||
(Phi (Const32 [c]) (Const32 [d])) && int32(c) == int32(d) -> (Const32 [c])
|
||||
(Phi (Const64 [c]) (Const64 [c])) -> (Const64 [c])
|
||||
|
||||
// user nil checks
|
||||
(NeqPtr p (ConstNil)) -> (IsNonNil p)
|
||||
(NeqPtr (ConstNil) p) -> (IsNonNil p)
|
||||
|
@ -240,8 +240,8 @@ var genericOps = []opData{
|
||||
{name: "Sqrt"}, // sqrt(arg0), float64 only
|
||||
|
||||
// Data movement
|
||||
{name: "Phi"}, // select an argument based on which predecessor block we came from
|
||||
{name: "Copy"}, // output = arg0
|
||||
{name: "Phi", variableLength: true}, // select an argument based on which predecessor block we came from
|
||||
{name: "Copy"}, // output = arg0
|
||||
// Convert converts between pointers and integers.
|
||||
// We have a special op for this so as to not confuse GC
|
||||
// (particularly stack maps). It takes a memory arg so it
|
||||
|
@ -32,6 +32,7 @@ type opData struct {
|
||||
typ string // default result type
|
||||
aux string
|
||||
rematerializeable bool
|
||||
variableLength bool // if true the operation has a variable number of arguments
|
||||
}
|
||||
|
||||
type blockData struct {
|
||||
|
@ -395,6 +395,23 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]string, top
|
||||
argnum++
|
||||
}
|
||||
}
|
||||
|
||||
variableLength := false
|
||||
for _, op := range genericOps {
|
||||
if op.name == s[0] {
|
||||
variableLength = op.variableLength
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, op := range arch.ops {
|
||||
if op.name == s[0] {
|
||||
variableLength = op.variableLength
|
||||
break
|
||||
}
|
||||
}
|
||||
if variableLength {
|
||||
fmt.Fprintf(w, "if len(%s.Args) != %d {\nbreak\n}\n", v, argnum)
|
||||
}
|
||||
}
|
||||
|
||||
func genResult(w io.Writer, arch arch, result string) {
|
||||
|
@ -213,6 +213,8 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
||||
return rewriteValuegeneric_OpOr64(v, config)
|
||||
case OpOr8:
|
||||
return rewriteValuegeneric_OpOr8(v, config)
|
||||
case OpPhi:
|
||||
return rewriteValuegeneric_OpPhi(v, config)
|
||||
case OpPtrIndex:
|
||||
return rewriteValuegeneric_OpPtrIndex(v, config)
|
||||
case OpRsh16Ux16:
|
||||
@ -3965,6 +3967,98 @@ func rewriteValuegeneric_OpOr8(v *Value, config *Config) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValuegeneric_OpPhi(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (Phi (Const8 [c]) (Const8 [d]))
|
||||
// cond: int8(c) == int8(d)
|
||||
// result: (Const8 [c])
|
||||
for {
|
||||
if v.Args[0].Op != OpConst8 {
|
||||
break
|
||||
}
|
||||
c := v.Args[0].AuxInt
|
||||
if v.Args[1].Op != OpConst8 {
|
||||
break
|
||||
}
|
||||
d := v.Args[1].AuxInt
|
||||
if len(v.Args) != 2 {
|
||||
break
|
||||
}
|
||||
if !(int8(c) == int8(d)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpConst8)
|
||||
v.AuxInt = c
|
||||
return true
|
||||
}
|
||||
// match: (Phi (Const16 [c]) (Const16 [d]))
|
||||
// cond: int16(c) == int16(d)
|
||||
// result: (Const16 [c])
|
||||
for {
|
||||
if v.Args[0].Op != OpConst16 {
|
||||
break
|
||||
}
|
||||
c := v.Args[0].AuxInt
|
||||
if v.Args[1].Op != OpConst16 {
|
||||
break
|
||||
}
|
||||
d := v.Args[1].AuxInt
|
||||
if len(v.Args) != 2 {
|
||||
break
|
||||
}
|
||||
if !(int16(c) == int16(d)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpConst16)
|
||||
v.AuxInt = c
|
||||
return true
|
||||
}
|
||||
// match: (Phi (Const32 [c]) (Const32 [d]))
|
||||
// cond: int32(c) == int32(d)
|
||||
// result: (Const32 [c])
|
||||
for {
|
||||
if v.Args[0].Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
c := v.Args[0].AuxInt
|
||||
if v.Args[1].Op != OpConst32 {
|
||||
break
|
||||
}
|
||||
d := v.Args[1].AuxInt
|
||||
if len(v.Args) != 2 {
|
||||
break
|
||||
}
|
||||
if !(int32(c) == int32(d)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpConst32)
|
||||
v.AuxInt = c
|
||||
return true
|
||||
}
|
||||
// match: (Phi (Const64 [c]) (Const64 [c]))
|
||||
// cond:
|
||||
// result: (Const64 [c])
|
||||
for {
|
||||
if v.Args[0].Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
c := v.Args[0].AuxInt
|
||||
if v.Args[1].Op != OpConst64 {
|
||||
break
|
||||
}
|
||||
if v.Args[1].AuxInt != v.Args[0].AuxInt {
|
||||
break
|
||||
}
|
||||
if len(v.Args) != 2 {
|
||||
break
|
||||
}
|
||||
v.reset(OpConst64)
|
||||
v.AuxInt = c
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValuegeneric_OpPtrIndex(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
|
Loading…
Reference in New Issue
Block a user