1
0
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:
Keith Randall 2015-10-09 09:33:29 -07:00
parent 32ffbf7e0f
commit 9703564c9a
3 changed files with 36 additions and 29 deletions

View File

@ -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:

View File

@ -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

View File

@ -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)