Skip to content

Commit 7bca2c5

Browse files
committed
[dev.ssa] cmd/compile: some improvements to PPC codegen
Runs fibonacci for all integer types. Fold addressing arithmetic into stores. Updates #16010. Change-Id: I257982c82c00c80b00679757c3da345045968022 Reviewed-on: https://go-review.googlesource.com/25103 Reviewed-by: Cherry Zhang <[email protected]> Run-TryBot: David Chase <[email protected]>
1 parent df2f813 commit 7bca2c5

File tree

6 files changed

+341
-90
lines changed

6 files changed

+341
-90
lines changed

src/cmd/compile/internal/ppc64/ssa.go

Lines changed: 106 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -162,39 +162,66 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
162162
}
163163
p.To.Type = obj.TYPE_REG
164164
p.To.Reg = gc.SSARegNum(v)
165+
166+
case ssa.OpPPC64MOVDaddr:
167+
p := gc.Prog(ppc64.AMOVD)
168+
p.From.Type = obj.TYPE_ADDR
169+
p.To.Type = obj.TYPE_REG
170+
p.To.Reg = gc.SSARegNum(v)
171+
172+
var wantreg string
173+
// Suspect comment, copied from ARM code
174+
// MOVD $sym+off(base), R
175+
// the assembler expands it as the following:
176+
// - base is SP: add constant offset to SP
177+
// when constant is large, tmp register (R11) may be used
178+
// - base is SB: load external address from constant pool (use relocation)
179+
switch v.Aux.(type) {
180+
default:
181+
v.Fatalf("aux is of unknown type %T", v.Aux)
182+
case *ssa.ExternSymbol:
183+
wantreg = "SB"
184+
gc.AddAux(&p.From, v)
185+
case *ssa.ArgSymbol, *ssa.AutoSymbol:
186+
wantreg = "SP"
187+
gc.AddAux(&p.From, v)
188+
case nil:
189+
// No sym, just MOVD $off(SP), R
190+
wantreg = "SP"
191+
p.From.Reg = ppc64.REGSP
192+
p.From.Offset = v.AuxInt
193+
}
194+
if reg := gc.SSAReg(v.Args[0]); reg.Name() != wantreg {
195+
v.Fatalf("bad reg %s for symbol type %T, want %s", reg.Name(), v.Aux, wantreg)
196+
}
197+
165198
case ssa.OpPPC64MOVDconst, ssa.OpPPC64MOVWconst, ssa.OpPPC64MOVHconst, ssa.OpPPC64MOVBconst, ssa.OpPPC64FMOVDconst, ssa.OpPPC64FMOVSconst:
166199
p := gc.Prog(v.Op.Asm())
167200
p.From.Type = obj.TYPE_CONST
168201
p.From.Offset = v.AuxInt
169202
p.To.Type = obj.TYPE_REG
170203
p.To.Reg = gc.SSARegNum(v)
171204

172-
case ssa.OpPPC64FCMPU:
173-
p := gc.Prog(v.Op.Asm())
174-
p.From.Type = obj.TYPE_REG
175-
p.From.Reg = gc.SSARegNum(v.Args[1])
176-
p.Reg = gc.SSARegNum(v.Args[0])
177-
178-
case ssa.OpPPC64CMP, ssa.OpPPC64CMPW, ssa.OpPPC64CMPU, ssa.OpPPC64CMPWU:
205+
case ssa.OpPPC64FCMPU, ssa.OpPPC64CMP, ssa.OpPPC64CMPW, ssa.OpPPC64CMPU, ssa.OpPPC64CMPWU:
179206
p := gc.Prog(v.Op.Asm())
180207
p.From.Type = obj.TYPE_REG
181-
p.From.Reg = gc.SSARegNum(v.Args[1])
182-
p.Reg = gc.SSARegNum(v.Args[0])
208+
p.From.Reg = gc.SSARegNum(v.Args[0])
183209
p.To.Type = obj.TYPE_REG
184-
p.To.Reg = gc.SSARegNum(v.Args[0])
210+
p.To.Reg = gc.SSARegNum(v.Args[1])
185211

