diff options
| author | isharipo <iskander.sharipov@intel.com> | 2017-09-13 14:32:08 +0300 |
|---|---|---|
| committer | Matthew Dempsky <mdempsky@google.com> | 2017-09-15 21:05:03 +0000 |
| commit | 8c67f210a181f4d3e003e46e544ae03ce231ca42 (patch) | |
| tree | 537c869a16a02ed96ed005b345aeeec040080686 /src/cmd/internal/obj/ppc64 | |
| parent | e1cf2be7a82a2421c69c48cbdf596841f29bff77 (diff) | |
| download | go-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.go | 50 | ||||
| -rw-r--r-- | src/cmd/internal/obj/ppc64/obj9.go | 2 |
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 |
