Skip to content

Commit 38c4a73

Browse files
committed
cmd/asm: add s390x branch-on-count instructions
The branch-on-count instructions on s390x decrement the input register and then compare its value to 0. If not equal the branch is taken. These instructions are useful for implementing loops with a set number of iterations (which might be in a register). For example, this for loop: for i := 0; i < n; i++ { ... // i is not used or modified in the loop } Could be implemented using this assembly: MOVD Rn, Ri loop: ... BRCTG Ri, loop Note that i will count down from n in the assembly whereas in the original for loop it counted up to n which is why we can't use i in the loop. These instructions will only be used in hand-written codegen and assembly for now since SSA blocks cannot currently modify values. We could look into this in the future though. Change-Id: Iaab93b8aa2699513b825439b8ea20d8fe2ea1ee6 Reviewed-on: https://go-review.googlesource.com/c/go/+/199977 Run-TryBot: Michael Munday <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent ff86ce1 commit 38c4a73

File tree

6 files changed

+34
-8
lines changed

6 files changed

+34
-8
lines changed

src/cmd/asm/internal/arch/s390x.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ func jumpS390x(word string) bool {
3030
"BR",
3131
"BVC",
3232
"BVS",
33+
"BRCT",
34+
"BRCTG",
3335
"CMPBEQ",
3436
"CMPBGE",
3537
"CMPBGT",

src/cmd/asm/internal/asm/testdata/s390x.s

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,9 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
266266
BLTU 0(PC) // a7540000
267267
BLEU 0(PC) // a7d40000
268268

269+
BRCT R1, 0(PC) // a7160000
270+
BRCTG R2, 0(PC) // a7270000
271+
269272
CMPBNE R1, R2, 0(PC) // ec1200007064
270273
CMPBEQ R3, R4, 0(PC) // ec3400008064
271274
CMPBLT R5, R6, 0(PC) // ec5600004064

src/cmd/compile/internal/s390x/ggen.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,14 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
3838

3939
// Generate a loop of large clears.
4040
if cnt > clearLoopCutoff {
41-
n := cnt - (cnt % 256)
42-
end := int16(s390x.REGRT2)
43-
p = pp.Appendpp(p, s390x.AADD, obj.TYPE_CONST, 0, off+n, obj.TYPE_REG, end, 0)
44-
p.Reg = reg
41+
ireg := int16(s390x.REGRT2) // register holds number of remaining loop iterations
42+
p = pp.Appendpp(p, s390x.AMOVD, obj.TYPE_CONST, 0, cnt/256, obj.TYPE_REG, ireg, 0)
4543
p = pp.Appendpp(p, s390x.ACLEAR, obj.TYPE_CONST, 0, 256, obj.TYPE_MEM, reg, off)
4644
pl := p
4745
p = pp.Appendpp(p, s390x.AADD, obj.TYPE_CONST, 0, 256, obj.TYPE_REG, reg, 0)
48-
p = pp.Appendpp(p, s390x.ACMP, obj.TYPE_REG, reg, 0, obj.TYPE_REG, end, 0)
49-
p = pp.Appendpp(p, s390x.ABNE, obj.TYPE_NONE, 0, 0, obj.TYPE_BRANCH, 0, 0)
46+
p = pp.Appendpp(p, s390x.ABRCTG, obj.TYPE_REG, ireg, 0, obj.TYPE_BRANCH, 0, 0)
5047
gc.Patch(p, pl)
51-
52-
cnt -= n
48+
cnt = cnt % 256
5349
}
5450

5551
// Generate remaining clear instructions without a loop.

src/cmd/internal/obj/s390x/a.out.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,10 @@ const (
409409
ABVS
410410
ASYSCALL
411411

412+
// branch on count
413+
ABRCT
414+
ABRCTG
415+
412416
// compare and branch
413417
ACRJ
414418
ACGRJ

src/cmd/internal/obj/s390x/anames.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/internal/obj/s390x/asmz.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ var optab = []Optab{
256256
{i: 90, as: ACLGIJ, a1: C_SCON, a2: C_REG, a3: C_ADDCON, a6: C_SBRA},
257257
{i: 90, as: ACMPUBEQ, a1: C_REG, a3: C_ANDCON, a6: C_SBRA},
258258

259+
// branch on count
260+
{i: 41, as: ABRCT, a1: C_REG, a6: C_SBRA},
261+
{i: 41, as: ABRCTG, a1: C_REG, a6: C_SBRA},
262+
259263
// move on condition
260264
{i: 17, as: AMOVDEQ, a1: C_REG, a6: C_REG},
261265

@@ -3394,6 +3398,21 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
33943398
*asm = append(*asm, uint8(wd))
33953399
}
33963400

3401+
case 41: // branch on count
3402+
r1 := p.From.Reg
3403+
ri2 := (p.Pcond.Pc - p.Pc) >> 1
3404+
if int64(int16(ri2)) != ri2 {
3405+
c.ctxt.Diag("branch target too far away")
3406+
}
3407+
var opcode uint32
3408+
switch p.As {
3409+
case ABRCT:
3410+
opcode = op_BRCT
3411+
case ABRCTG:
3412+
opcode = op_BRCTG
3413+
}
3414+
zRI(opcode, uint32(r1), uint32(ri2), asm)
3415+
33973416
case 47: // negate [reg] reg
33983417
r := p.From.Reg
33993418
if r == 0 {

0 commit comments

Comments
 (0)