186212
case ssa.OpPPC64CMPconst:
187213
p := gc.Prog(v.Op.Asm())
188-
p.From.Type = obj.TYPE_CONST
189-
p.From.Offset = v.AuxInt
190-
p.Reg = gc.SSARegNum(v.Args[0])
214+
p.From.Type = obj.TYPE_REG
215+
p.From.Reg = gc.SSARegNum(v.Args[0])
216+
p.To.Type = obj.TYPE_CONST
217+
p.To.Offset = v.AuxInt
191218

192219
case ssa.OpPPC64MOVBreg, ssa.OpPPC64MOVBZreg, ssa.OpPPC64MOVHreg, ssa.OpPPC64MOVHZreg, ssa.OpPPC64MOVWreg, ssa.OpPPC64MOVWZreg:
193220
// Shift in register to required size
194221
p := gc.Prog(v.Op.Asm())
195222
p.From.Type = obj.TYPE_REG
196223
p.From.Reg = gc.SSARegNum(v.Args[0])
197-
p.To.Reg = gc.SSARegNum(v.Args[0])
224+
p.To.Reg = gc.SSARegNum(v)
198225
p.To.Type = obj.TYPE_REG
199226

200227
case ssa.OpPPC64MOVDload, ssa.OpPPC64MOVWload, ssa.OpPPC64MOVBload, ssa.OpPPC64MOVHload, ssa.OpPPC64MOVWZload, ssa.OpPPC64MOVBZload, ssa.OpPPC64MOVHZload:
@@ -212,13 +239,15 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
212239
p.To.Type = obj.TYPE_REG
213240
p.To.Reg = gc.SSARegNum(v)
214241
case ssa.OpPPC64MOVDstoreconst, ssa.OpPPC64MOVWstoreconst, ssa.OpPPC64MOVHstoreconst, ssa.OpPPC64MOVBstoreconst:
242+
// TODO: pretty sure this is bogus, PPC has no such instruction unless constant is zero.
215243
p := gc.Prog(v.Op.Asm())
216244
p.From.Type = obj.TYPE_CONST
217245
sc := v.AuxValAndOff()
218246
p.From.Offset = sc.Val()
219247
p.To.Type = obj.TYPE_MEM
220248
p.To.Reg = gc.SSARegNum(v.Args[0])
221249
gc.AddAux2(&p.To, v, sc.Off())
250+
222251
case ssa.OpPPC64MOVDstore, ssa.OpPPC64MOVWstore, ssa.OpPPC64MOVHstore, ssa.OpPPC64MOVBstore:
223252
p := gc.Prog(v.Op.Asm())
224253
p.From.Type = obj.TYPE_REG
@@ -272,17 +301,79 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
272301
}
273302
}
274303

304+
var blockJump = [...]struct {
305+
asm, invasm obj.As
306+
}{
307+
ssa.BlockPPC64EQ: {ppc64.ABEQ, ppc64.ABNE},
308+
ssa.BlockPPC64NE: {ppc64.ABNE, ppc64.ABEQ},
309+
310+
ssa.BlockPPC64LT: {ppc64.ABLT, ppc64.ABGE},
311+
ssa.BlockPPC64GE: {ppc64.ABGE, ppc64.ABLT},
312+
ssa.BlockPPC64LE: {ppc64.ABLE, ppc64.ABGT},
313+
ssa.BlockPPC64GT: {ppc64.ABGT, ppc64.ABLE},
314+
315+
ssa.BlockPPC64ULT: {ppc64.ABLT, ppc64.ABGE},
316+
ssa.BlockPPC64UGE: {ppc64.ABGE, ppc64.ABLT},
317+
ssa.BlockPPC64ULE: {ppc64.ABLE, ppc64.ABGT},
318+
ssa.BlockPPC64UGT: {ppc64.ABGT, ppc64.ABLE},
319+
}
320+
275321
func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
276322
s.SetLineno(b.Line)
277323

