mirror of
https://github.com/golang/go
synced 2024-10-05 20:21:21 -06:00
[dev.ssa] cmd/compile: make sure we don't move loads between blocks
This can lead to multiple stores being live at once. Do OINDEX and ODOT using addresses & loads instead of specific ops. This keeps SSA values from containing unSSAable types. Change-Id: I79567e9d43cdee09084eb89ea0bd7aa3aad48ada Reviewed-on: https://go-review.googlesource.com/15654 Run-TryBot: Keith Randall <khr@golang.org> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
32ffbf7e0f
commit
9703564c9a
@ -1732,8 +1732,9 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||||||
return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
|
return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
|
||||||
|
|
||||||
case ODOT:
|
case ODOT:
|
||||||
v := s.expr(n.Left)
|
// TODO: fix when we can SSA struct types.
|
||||||
return s.newValue1I(ssa.OpStructSelect, n.Type, n.Xoffset, v)
|
p := s.addr(n)
|
||||||
|
return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
|
||||||
|
|
||||||
case ODOTPTR:
|
case ODOTPTR:
|
||||||
p := s.expr(n.Left)
|
p := s.expr(n.Left)
|
||||||
@ -1742,29 +1743,29 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||||||
return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
|
return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
|
||||||
|
|
||||||
case OINDEX:
|
case OINDEX:
|
||||||
if n.Left.Type.Bound >= 0 { // array or string
|
switch {
|
||||||
|
case n.Left.Type.IsString():
|
||||||
a := s.expr(n.Left)
|
a := s.expr(n.Left)
|
||||||
i := s.expr(n.Right)
|
i := s.expr(n.Right)
|
||||||
i = s.extendIndex(i)
|
i = s.extendIndex(i)
|
||||||
if n.Left.Type.IsString() {
|
if !n.Bounded {
|
||||||
if !n.Bounded {
|
len := s.newValue1(ssa.OpStringLen, Types[TINT], a)
|
||||||
len := s.newValue1(ssa.OpStringLen, Types[TINT], a)
|
s.boundsCheck(i, len)
|
||||||
s.boundsCheck(i, len)
|
|
||||||
}
|
|
||||||
ptrtyp := Ptrto(Types[TUINT8])
|
|
||||||
ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a)
|
|
||||||
ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
|
|
||||||
return s.newValue2(ssa.OpLoad, Types[TUINT8], ptr, s.mem())
|
|
||||||
} else {
|
|
||||||
if !n.Bounded {
|
|
||||||
len := s.constInt(Types[TINT], n.Left.Type.Bound)
|
|
||||||
s.boundsCheck(i, len)
|
|
||||||
}
|
|
||||||
return s.newValue2(ssa.OpArrayIndex, n.Left.Type.Type, a, i)
|
|
||||||
}
|
}
|
||||||
} else { // slice
|
ptrtyp := Ptrto(Types[TUINT8])
|
||||||
|
ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a)
|
||||||
|
ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
|
||||||
|
return s.newValue2(ssa.OpLoad, Types[TUINT8], ptr, s.mem())
|
||||||
|
case n.Left.Type.IsSlice():
|
||||||
p := s.addr(n)
|
p := s.addr(n)
|
||||||
return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem())
|
return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem())
|
||||||
|
case n.Left.Type.IsArray():
|
||||||
|
// TODO: fix when we can SSA arrays of length 1.
|
||||||
|
p := s.addr(n)
|
||||||
|
return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem())
|
||||||
|
default:
|
||||||
|
s.Fatalf("bad type for index %v", n.Left.Type)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
case OLEN, OCAP:
|
case OLEN, OCAP:
|
||||||
|
@ -75,9 +75,9 @@
|
|||||||
|
|
||||||
// indexing operations
|
// indexing operations
|
||||||
// Note: bounds check has already been done
|
// Note: bounds check has already been done
|
||||||
(ArrayIndex (Load ptr mem) idx) -> (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem)
|
(ArrayIndex (Load ptr mem) idx) && b == v.Args[0].Block -> (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem)
|
||||||
(PtrIndex <t> ptr idx) -> (AddPtr ptr (MulPtr idx (ConstPtr [t.Elem().Size()])))
|
(PtrIndex <t> ptr idx) -> (AddPtr ptr (MulPtr idx (ConstPtr [t.Elem().Size()])))
|
||||||
(StructSelect [idx] (Load ptr mem)) -> (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
|
(StructSelect [idx] (Load ptr mem)) && b == v.Args[0].Block -> (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
|
||||||
|
|
||||||
// complex ops
|
// complex ops
|
||||||
(ComplexReal (ComplexMake real _ )) -> real
|
(ComplexReal (ComplexMake real _ )) -> real
|
||||||
|
@ -136,15 +136,18 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
|||||||
;
|
;
|
||||||
case OpArrayIndex:
|
case OpArrayIndex:
|
||||||
// match: (ArrayIndex (Load ptr mem) idx)
|
// match: (ArrayIndex (Load ptr mem) idx)
|
||||||
// cond:
|
// cond: b == v.Args[0].Block
|
||||||
// result: (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem)
|
// result: (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem)
|
||||||
{
|
{
|
||||||
if v.Args[0].Op != OpLoad {
|
if v.Args[0].Op != OpLoad {
|
||||||
goto end4894dd7b58383fee5f8a92be08437c33
|
goto end68b373270d9d605c420497edefaa71df
|
||||||
}
|
}
|
||||||
ptr := v.Args[0].Args[0]
|
ptr := v.Args[0].Args[0]
|
||||||
mem := v.Args[0].Args[1]
|
mem := v.Args[0].Args[1]
|
||||||
idx := v.Args[1]
|
idx := v.Args[1]
|
||||||
|
if !(b == v.Args[0].Block) {
|
||||||
|
goto end68b373270d9d605c420497edefaa71df
|
||||||
|
}
|
||||||
v.Op = OpLoad
|
v.Op = OpLoad
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Aux = nil
|
v.Aux = nil
|
||||||
@ -157,8 +160,8 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
|||||||
v.AddArg(mem)
|
v.AddArg(mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
goto end4894dd7b58383fee5f8a92be08437c33
|
goto end68b373270d9d605c420497edefaa71df
|
||||||
end4894dd7b58383fee5f8a92be08437c33:
|
end68b373270d9d605c420497edefaa71df:
|
||||||
;
|
;
|
||||||
case OpCom16:
|
case OpCom16:
|
||||||
// match: (Com16 (Com16 x))
|
// match: (Com16 (Com16 x))
|
||||||
@ -1510,15 +1513,18 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
|||||||
;
|
;
|
||||||
case OpStructSelect:
|
case OpStructSelect:
|
||||||
// match: (StructSelect [idx] (Load ptr mem))
|
// match: (StructSelect [idx] (Load ptr mem))
|
||||||
// cond:
|
// cond: b == v.Args[0].Block
|
||||||
// result: (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
|
// result: (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
|
||||||
{
|
{
|
||||||
idx := v.AuxInt
|
idx := v.AuxInt
|
||||||
if v.Args[0].Op != OpLoad {
|
if v.Args[0].Op != OpLoad {
|
||||||
goto end16fdb45e1dd08feb36e3cc3fb5ed8935
|
goto endd1a92da3e00c16a8f5bd3bd30deca298
|
||||||
}
|
}
|
||||||
ptr := v.Args[0].Args[0]
|
ptr := v.Args[0].Args[0]
|
||||||
mem := v.Args[0].Args[1]
|
mem := v.Args[0].Args[1]
|
||||||
|
if !(b == v.Args[0].Block) {
|
||||||
|
goto endd1a92da3e00c16a8f5bd3bd30deca298
|
||||||
|
}
|
||||||
v.Op = OpLoad
|
v.Op = OpLoad
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Aux = nil
|
v.Aux = nil
|
||||||
@ -1531,8 +1537,8 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
|
|||||||
v.AddArg(mem)
|
v.AddArg(mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
goto end16fdb45e1dd08feb36e3cc3fb5ed8935
|
goto endd1a92da3e00c16a8f5bd3bd30deca298
|
||||||
end16fdb45e1dd08feb36e3cc3fb5ed8935:
|
endd1a92da3e00c16a8f5bd3bd30deca298:
|
||||||
;
|
;
|
||||||
case OpSub16:
|
case OpSub16:
|
||||||
// match: (Sub16 x x)
|
// match: (Sub16 x x)
|
||||||
|
Loading…
Reference in New Issue
Block a user