diff --git a/src/cmd/asm/internal/asm/testdata/s390x.s b/src/cmd/asm/internal/asm/testdata/s390x.s index d8688e7ba6..6cc129ccc5 100644 --- a/src/cmd/asm/internal/asm/testdata/s390x.s +++ b/src/cmd/asm/internal/asm/testdata/s390x.s @@ -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 diff --git a/src/cmd/compile/internal/s390x/ggen.go b/src/cmd/compile/internal/s390x/ggen.go index f1ab5b0ddc..636ab16dd4 100644 --- a/src/cmd/compile/internal/s390x/ggen.go +++ b/src/cmd/compile/internal/s390x/ggen.go @@ -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) { diff --git a/src/cmd/compile/internal/ssa/gen/S390X.rules b/src/cmd/compile/internal/ssa/gen/S390X.rules index eef6853d9f..f54169de58 100644 --- a/src/cmd/compile/internal/ssa/gen/S390X.rules +++ b/src/cmd/compile/internal/ssa/gen/S390X.rules @@ -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 [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 diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go index a1a5aa2dc4..c3edb9385d 100644 --- a/src/cmd/compile/internal/ssa/gen/S390XOps.go +++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go @@ -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"}, diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 47c9dba37d..32d928388f 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -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, diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index ccd723388d..db1540d16c 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -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)) diff --git a/src/cmd/compile/internal/ssa/rewriteS390X.go b/src/cmd/compile/internal/ssa/rewriteS390X.go index d8e8bd70f1..ee3f07e904 100644 --- a/src/cmd/compile/internal/ssa/rewriteS390X.go +++ b/src/cmd/compile/internal/ssa/rewriteS390X.go @@ -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) diff --git a/src/cmd/internal/obj/s390x/asmz.go b/src/cmd/internal/obj/s390x/asmz.go index 624d3b74ff..3bba7b2a5c 100644 --- a/src/cmd/internal/obj/s390x/asmz.go +++ b/src/cmd/internal/obj/s390x/asmz.go @@ -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)