mirror of https://github.com/golang/go.git
cmd/{asm,compile}: avoid zeroAuto clobbering flags on s390x
This CL modifies how MOV[DWHB] instructions that store a constant to memory are assembled to avoid them clobbering the condition code (flags). It also modifies zeroAuto to use MOVD instructions instead of CLEAR (which is assembled as XC). MOV[DWHB]storeconst ops also no longer clobbers flags. Note: this CL modifies the assembler so that it can no longer handle immediates outside the range of an int16 or offsets from SB, which reflects what the machine instructions support. The compiler doesn't need this capability any more and I don't think this affects any existing assembly, but it is easy to workaround if it does. Fixes #20187. Change-Id: Ie54947ff38367bd6a19962bf1a6d0296a4accffb Reviewed-on: https://go-review.googlesource.com/42179 Reviewed-by: David Chase <drchase@google.com> Run-TryBot: David Chase <drchase@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
e9702c0c85
commit
35cf3843a4
|
|
@ -47,10 +47,16 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
|
|||
MOVH $-512, R3 // a739fe00
|
||||
MOVB $-1, R4 // a749ffff
|
||||
|
||||
MOVD $-2147483648, n-8(SP) // c0b180000000e3b0f0100024
|
||||
MOVW $-131072, n-8(SP) // c0b1fffe0000e3b0f0100050
|
||||
MOVH $-512, n-8(SP) // e544f010fe00
|
||||
MOVD $32767, n-8(SP) // e548f0107fff
|
||||
MOVD $-1, -524288(R1) // e3a010008071e548a000ffff
|
||||
MOVW $32767, n-8(SP) // e54cf0107fff
|
||||
MOVW $-32768, 4096(R2) // e3a020000171e54ca0008000
|
||||
MOVH $512, n-8(SP) // e544f0100200
|
||||
MOVH $-512, 524288(R3) // c0a10008000041aa3000e544a000fe00
|
||||
MOVB $-1, n-8(SP) // 92fff010
|
||||
MOVB $255, 4096(R4) // ebff40000152
|
||||
MOVB $-128, -524288(R5) // eb8050008052
|
||||
MOVB $1, -524289(R6) // c0a1fff7ffff41aa60009201a000
|
||||
|
||||
ADD R1, R2 // b9e81022
|
||||
ADD R1, R2, R3 // b9e81032
|
||||
|
|
|
|||
|
|
@ -88,15 +88,20 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
|
|||
}
|
||||
|
||||
func zeroAuto(pp *gc.Progs, n *gc.Node) {
|
||||
// Note: this code must not clobber any registers.
|
||||
p := pp.Prog(s390x.ACLEAR)
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = n.Type.Size()
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Name = obj.NAME_AUTO
|
||||
p.To.Reg = s390x.REGSP
|
||||
p.To.Offset = n.Xoffset
|
||||
p.To.Sym = n.Sym.Linksym()
|
||||
// Note: this code must not clobber any registers or the
|
||||
// condition code.
|
||||
sym := n.Sym.Linksym()
|
||||
size := n.Type.Size()
|
||||
for i := int64(0); i < size; i += int64(gc.Widthptr) {
|
||||
p := pp.Prog(s390x.AMOVD)
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.From.Offset = 0
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Name = obj.NAME_AUTO
|
||||
p.To.Reg = s390x.REGSP
|
||||
p.To.Offset = n.Xoffset + i
|
||||
p.To.Sym = sym
|
||||
}
|
||||
}
|
||||
|
||||
func ginsnop(pp *gc.Progs) {
|
||||
|
|
|
|||
|
|
@ -718,23 +718,23 @@
|
|||
(FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is20Bit(off1+off2) -> (FMOVDstore [off1+off2] {sym} ptr val mem)
|
||||
|
||||
// Fold constants into stores.
|
||||
(MOVDstore [off] {sym} ptr (MOVDconst [c]) mem) && validValAndOff(c,off) && int64(int16(c)) == c && ptr.Op != OpSB ->
|
||||
(MOVDstore [off] {sym} ptr (MOVDconst [c]) mem) && is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB ->
|
||||
(MOVDstoreconst [makeValAndOff(c,off)] {sym} ptr mem)
|
||||
(MOVWstore [off] {sym} ptr (MOVDconst [c]) mem) && validOff(off) && int64(int16(c)) == c && ptr.Op != OpSB ->
|
||||
(MOVWstore [off] {sym} ptr (MOVDconst [c]) mem) && is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB ->
|
||||
(MOVWstoreconst [makeValAndOff(int64(int32(c)),off)] {sym} ptr mem)
|
||||
(MOVHstore [off] {sym} ptr (MOVDconst [c]) mem) && validOff(off) && ptr.Op != OpSB ->
|
||||
(MOVHstore [off] {sym} ptr (MOVDconst [c]) mem) && isU12Bit(off) && ptr.Op != OpSB ->
|
||||
(MOVHstoreconst [makeValAndOff(int64(int16(c)),off)] {sym} ptr mem)
|
||||
(MOVBstore [off] {sym} ptr (MOVDconst [c]) mem) && validOff(off) && ptr.Op != OpSB ->
|
||||
(MOVBstore [off] {sym} ptr (MOVDconst [c]) mem) && is20Bit(off) && ptr.Op != OpSB ->
|
||||
(MOVBstoreconst [makeValAndOff(int64(int8(c)),off)] {sym} ptr mem)
|
||||
|
||||
// Fold address offsets into constant stores.
|
||||
(MOVDstoreconst [sc] {s} (ADDconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) ->
|
||||
(MOVDstoreconst [sc] {s} (ADDconst [off] ptr) mem) && isU12Bit(ValAndOff(sc).Off()+off) ->
|
||||
(MOVDstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
|
||||
(MOVWstoreconst [sc] {s} (ADDconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) ->
|
||||
(MOVWstoreconst [sc] {s} (ADDconst [off] ptr) mem) && isU12Bit(ValAndOff(sc).Off()+off) ->
|
||||
(MOVWstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
|
||||
(MOVHstoreconst [sc] {s} (ADDconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) ->
|
||||
(MOVHstoreconst [sc] {s} (ADDconst [off] ptr) mem) && isU12Bit(ValAndOff(sc).Off()+off) ->
|
||||
(MOVHstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
|
||||
(MOVBstoreconst [sc] {s} (ADDconst [off] ptr) mem) && ValAndOff(sc).canAdd(off) ->
|
||||
(MOVBstoreconst [sc] {s} (ADDconst [off] ptr) mem) && is20Bit(ValAndOff(sc).Off()+off) ->
|
||||
(MOVBstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
|
||||
|
||||
// We need to fold MOVDaddr into the MOVx ops so that the live variable analysis knows
|
||||
|
|
@ -772,13 +772,14 @@
|
|||
(FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} base) val mem) && is32Bit(off1+off2) && canMergeSym(sym1, sym2) ->
|
||||
(FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||
|
||||
(MOVDstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
|
||||
// Cannot store constant to SB directly (no 'move relative long immediate' instructions).
|
||||
(MOVDstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
|
||||
(MOVDstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
|
||||
(MOVWstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
|
||||
(MOVWstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
|
||||
(MOVWstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
|
||||
(MOVHstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
|
||||
(MOVHstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
|
||||
(MOVHstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
|
||||
(MOVBstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
|
||||
(MOVBstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem) && ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off) ->
|
||||
(MOVBstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
|
||||
|
||||
// generating indexed loads and stores
|
||||
|
|
@ -1084,8 +1085,8 @@
|
|||
-> (XORWload <t> [off] {sym} x ptr mem)
|
||||
|
||||
// Combine constant stores into larger (unaligned) stores.
|
||||
// It doesn't work to global data (based on SB),
|
||||
// because STGRL doesn't support unaligned address
|
||||
// Avoid SB because constant stores to relative offsets are
|
||||
// emulated by the assembler and also can't handle unaligned offsets.
|
||||
(MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem))
|
||||
&& p.Op != OpSB
|
||||
&& x.Uses == 1
|
||||
|
|
@ -1097,7 +1098,7 @@
|
|||
&& x.Uses == 1
|
||||
&& ValAndOff(a).Off() + 2 == ValAndOff(c).Off()
|
||||
&& clobber(x)
|
||||
-> (MOVWstoreconst [makeValAndOff(ValAndOff(c).Val()&0xffff | ValAndOff(a).Val()<<16, ValAndOff(a).Off())] {s} p mem)
|
||||
-> (MOVWstore [ValAndOff(a).Off()] {s} p (MOVDconst [int64(int32(ValAndOff(c).Val()&0xffff | ValAndOff(a).Val()<<16))]) mem)
|
||||
(MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem))
|
||||
&& p.Op != OpSB
|
||||
&& x.Uses == 1
|
||||
|
|
|
|||
|
|
@ -406,10 +406,10 @@ func init() {
|
|||
// For storeconst ops, the AuxInt field encodes both
|
||||
// the value to store and an address offset of the store.
|
||||
// Cast AuxInt to a ValAndOff to extract Val and Off fields.
|
||||
{name: "MOVBstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVB", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux. arg1=mem
|
||||
{name: "MOVHstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVH", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store low 2 bytes of ...
|
||||
{name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store low 4 bytes of ...
|
||||
{name: "MOVDstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVD", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of ...
|
||||
{name: "MOVBstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVB", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low byte of ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux. arg1=mem
|
||||
{name: "MOVHstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVH", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 2 bytes of ...
|
||||
{name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store low 4 bytes of ...
|
||||
{name: "MOVDstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVD", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of ...
|
||||
|
||||
{name: "CLEAR", argLength: 2, reg: regInfo{inputs: []regMask{ptr, 0}}, asm: "CLEAR", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"},
|
||||
|
||||
|
|
|
|||
|
|
@ -20356,7 +20356,6 @@ var opcodeTable = [...]opInfo{
|
|||
name: "MOVBstoreconst",
|
||||
auxType: auxSymValAndOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVB,
|
||||
|
|
@ -20370,7 +20369,6 @@ var opcodeTable = [...]opInfo{
|
|||
name: "MOVHstoreconst",
|
||||
auxType: auxSymValAndOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVH,
|
||||
|
|
@ -20384,7 +20382,6 @@ var opcodeTable = [...]opInfo{
|
|||
name: "MOVWstoreconst",
|
||||
auxType: auxSymValAndOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVW,
|
||||
|
|
@ -20398,7 +20395,6 @@ var opcodeTable = [...]opInfo{
|
|||
name: "MOVDstoreconst",
|
||||
auxType: auxSymValAndOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVD,
|
||||
|
|
|
|||
|
|
@ -365,6 +365,11 @@ func is16Bit(n int64) bool {
|
|||
return n == int64(int16(n))
|
||||
}
|
||||
|
||||
// isU12Bit reports whether n can be represented as an unsigned 12 bit integer.
|
||||
func isU12Bit(n int64) bool {
|
||||
return 0 <= n && n < (1<<12)
|
||||
}
|
||||
|
||||
// isU16Bit reports whether n can be represented as an unsigned 16 bit integer.
|
||||
func isU16Bit(n int64) bool {
|
||||
return n == int64(uint16(n))
|
||||
|
|
|
|||
|
|
@ -9108,7 +9108,7 @@ func rewriteValueS390X_OpS390XMOVBstore_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (MOVBstore [off] {sym} ptr (MOVDconst [c]) mem)
|
||||
// cond: validOff(off) && ptr.Op != OpSB
|
||||
// cond: is20Bit(off) && ptr.Op != OpSB
|
||||
// result: (MOVBstoreconst [makeValAndOff(int64(int8(c)),off)] {sym} ptr mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
|
|
@ -9120,7 +9120,7 @@ func rewriteValueS390X_OpS390XMOVBstore_0(v *Value) bool {
|
|||
}
|
||||
c := v_1.AuxInt
|
||||
mem := v.Args[2]
|
||||
if !(validOff(off) && ptr.Op != OpSB) {
|
||||
if !(is20Bit(off) && ptr.Op != OpSB) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVBstoreconst)
|
||||
|
|
@ -9581,7 +9581,7 @@ func rewriteValueS390X_OpS390XMOVBstore_10(v *Value) bool {
|
|||
}
|
||||
func rewriteValueS390X_OpS390XMOVBstoreconst_0(v *Value) bool {
|
||||
// match: (MOVBstoreconst [sc] {s} (ADDconst [off] ptr) mem)
|
||||
// cond: ValAndOff(sc).canAdd(off)
|
||||
// cond: is20Bit(ValAndOff(sc).Off()+off)
|
||||
// result: (MOVBstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
|
||||
for {
|
||||
sc := v.AuxInt
|
||||
|
|
@ -9593,7 +9593,7 @@ func rewriteValueS390X_OpS390XMOVBstoreconst_0(v *Value) bool {
|
|||
off := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(ValAndOff(sc).canAdd(off)) {
|
||||
if !(is20Bit(ValAndOff(sc).Off() + off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVBstoreconst)
|
||||
|
|
@ -9604,7 +9604,7 @@ func rewriteValueS390X_OpS390XMOVBstoreconst_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (MOVBstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
|
||||
// cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
|
||||
// result: (MOVBstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
|
||||
for {
|
||||
sc := v.AuxInt
|
||||
|
|
@ -9617,7 +9617,7 @@ func rewriteValueS390X_OpS390XMOVBstoreconst_0(v *Value) bool {
|
|||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
|
||||
if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVBstoreconst)
|
||||
|
|
@ -12765,7 +12765,7 @@ func rewriteValueS390X_OpS390XMOVDstore_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (MOVDstore [off] {sym} ptr (MOVDconst [c]) mem)
|
||||
// cond: validValAndOff(c,off) && int64(int16(c)) == c && ptr.Op != OpSB
|
||||
// cond: is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB
|
||||
// result: (MOVDstoreconst [makeValAndOff(c,off)] {sym} ptr mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
|
|
@ -12777,7 +12777,7 @@ func rewriteValueS390X_OpS390XMOVDstore_0(v *Value) bool {
|
|||
}
|
||||
c := v_1.AuxInt
|
||||
mem := v.Args[2]
|
||||
if !(validValAndOff(c, off) && int64(int16(c)) == c && ptr.Op != OpSB) {
|
||||
if !(is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVDstoreconst)
|
||||
|
|
@ -12982,7 +12982,7 @@ func rewriteValueS390X_OpS390XMOVDstore_0(v *Value) bool {
|
|||
}
|
||||
func rewriteValueS390X_OpS390XMOVDstoreconst_0(v *Value) bool {
|
||||
// match: (MOVDstoreconst [sc] {s} (ADDconst [off] ptr) mem)
|
||||
// cond: ValAndOff(sc).canAdd(off)
|
||||
// cond: isU12Bit(ValAndOff(sc).Off()+off)
|
||||
// result: (MOVDstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
|
||||
for {
|
||||
sc := v.AuxInt
|
||||
|
|
@ -12994,7 +12994,7 @@ func rewriteValueS390X_OpS390XMOVDstoreconst_0(v *Value) bool {
|
|||
off := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(ValAndOff(sc).canAdd(off)) {
|
||||
if !(isU12Bit(ValAndOff(sc).Off() + off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVDstoreconst)
|
||||
|
|
@ -13005,7 +13005,7 @@ func rewriteValueS390X_OpS390XMOVDstoreconst_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (MOVDstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
|
||||
// cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
|
||||
// result: (MOVDstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
|
||||
for {
|
||||
sc := v.AuxInt
|
||||
|
|
@ -13018,7 +13018,7 @@ func rewriteValueS390X_OpS390XMOVDstoreconst_0(v *Value) bool {
|
|||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
|
||||
if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVDstoreconst)
|
||||
|
|
@ -14725,7 +14725,7 @@ func rewriteValueS390X_OpS390XMOVHstore_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (MOVHstore [off] {sym} ptr (MOVDconst [c]) mem)
|
||||
// cond: validOff(off) && ptr.Op != OpSB
|
||||
// cond: isU12Bit(off) && ptr.Op != OpSB
|
||||
// result: (MOVHstoreconst [makeValAndOff(int64(int16(c)),off)] {sym} ptr mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
|
|
@ -14737,7 +14737,7 @@ func rewriteValueS390X_OpS390XMOVHstore_0(v *Value) bool {
|
|||
}
|
||||
c := v_1.AuxInt
|
||||
mem := v.Args[2]
|
||||
if !(validOff(off) && ptr.Op != OpSB) {
|
||||
if !(isU12Bit(off) && ptr.Op != OpSB) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVHstoreconst)
|
||||
|
|
@ -15015,8 +15015,12 @@ func rewriteValueS390X_OpS390XMOVHstore_10(v *Value) bool {
|
|||
return false
|
||||
}
|
||||
func rewriteValueS390X_OpS390XMOVHstoreconst_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
types := &b.Func.Config.Types
|
||||
_ = types
|
||||
// match: (MOVHstoreconst [sc] {s} (ADDconst [off] ptr) mem)
|
||||
// cond: ValAndOff(sc).canAdd(off)
|
||||
// cond: isU12Bit(ValAndOff(sc).Off()+off)
|
||||
// result: (MOVHstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
|
||||
for {
|
||||
sc := v.AuxInt
|
||||
|
|
@ -15028,7 +15032,7 @@ func rewriteValueS390X_OpS390XMOVHstoreconst_0(v *Value) bool {
|
|||
off := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(ValAndOff(sc).canAdd(off)) {
|
||||
if !(isU12Bit(ValAndOff(sc).Off() + off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVHstoreconst)
|
||||
|
|
@ -15039,7 +15043,7 @@ func rewriteValueS390X_OpS390XMOVHstoreconst_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (MOVHstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
|
||||
// cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
|
||||
// result: (MOVHstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
|
||||
for {
|
||||
sc := v.AuxInt
|
||||
|
|
@ -15052,7 +15056,7 @@ func rewriteValueS390X_OpS390XMOVHstoreconst_0(v *Value) bool {
|
|||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
|
||||
if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVHstoreconst)
|
||||
|
|
@ -15064,7 +15068,7 @@ func rewriteValueS390X_OpS390XMOVHstoreconst_0(v *Value) bool {
|
|||
}
|
||||
// match: (MOVHstoreconst [c] {s} p x:(MOVHstoreconst [a] {s} p mem))
|
||||
// cond: p.Op != OpSB && x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x)
|
||||
// result: (MOVWstoreconst [makeValAndOff(ValAndOff(c).Val()&0xffff | ValAndOff(a).Val()<<16, ValAndOff(a).Off())] {s} p mem)
|
||||
// result: (MOVWstore [ValAndOff(a).Off()] {s} p (MOVDconst [int64(int32(ValAndOff(c).Val()&0xffff | ValAndOff(a).Val()<<16))]) mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
s := v.Aux
|
||||
|
|
@ -15084,10 +15088,13 @@ func rewriteValueS390X_OpS390XMOVHstoreconst_0(v *Value) bool {
|
|||
if !(p.Op != OpSB && x.Uses == 1 && ValAndOff(a).Off()+2 == ValAndOff(c).Off() && clobber(x)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVWstoreconst)
|
||||
v.AuxInt = makeValAndOff(ValAndOff(c).Val()&0xffff|ValAndOff(a).Val()<<16, ValAndOff(a).Off())
|
||||
v.reset(OpS390XMOVWstore)
|
||||
v.AuxInt = ValAndOff(a).Off()
|
||||
v.Aux = s
|
||||
v.AddArg(p)
|
||||
v0 := b.NewValue0(v.Pos, OpS390XMOVDconst, types.UInt64)
|
||||
v0.AuxInt = int64(int32(ValAndOff(c).Val()&0xffff | ValAndOff(a).Val()<<16))
|
||||
v.AddArg(v0)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
|
|
@ -17176,7 +17183,7 @@ func rewriteValueS390X_OpS390XMOVWstore_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (MOVWstore [off] {sym} ptr (MOVDconst [c]) mem)
|
||||
// cond: validOff(off) && int64(int16(c)) == c && ptr.Op != OpSB
|
||||
// cond: is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB
|
||||
// result: (MOVWstoreconst [makeValAndOff(int64(int32(c)),off)] {sym} ptr mem)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
|
|
@ -17188,7 +17195,7 @@ func rewriteValueS390X_OpS390XMOVWstore_0(v *Value) bool {
|
|||
}
|
||||
c := v_1.AuxInt
|
||||
mem := v.Args[2]
|
||||
if !(validOff(off) && int64(int16(c)) == c && ptr.Op != OpSB) {
|
||||
if !(is16Bit(c) && isU12Bit(off) && ptr.Op != OpSB) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVWstoreconst)
|
||||
|
|
@ -17491,7 +17498,7 @@ func rewriteValueS390X_OpS390XMOVWstoreconst_0(v *Value) bool {
|
|||
types := &b.Func.Config.Types
|
||||
_ = types
|
||||
// match: (MOVWstoreconst [sc] {s} (ADDconst [off] ptr) mem)
|
||||
// cond: ValAndOff(sc).canAdd(off)
|
||||
// cond: isU12Bit(ValAndOff(sc).Off()+off)
|
||||
// result: (MOVWstoreconst [ValAndOff(sc).add(off)] {s} ptr mem)
|
||||
for {
|
||||
sc := v.AuxInt
|
||||
|
|
@ -17503,7 +17510,7 @@ func rewriteValueS390X_OpS390XMOVWstoreconst_0(v *Value) bool {
|
|||
off := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(ValAndOff(sc).canAdd(off)) {
|
||||
if !(isU12Bit(ValAndOff(sc).Off() + off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVWstoreconst)
|
||||
|
|
@ -17514,7 +17521,7 @@ func rewriteValueS390X_OpS390XMOVWstoreconst_0(v *Value) bool {
|
|||
return true
|
||||
}
|
||||
// match: (MOVWstoreconst [sc] {sym1} (MOVDaddr [off] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
|
||||
// cond: ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)
|
||||
// result: (MOVWstoreconst [ValAndOff(sc).add(off)] {mergeSym(sym1, sym2)} ptr mem)
|
||||
for {
|
||||
sc := v.AuxInt
|
||||
|
|
@ -17527,7 +17534,7 @@ func rewriteValueS390X_OpS390XMOVWstoreconst_0(v *Value) bool {
|
|||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
|
||||
if !(ptr.Op != OpSB && canMergeSym(sym1, sym2) && ValAndOff(sc).canAdd(off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVWstoreconst)
|
||||
|
|
|
|||
|
|
@ -89,21 +89,26 @@ var optab = []Optab{
|
|||
Optab{AMOVBZ, C_DCON, C_NONE, C_NONE, C_REG, 3, 0},
|
||||
|
||||
// store constant
|
||||
Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
|
||||
Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
|
||||
Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
|
||||
Optab{AMOVBZ, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
|
||||
Optab{AMOVB, C_LCON, C_NONE, C_NONE, C_ADDR, 73, 0},
|
||||
Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVB, C_LCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVBZ, C_LCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVB, C_LCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVBZ, C_LCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVD, C_SCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVD, C_ADDCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVW, C_SCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVW, C_ADDCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVWZ, C_SCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVB, C_SCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVB, C_ADDCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVBZ, C_SCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVBZ, C_ADDCON, C_NONE, C_NONE, C_LAUTO, 72, REGSP},
|
||||
Optab{AMOVD, C_SCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVD, C_ADDCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVW, C_SCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVW, C_ADDCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVWZ, C_SCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVB, C_SCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVB, C_ADDCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVBZ, C_SCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
Optab{AMOVBZ, C_ADDCON, C_NONE, C_NONE, C_LOREG, 72, 0},
|
||||
|
||||
// store
|
||||
Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 35, REGSP},
|
||||
|
|
@ -3303,84 +3308,49 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
|||
v := c.regoff(&p.From)
|
||||
d := c.regoff(&p.To)
|
||||
r := p.To.Reg
|
||||
x := p.To.Index
|
||||
if p.To.Index != 0 {
|
||||
c.ctxt.Diag("cannot use index register")
|
||||
}
|
||||
if r == 0 {
|
||||
r = o.param
|
||||
}
|
||||
if int32(int16(v)) == v && x == 0 {
|
||||
if d < 0 || d >= DISP12 {
|
||||
if r == REGTMP || r == REGTMP2 {
|
||||
zRIL(_a, op_AGFI, uint32(r), uint32(d), asm)
|
||||
var opcode uint32
|
||||
switch p.As {
|
||||
case AMOVD:
|
||||
opcode = op_MVGHI
|
||||
case AMOVW, AMOVWZ:
|
||||
opcode = op_MVHI
|
||||
case AMOVH, AMOVHZ:
|
||||
opcode = op_MVHHI
|
||||
case AMOVB, AMOVBZ:
|
||||
opcode = op_MVI
|
||||
}
|
||||
if d < 0 || d >= DISP12 {
|
||||
if r == REGTMP {
|
||||
c.ctxt.Diag("displacement must be in range [0, 4096) to use %v", r)
|
||||
}
|
||||
if d >= -DISP20/2 && d < DISP20/2 {
|
||||
if opcode == op_MVI {
|
||||
opcode = op_MVIY
|
||||
} else {
|
||||
zRIL(_a, op_LGFI, REGTMP, uint32(d), asm)
|
||||
zRRE(op_AGR, REGTMP, uint32(r), asm)
|
||||
zRXY(op_LAY, uint32(REGTMP), 0, uint32(r), uint32(d), asm)
|
||||
r = REGTMP
|
||||
d = 0
|
||||
}
|
||||
} else {
|
||||
zRIL(_a, op_LGFI, REGTMP, uint32(d), asm)
|
||||
zRX(op_LA, REGTMP, REGTMP, uint32(r), 0, asm)
|
||||
r = REGTMP
|
||||
d = 0
|
||||
}
|
||||
var opcode uint32
|
||||
switch p.As {
|
||||
case AMOVD:
|
||||
opcode = op_MVGHI
|
||||
case AMOVW, AMOVWZ:
|
||||
opcode = op_MVHI
|
||||
case AMOVH, AMOVHZ:
|
||||
opcode = op_MVHHI
|
||||
case AMOVB, AMOVBZ:
|
||||
opcode = op_MVI
|
||||
}
|
||||
if opcode == op_MVI {
|
||||
zSI(opcode, uint32(v), uint32(r), uint32(d), asm)
|
||||
} else {
|
||||
zSIL(opcode, uint32(r), uint32(d), uint32(v), asm)
|
||||
}
|
||||
} else {
|
||||
zRIL(_a, op_LGFI, REGTMP2, uint32(v), asm)
|
||||
if d < -DISP20/2 || d >= DISP20/2 {
|
||||
if r == REGTMP {
|
||||
zRIL(_a, op_AGFI, REGTMP, uint32(d), asm)
|
||||
} else {
|
||||
zRIL(_a, op_LGFI, REGTMP, uint32(d), asm)
|
||||
if x != 0 {
|
||||
zRRE(op_AGR, REGTMP, uint32(x), asm)
|
||||
}
|
||||
x = REGTMP
|
||||
}
|
||||
d = 0
|
||||
}
|
||||
zRXY(c.zopstore(p.As), REGTMP2, uint32(x), uint32(r), uint32(d), asm)
|
||||
}
|
||||
|
||||
case 73: // mov $constant addr (including relocation)
|
||||
v := c.regoff(&p.From)
|
||||
d := c.regoff(&p.To)
|
||||
a := uint32(0)
|
||||
if d&1 != 0 {
|
||||
d -= 1
|
||||
a = 1
|
||||
}
|
||||
zRIL(_b, op_LARL, REGTMP, uint32(d), asm)
|
||||
c.addrilreloc(p.To.Sym, int64(d))
|
||||
if int32(int16(v)) == v {
|
||||
var opcode uint32
|
||||
switch p.As {
|
||||
case AMOVD:
|
||||
opcode = op_MVGHI
|
||||
case AMOVW, AMOVWZ:
|
||||
opcode = op_MVHI
|
||||
case AMOVH, AMOVHZ:
|
||||
opcode = op_MVHHI
|
||||
case AMOVB, AMOVBZ:
|
||||
opcode = op_MVI
|
||||
}
|
||||
if opcode == op_MVI {
|
||||
zSI(opcode, uint32(v), REGTMP, a, asm)
|
||||
} else {
|
||||
zSIL(opcode, REGTMP, a, uint32(v), asm)
|
||||
}
|
||||
} else {
|
||||
zRIL(_a, op_LGFI, REGTMP2, uint32(v), asm)
|
||||
zRXY(c.zopstore(p.As), REGTMP2, 0, REGTMP, a, asm)
|
||||
switch opcode {
|
||||
case op_MVI:
|
||||
zSI(opcode, uint32(v), uint32(r), uint32(d), asm)
|
||||
case op_MVIY:
|
||||
zSIY(opcode, uint32(v), uint32(r), uint32(d), asm)
|
||||
default:
|
||||
zSIL(opcode, uint32(r), uint32(d), uint32(v), asm)
|
||||
}
|
||||
|
||||
case 74: // mov reg addr (including relocation)
|
||||
|
|
|
|||
Loading…
Reference in New Issue