aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/s390x
diff options
context:
space:
mode:
authorMichael Munday <mike.munday@ibm.com>2019-08-15 21:53:37 +0100
committerMichael Munday <mike.munday@ibm.com>2019-10-09 15:04:59 +0000
commit38c4a7370670e6b73cbae192c7d3079c90203832 (patch)
tree0ed95e4710b6cb9d1f0d40a28b62b8d81eb4dd20 /src/cmd/compile/internal/s390x
parentff86ce13b69f427248203493d669a730988f882c (diff)
downloadgo-38c4a7370670e6b73cbae192c7d3079c90203832.tar.gz
go-38c4a7370670e6b73cbae192c7d3079c90203832.zip
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 <mike.munday@ibm.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src/cmd/compile/internal/s390x')
-rw-r--r--src/cmd/compile/internal/s390x/ggen.go12
1 files changed, 4 insertions, 8 deletions
diff --git a/src/cmd/compile/internal/s390x/ggen.go b/src/cmd/compile/internal/s390x/ggen.go
index ae9965c378..16af190b2f 100644
--- a/src/cmd/compile/internal/s390x/ggen.go
+++ b/src/cmd/compile/internal/s390x/ggen.go
@@ -38,18 +38,14 @@ func zerorange(pp *gc.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
// Generate a loop of large clears.
if cnt > clearLoopCutoff {
- n := cnt - (cnt % 256)
- end := int16(s390x.REGRT2)
- p = pp.Appendpp(p, s390x.AADD, obj.TYPE_CONST, 0, off+n, obj.TYPE_REG, end, 0)
- p.Reg = reg
+ ireg := int16(s390x.REGRT2) // register holds number of remaining loop iterations
+ p = pp.Appendpp(p, s390x.AMOVD, obj.TYPE_CONST, 0, cnt/256, obj.TYPE_REG, ireg, 0)
p = pp.Appendpp(p, s390x.ACLEAR, obj.TYPE_CONST, 0, 256, obj.TYPE_MEM, reg, off)
pl := p
p = pp.Appendpp(p, s390x.AADD, obj.TYPE_CONST, 0, 256, obj.TYPE_REG, reg, 0)
- p = pp.Appendpp(p, s390x.ACMP, obj.TYPE_REG, reg, 0, obj.TYPE_REG, end, 0)
- p = pp.Appendpp(p, s390x.ABNE, obj.TYPE_NONE, 0, 0, obj.TYPE_BRANCH, 0, 0)
+ p = pp.Appendpp(p, s390x.ABRCTG, obj.TYPE_REG, ireg, 0, obj.TYPE_BRANCH, 0, 0)
gc.Patch(p, pl)
-
- cnt -= n
+ cnt = cnt % 256
}
// Generate remaining clear instructions without a loop.