278324
switch b.Kind {
279-
case ssa.BlockCall:
325+
case ssa.BlockPlain, ssa.BlockCall, ssa.BlockCheck:
280326
if b.Succs[0].Block() != next {
281327
p := gc.Prog(obj.AJMP)
282328
p.To.Type = obj.TYPE_BRANCH
283329
s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
284330
}
331+
case ssa.BlockExit:
332+
gc.Prog(obj.AUNDEF) // tell plive.go that we never reach here
285333
case ssa.BlockRet:
286334
gc.Prog(obj.ARET)
335+
336+
case ssa.BlockPPC64EQ, ssa.BlockPPC64NE,
337+
ssa.BlockPPC64LT, ssa.BlockPPC64GE,
338+
ssa.BlockPPC64LE, ssa.BlockPPC64GT,
339+
ssa.BlockPPC64ULT, ssa.BlockPPC64UGT,
340+
ssa.BlockPPC64ULE, ssa.BlockPPC64UGE:
341+
jmp := blockJump[b.Kind]
342+
likely := b.Likely
343+
var p *obj.Prog
344+
switch next {
345+
case b.Succs[0].Block():
346+
p = gc.Prog(jmp.invasm)
347+
likely *= -1
348+
p.To.Type = obj.TYPE_BRANCH
349+
s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[1].Block()})
350+
case b.Succs[1].Block():
351+
p = gc.Prog(jmp.asm)
352+
p.To.Type = obj.TYPE_BRANCH
353+
s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
354+
default:
355+
p = gc.Prog(jmp.asm)
356+
p.To.Type = obj.TYPE_BRANCH
357+
s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
358+
q := gc.Prog(obj.AJMP)
359+
q.To.Type = obj.TYPE_BRANCH
360+
s.Branches = append(s.Branches, gc.Branch{P: q, B: b.Succs[1].Block()})
361+
}
362+
363+
// liblink reorders the instruction stream as it sees fit.
364+
// Pass along what we know so liblink can make use of it.
365+
// TODO: Once we've fully switched to SSA,
366+
// make liblink leave our output alone.
367+
//switch likely {
368+
//case ssa.BranchUnlikely:
369+
// p.From.Type = obj.TYPE_CONST
370+
// p.From.Offset = 0
371+
//case ssa.BranchLikely:
372+
// p.From.Type = obj.TYPE_CONST
373+
// p.From.Offset = 1
374+
//}
375+
376+
default:
377+
b.Unimplementedf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
287378
}
288379
}

src/cmd/compile/internal/ssa/gen/PPC64.rules

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
(ConstNil) -> (MOVDconst [0])
4040
(ConstBool [b]) -> (MOVBconst [b])
4141

