aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj/ppc64
diff options
context:
space:
mode:
authorisharipo <iskander.sharipov@intel.com>2017-09-13 14:32:08 +0300
committerMatthew Dempsky <mdempsky@google.com>2017-09-15 21:05:03 +0000
commit8c67f210a181f4d3e003e46e544ae03ce231ca42 (patch)
tree537c869a16a02ed96ed005b345aeeec040080686 /src/cmd/internal/obj/ppc64
parente1cf2be7a82a2421c69c48cbdf596841f29bff77 (diff)
downloadgo-8c67f210a181f4d3e003e46e544ae03ce231ca42.tar.xz
cmd/internal/obj: change Prog.From3 to RestArgs ([]Addr)
This change makes it easier to express instructions with arbitrary number of operands. Rationale: previous approach with operand "hiding" does not scale well, AVX and especially AVX512 have many instructions with 3+ operands. x86 asm backend is updated to handle up to 6 explicit operands. It also fixes issue with 4-th immediate operand type checks. All `ytab` tables are updated accordingly. Changes to non-x86 backends only include these patterns: `p.From3 = X` => `p.SetFrom3(X)` `p.From3.X = Y` => `p.GetFrom3().X = Y` Over time, other backends can adapt Prog.RestArgs and reduce the amount of workarounds. -- Performance -- x/benchmark/build: $ benchstat upstream.bench patched.bench name old time/op new time/op delta Build-48 21.7s ± 2% 21.8s ± 2% ~ (p=0.218 n=10+10) name old binary-size new binary-size delta Build-48 10.3M ± 0% 10.3M ± 0% ~ (all equal) name old build-time/op new build-time/op delta Build-48 21.7s ± 2% 21.8s ± 2% ~ (p=0.218 n=10+10) name old build-peak-RSS-bytes new build-peak-RSS-bytes delta Build-48 145MB ± 5% 148MB ± 5% ~ (p=0.218 n=10+10) name old build-user+sys-time/op new build-user+sys-time/op delta Build-48 21.0s ± 2% 21.2s ± 2% ~ (p=0.075 n=10+10) Microbenchmark shows a slight slowdown. name old time/op new time/op delta AMD64asm-4 49.5ms ± 1% 49.9ms ± 1% +0.67% (p=0.001 n=23+15) func BenchmarkAMD64asm(b *testing.B) { for i := 0; i < b.N; i++ { TestAMD64EndToEnd(nil) TestAMD64Encoder(nil) } } Change-Id: I4f1d37b5c2c966da3f2127705ccac9bff0038183 Reviewed-on: https://go-review.googlesource.com/63490 Run-TryBot: Iskander Sharipov <iskander.sharipov@intel.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/internal/obj/ppc64')
-rw-r--r--src/cmd/internal/obj/ppc64/asm9.go50
-rw-r--r--src/cmd/internal/obj/ppc64/obj9.go2
2 files changed, 26 insertions, 26 deletions
diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go
index dd6429fd0b..2f7e3237b4 100644
--- a/src/cmd/internal/obj/ppc64/asm9.go
+++ b/src/cmd/internal/obj/ppc64/asm9.go
@@ -900,11 +900,11 @@ func (c *ctxt9) oplook(p *obj.Prog) *Optab {
a1--
a3 := C_NONE + 1
- if p.From3 != nil {
- a3 = int(p.From3.Class)
+ if p.GetFrom3() != nil {
+ a3 = int(p.GetFrom3().Class)
if a3 == 0 {
- a3 = c.aclass(p.From3) + 1
- p.From3.Class = int8(a3)
+ a3 = c.aclass(p.GetFrom3()) + 1
+ p.GetFrom3().Class = int8(a3)
}
}
@@ -2461,7 +2461,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
if r == 0 {
r = int(p.To.Reg)
}
- d := c.vregoff(p.From3)
+ d := c.vregoff(p.GetFrom3())
var a int
switch p.As {
@@ -2714,7 +2714,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(v))
case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */
- v := c.regoff(p.From3)
+ v := c.regoff(p.GetFrom3())
r := int(p.From.Reg)
o1 = AOP_IRR(c.opirr(p.As), uint32(p.To.Reg), uint32(r), uint32(v))
@@ -2723,7 +2723,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
if p.To.Reg == REGTMP || p.From.Reg == REGTMP {
c.ctxt.Diag("can't synthesize large constant\n%v", p)
}
- v := c.regoff(p.From3)
+ v := c.regoff(p.GetFrom3())
o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(v)>>16)
o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, uint32(v))
o3 = AOP_RRR(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), REGTMP)
@@ -2736,7 +2736,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
case 29: /* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */
v := c.regoff(&p.From)
- d := c.vregoff(p.From3)
+ d := c.vregoff(p.GetFrom3())
var mask [2]uint8
c.maskgen64(p, mask[:], uint64(d))
var a int
@@ -2776,7 +2776,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
case 30: /* rldimi $sh,s,$mask,a */
v := c.regoff(&p.From)
- d := c.vregoff(p.From3)
+ d := c.vregoff(p.GetFrom3())
// Original opcodes had mask operands which had to be converted to a shift count as expected by
// the ppc64 asm.
@@ -2847,7 +2847,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 = AOP_RRR(c.oprrr(p.As), uint32(p.To.Reg), 0, uint32(r))
case 34: /* FMADDx fra,frb,frc,frt (t=a*c±b) */
- o1 = AOP_RRR(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)) | (uint32(p.From3.Reg)&31)<<6
+ o1 = AOP_RRR(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)) | (uint32(p.GetFrom3().Reg)&31)<<6
case 35: /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
v := c.regoff(&p.To)
@@ -2889,10 +2889,10 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 = uint32(c.regoff(&p.From))
case 41: /* stswi */
- o1 = AOP_RRR(c.opirr(p.As), uint32(p.From.Reg), uint32(p.To.Reg), 0) | (uint32(c.regoff(p.From3))&0x7F)<<11
+ o1 = AOP_RRR(c.opirr(p.As), uint32(p.From.Reg), uint32(p.To.Reg), 0) | (uint32(c.regoff(p.GetFrom3()))&0x7F)<<11
case 42: /* lswi */
- o1 = AOP_RRR(c.opirr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), 0) | (uint32(c.regoff(p.From3))&0x7F)<<11
+ o1 = AOP_RRR(c.opirr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), 0) | (uint32(c.regoff(p.GetFrom3()))&0x7F)<<11
case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */
o1 = AOP_RRR(c.oprrr(p.As), 0, uint32(p.From.Index), uint32(p.From.Reg))
@@ -3062,13 +3062,13 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
v := c.regoff(&p.From)
var mask [2]uint8
- c.maskgen(p, mask[:], uint32(c.regoff(p.From3)))
+ c.maskgen(p, mask[:], uint32(c.regoff(p.GetFrom3())))
o1 = AOP_RRR(c.opirr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(v))
o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
case 63: /* rlwmi b,s,$mask,a */
var mask [2]uint8
- c.maskgen(p, mask[:], uint32(c.regoff(p.From3)))
+ c.maskgen(p, mask[:], uint32(c.regoff(p.GetFrom3())))
o1 = AOP_RRR(c.opirr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg))
o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1
@@ -3076,7 +3076,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
case 64: /* mtfsf fr[, $m] {,fpcsr} */
var v int32
if p.From3Type() != obj.TYPE_NONE {
- v = c.regoff(p.From3) & 255
+ v = c.regoff(p.GetFrom3()) & 255
} else {
v = 255
}
@@ -3131,7 +3131,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
if p.To.Reg != 0 {
c.ctxt.Diag("can't use both mask and CR(n)\n%v", p)
}
- v = c.regoff(p.From3) & 0xff
+ v = c.regoff(p.GetFrom3()) & 0xff
} else {
if p.To.Reg == 0 {
v = 0xff /* CR */
@@ -3270,7 +3270,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
/* imm imm reg reg */
/* operand order: SIX, VRA, ST, VRT */
six := int(c.regoff(&p.From))
- st := int(c.regoff(p.From3))
+ st := int(c.regoff(p.GetFrom3()))
o1 = AOP_IIRR(c.opiirr(p.As), uint32(p.To.Reg), uint32(p.Reg), uint32(st), uint32(six))
} else if p.From3Type() == obj.TYPE_NONE && p.Reg != 0 {
/* imm reg reg */
@@ -3288,19 +3288,19 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
if p.From.Type == obj.TYPE_REG {
/* reg reg reg reg */
/* 4-register operand order: VRA, VRB, VRC, VRT */
- o1 = AOP_RRRR(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), uint32(p.From3.Reg))
+ o1 = AOP_RRRR(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), uint32(p.GetFrom3().Reg))
} else if p.From.Type == obj.TYPE_CONST {
/* imm reg reg reg */
/* operand order: SHB, VRA, VRB, VRT */
shb := int(c.regoff(&p.From))
- o1 = AOP_IRRR(c.opirrr(p.As), uint32(p.To.Reg), uint32(p.Reg), uint32(p.From3.Reg), uint32(shb))
+ o1 = AOP_IRRR(c.opirrr(p.As), uint32(p.To.Reg), uint32(p.Reg), uint32(p.GetFrom3().Reg), uint32(shb))
}
case 84: // ISEL BC,RA,RB,RT -> isel rt,ra,rb,bc
bc := c.vregoff(&p.From)
// rt = To.Reg, ra = p.Reg, rb = p.From3.Reg
- o1 = AOP_ISEL(OP_ISEL, uint32(p.To.Reg), uint32(p.Reg), uint32(p.From3.Reg), uint32(bc))
+ o1 = AOP_ISEL(OP_ISEL, uint32(p.To.Reg), uint32(p.Reg), uint32(p.GetFrom3().Reg), uint32(bc))
case 85: /* vector instructions, VX-form */
/* reg none reg */
@@ -3348,7 +3348,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
case 89: /* VSX instructions, XX2-form */
/* reg none reg OR reg imm reg */
/* 2-register operand order: XB, XT or XB, UIM, XT*/
- uim := int(c.regoff(p.From3))
+ uim := int(c.regoff(p.GetFrom3()))
o1 = AOP_XX2(c.oprrr(p.As), uint32(p.To.Reg), uint32(uim), uint32(p.From.Reg))
case 90: /* VSX instructions, XX3-form */
@@ -3359,14 +3359,14 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
} else if p.From3Type() == obj.TYPE_CONST {
/* reg reg reg imm */
/* operand order: XA, XB, DM, XT */
- dm := int(c.regoff(p.From3))
+ dm := int(c.regoff(p.GetFrom3()))
o1 = AOP_XX3I(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), uint32(dm))
}
case 91: /* VSX instructions, XX4-form */
/* reg reg reg reg */
/* 3-register operand order: XA, XB, XC, XT */
- o1 = AOP_XX4(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), uint32(p.From3.Reg))
+ o1 = AOP_XX4(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), uint32(p.GetFrom3().Reg))
case 92: /* X-form instructions, 3-operands */
if p.To.Type == obj.TYPE_CONST {
@@ -3384,7 +3384,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
} else if p.From3Type() == obj.TYPE_CONST {
/* reg reg imm */
/* operand order: RB, L, RA */
- l := int(c.regoff(p.From3))
+ l := int(c.regoff(p.GetFrom3()))
o1 = AOP_RRR(c.opirr(p.As), uint32(l), uint32(p.To.Reg), uint32(p.From.Reg))
} else if p.To.Type == obj.TYPE_REG {
cr := int32(p.To.Reg)
@@ -3425,7 +3425,7 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
case 94: /* Z23-form instructions, 4-operands */
/* reg reg reg imm */
/* operand order: RA, RB, CY, RT */
- cy := int(c.regoff(p.From3))
+ cy := int(c.regoff(p.GetFrom3()))
o1 = AOP_Z23I(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), uint32(cy))
}
diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go
index b1509e3813..c50cd3b06c 100644
--- a/src/cmd/internal/obj/ppc64/obj9.go
+++ b/src/cmd/internal/obj/ppc64/obj9.go
@@ -176,7 +176,7 @@ func (c *ctxt9) rewriteToUseGot(p *obj.Prog) {
p.From.Offset = 0
}
}
- if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
+ if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
c.ctxt.Diag("don't know how to handle %v with -dynlink", p)
}
var source *obj.Addr