42-
(Addr {sym} base) -> (ADDconst {sym} base)
42+
(Addr {sym} base) -> (MOVDaddr {sym} base)
43+
// (Addr {sym} base) -> (ADDconst {sym} base)
4344
(OffPtr [off] ptr) -> (ADD (MOVDconst <config.Frontend().TypeInt64()> [off]) ptr)
4445
(StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
4546

@@ -148,7 +149,7 @@
148149
(Load <t> ptr mem) && is32BitInt(t) && !isSigned(t) -> (MOVWZload ptr mem)
149150
(Load <t> ptr mem) && is16BitInt(t) && isSigned(t) -> (MOVHload ptr mem)
150151
(Load <t> ptr mem) && is16BitInt(t) && !isSigned(t) -> (MOVHZload ptr mem)
151-
(Load <t> ptr mem) && (t.IsBoolean() || (is8BitInt(t) && !isSigned(t))) -> (MOVBload ptr mem)
152+
(Load <t> ptr mem) && (t.IsBoolean() || (is8BitInt(t) && isSigned(t))) -> (MOVBload ptr mem)
152153
(Load <t> ptr mem) && is8BitInt(t) && !isSigned(t) -> (MOVBZload ptr mem)
153154
(Load <t> ptr mem) && is32BitFloat(t) -> (FMOVSload ptr mem)
154155
(Load <t> ptr mem) && is64BitFloat(t) -> (FMOVDload ptr mem)
@@ -210,6 +211,14 @@
210211
(ADD (MOVDconst [c]) x) -> (ADDconst [c] x)
211212
(ADD x (MOVDconst [c])) -> (ADDconst [c] x)
212213

214+
(MOVDstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVDstore [off1+off2] {sym} x val mem)
215+
(MOVWstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVWstore [off1+off2] {sym} x val mem)
216+
(MOVHstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVHstore [off1+off2] {sym} x val mem)
217+
(MOVBstore [off1] {sym} (ADDconst [off2] x) val mem) && is16Bit(off1+off2) -> (MOVBstore [off1+off2] {sym} x val mem)
218+
219+
// TODO MOV*storeconst is wrong for PPC
220+
// (MOVDstore ptr (MOVDconst [c]) mem) && c == 0 -> (MOVDstoreconst [c] ptr mem)
221+
213222
// Lowering extension
214223
// Note: we always extend to 64 bits even though some ops don't need that many result bits.
215224
(SignExt8to16 x) -> (MOVBreg x)

src/cmd/compile/internal/ssa/gen/PPC64Ops.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,27 +96,27 @@ func init() {
9696
gp = buildReg("R3 R4 R5 R6 R7 R8 R9 R10 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29")
9797
fp = buildReg("F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26")
9898
sp = buildReg("SP")
99-
// sb = buildReg("SB")
99+
sb = buildReg("SB")
100100
// gg = buildReg("R30")
101101
cr = buildReg("CR")
102102
// tmp = buildReg("R31")
103103
// ctxt = buildReg("R11")
104104
// tls = buildReg("R13")
105105
gp01 = regInfo{inputs: []regMask{}, outputs: []regMask{gp}}
106-
gp11 = regInfo{inputs: []regMask{gp | sp}, outputs: []regMask{gp}}
107-
gp21 = regInfo{inputs: []regMask{gp | sp, gp | sp}, outputs: []regMask{gp}}
108-
gp1cr = regInfo{inputs: []regMask{gp | sp}, outputs: []regMask{cr}}
109-
gp2cr = regInfo{inputs: []regMask{gp | sp, gp | sp}, outputs: []regMask{cr}}
106+
gp11 = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}
107+
gp21 = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{gp}}
108+
gp1cr = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{cr}}
109+
gp2cr = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{cr}}
110110
crgp = regInfo{inputs: []regMask{cr}, outputs: []regMask{gp}}
111-
gpload = regInfo{inputs: []regMask{gp | sp}, outputs: []regMask{gp}}
112-
gpstore = regInfo{inputs: []regMask{gp | sp, gp | sp}, outputs: []regMask{}}
113-
gpstoreconst = regInfo{inputs: []regMask{gp | sp, 0}, outputs: []regMask{}}
111+
gpload = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}
112+
gpstore = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb}, outputs: []regMask{}}
113+
gpstoreconst = regInfo{inputs: []regMask{gp | sp | sb, 0}, outputs: []regMask{}}
114114
fp01 = regInfo{inputs: []regMask{}, outputs: []regMask{fp}}
115115
// fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
116116
fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
117117
fp2cr = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{cr}}
118-
fpload = regInfo{inputs: []regMask{gp | sp}, outputs: []regMask{fp}}
119-
fpstore = regInfo{inputs: []regMask{fp, gp | sp}, outputs: []regMask{}}
118+
fpload = regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{fp}}
119+
fpstore = regInfo{inputs: []regMask{gp | sp | sb, fp}, outputs: []regMask{}}
120120
callerSave = regMask(gp | fp)
121121
)
122122
ops := []opData{
@@ -167,6 +167,8 @@ func init() {
167167
{name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem"}, // store low 4 bytes of ...
168168
{name: "MOVDstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVD", aux: "SymValAndOff", typ: "Mem"}, // store 8 bytes of ...
169169

170+
{name: "MOVDaddr", argLength: 1, reg: regInfo{inputs: []regMask{sp | sb}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVD", rematerializeable: true}, // arg0 + auxInt + aux.(*gc.Sym), arg0=SP/SB
171+
170172
{name: "MOVDconst", argLength: 0, reg: gp01, aux: "Int64", asm: "MOVD", rematerializeable: true}, //
171173
{name: "MOVWconst", argLength: 0, reg: gp01, aux: "Int32", asm: "MOVW", rematerializeable: true}, // 32 low bits of auxint
172174
{name: "MOVHconst", argLength: 0, reg: gp01, aux: "Int16", asm: "MOVH", rematerializeable: true}, // 16 low bits of auxint

0 commit comments

Comments
 (0)