Skip to content

Commit dca577d

Browse files
committed
cmd/compile/internal/ssa: reintroduce ANDconst opcode on PPC64
This allows more effective conversion of rotate and mask opcodes into their CC equivalents, while simplifying the first lowering pass. This was removed before the latelower pass was introduced to fold more cases of compare against zero. Add ANDconst to push the conversion of ANDconst to ANDCCconst into latelower with the other CC opcodes. This also requires introducing RLDICLCC to prevent regressions when ANDconst is converted to RLDICL then to RLDICLCC and back to ANDCCconst when possible. Change-Id: I9e5f9c99fbefa334db18c6c152c5f967f3ff2590 Reviewed-on: https://go-review.googlesource.com/c/go/+/586160 Reviewed-by: Lynn Boger <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Carlos Amedee <[email protected]>
1 parent 6861b2e commit dca577d

File tree

8 files changed

+752
-982
lines changed

8 files changed

+752
-982
lines changed

Diff for: src/cmd/compile/internal/ppc64/ssa.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -629,18 +629,18 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
629629
p.AddRestSourceArgs([]obj.Addr{{Type: obj.TYPE_CONST, Offset: mb}, {Type: obj.TYPE_CONST, Offset: me}})
630630
// Auxint holds mask
631631

632-
case ssa.OpPPC64RLDICL, ssa.OpPPC64RLDICR:
632+
case ssa.OpPPC64RLDICL, ssa.OpPPC64RLDICLCC, ssa.OpPPC64RLDICR:
633633
sh, mb, me, _ := ssa.DecodePPC64RotateMask(v.AuxInt)
634634
p := s.Prog(v.Op.Asm())
635635
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: sh}
636636
switch v.Op {
637-
case ssa.OpPPC64RLDICL:
637+
case ssa.OpPPC64RLDICL, ssa.OpPPC64RLDICLCC:
638638
p.AddRestSourceConst(mb)
639639
case ssa.OpPPC64RLDICR:
640640
p.AddRestSourceConst(me)
641641
}
642642
p.Reg = v.Args[0].Reg()
643-
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: v.Reg()}
643+
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: v.ResultReg()}
644644

645645
case ssa.OpPPC64RLWNM:
646646
_, mb, me, _ := ssa.DecodePPC64RotateMask(v.AuxInt)
@@ -691,7 +691,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
691691

692692
case ssa.OpPPC64ADDconst, ssa.OpPPC64ORconst, ssa.OpPPC64XORconst,
693693
ssa.OpPPC64SRADconst, ssa.OpPPC64SRAWconst, ssa.OpPPC64SRDconst, ssa.OpPPC64SRWconst,
694-
ssa.OpPPC64SLDconst, ssa.OpPPC64SLWconst, ssa.OpPPC64EXTSWSLconst, ssa.OpPPC64MULLWconst, ssa.OpPPC64MULLDconst:
694+
ssa.OpPPC64SLDconst, ssa.OpPPC64SLWconst, ssa.OpPPC64EXTSWSLconst, ssa.OpPPC64MULLWconst, ssa.OpPPC64MULLDconst,
695+
ssa.OpPPC64ANDconst:
695696
p := s.Prog(v.Op.Asm())
696697
p.Reg = v.Args[0].Reg()
697698
p.From.Type = obj.TYPE_CONST

Diff for: src/cmd/compile/internal/ssa/_gen/PPC64.rules

+61-63
Large diffs are not rendered by default.

Diff for: src/cmd/compile/internal/ssa/_gen/PPC64Ops.go

+10-8
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,12 @@ func init() {
248248
{name: "ROTLWconst", argLength: 1, reg: gp11, asm: "ROTLW", aux: "Int64"}, // uint32(arg0) rotate left by auxInt bits
249249
{name: "EXTSWSLconst", argLength: 1, reg: gp11, asm: "EXTSWSLI", aux: "Int64"},
250250

251-
{name: "RLWINM", argLength: 1, reg: gp11, asm: "RLWNM", aux: "Int64"}, // Rotate and mask by immediate "rlwinm". encodePPC64RotateMask describes aux
252-
{name: "RLWNM", argLength: 2, reg: gp21, asm: "RLWNM", aux: "Int64"}, // Rotate and mask by "rlwnm". encodePPC64RotateMask describes aux
253-
{name: "RLWMI", argLength: 2, reg: gp21a0, asm: "RLWMI", aux: "Int64", resultInArg0: true}, // "rlwimi" similar aux encoding as above
254-
{name: "RLDICL", argLength: 1, reg: gp11, asm: "RLDICL", aux: "Int64"}, // Auxint is encoded similarly to RLWINM, but only MB and SH are valid. ME is always 63.
255-
{name: "RLDICR", argLength: 1, reg: gp11, asm: "RLDICR", aux: "Int64"}, // Likewise, but only ME and SH are valid. MB is always 0.
251+
{name: "RLWINM", argLength: 1, reg: gp11, asm: "RLWNM", aux: "Int64"}, // Rotate and mask by immediate "rlwinm". encodePPC64RotateMask describes aux
252+
{name: "RLWNM", argLength: 2, reg: gp21, asm: "RLWNM", aux: "Int64"}, // Rotate and mask by "rlwnm". encodePPC64RotateMask describes aux
253+
{name: "RLWMI", argLength: 2, reg: gp21a0, asm: "RLWMI", aux: "Int64", resultInArg0: true}, // "rlwimi" similar aux encoding as above
254+
{name: "RLDICL", argLength: 1, reg: gp11, asm: "RLDICL", aux: "Int64"}, // Auxint is encoded similarly to RLWINM, but only MB and SH are valid. ME is always 63.
255+
{name: "RLDICLCC", argLength: 1, reg: gp11, asm: "RLDICLCC", aux: "Int64", typ: "(Int, Flags)"}, // Auxint is encoded similarly to RLWINM, but only MB and SH are valid. ME is always 63. Sets CC.
256+
{name: "RLDICR", argLength: 1, reg: gp11, asm: "RLDICR", aux: "Int64"}, // Likewise, but only ME and SH are valid. MB is always 0.
256257

257258
{name: "CNTLZD", argLength: 1, reg: gp11, asm: "CNTLZD"}, // count leading zeros
258259
{name: "CNTLZDCC", argLength: 1, reg: gp11, asm: "CNTLZDCC", typ: "(Int, Flags)"}, // count leading zeros, sets CC
@@ -323,9 +324,10 @@ func init() {
323324
{name: "FNABS", argLength: 1, reg: fp11, asm: "FNABS"}, // -abs(arg0), float64
324325
{name: "FCPSGN", argLength: 2, reg: fp21, asm: "FCPSGN"}, // copysign arg0 -> arg1, float64
325326

326-
{name: "ORconst", argLength: 1, reg: gp11, asm: "OR", aux: "Int64"}, // arg0|aux
327-
{name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64"}, // arg0^aux
328-
{name: "ANDCCconst", argLength: 1, reg: regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}, asm: "ANDCC", aux: "Int64", typ: "(Int,Flags)"}, // arg0&aux == 0 // and-immediate sets CC on PPC, always.
327+
{name: "ORconst", argLength: 1, reg: gp11, asm: "OR", aux: "Int64"}, // arg0|aux
328+
{name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64"}, // arg0^aux
329+
{name: "ANDCCconst", argLength: 1, reg: regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}, asm: "ANDCC", aux: "Int64", typ: "(Int,Flags)"}, // arg0&aux == 0 // and-immediate sets CC on PPC, always.
330+
{name: "ANDconst", argLength: 1, reg: regInfo{inputs: []regMask{gp | sp | sb}, outputs: []regMask{gp}}, clobberFlags: true, asm: "ANDCC", aux: "Int64", typ: "Int"}, // arg0&aux == 0 // and-immediate sets CC on PPC, always.
329331

330332
{name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB", typ: "Int64"}, // sign extend int8 to int64
331333
{name: "MOVBZreg", argLength: 1, reg: gp11, asm: "MOVBZ", typ: "Int64"}, // zero extend uint8 to uint64

Diff for: src/cmd/compile/internal/ssa/_gen/PPC64latelower.rules

+11-6
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,8 @@
1818
(SETBC [1] cmp) && buildcfg.GOPPC64 <= 9 => (ISELZ [1] (MOVDconst [1]) cmp)
1919
(SETBCR [1] cmp) && buildcfg.GOPPC64 <= 9 => (ISELZ [5] (MOVDconst [1]) cmp)
2020

21-
// Avoid using ANDCCconst if the value for CR0 is not needed, since ANDCCconst
22-
// always sets it.
23-
(Select0 z:(ANDCCconst [m] x)) && z.Uses == 1 && isPPC64ValidShiftMask(m) => (RLDICL [encodePPC64RotateMask(0,m,64)] x)
2421
// The upper bits of the smaller than register values is undefined. Take advantage of that.
25-
(AND <t> x:(MOVDconst [m]) n) && t.Size() <= 2 => (Select0 (ANDCCconst [int64(int16(m))] n))
22+
(AND <t> x:(MOVDconst [m]) n) && t.Size() <= 2 => (ANDconst [int64(int16(m))] n)
2623

2724
// Convert simple bit masks to an equivalent rldic[lr] if possible.
2825
(AND x:(MOVDconst [m]) n) && isPPC64ValidShiftMask(m) => (RLDICL [encodePPC64RotateMask(0,m,64)] n)
@@ -47,9 +44,17 @@
4744
// Note: to minimize potentially expensive regeneration of CC opcodes during the flagalloc pass, only rewrite if
4845
// both ops are in the same block.
4946
(CMPconst [0] z:((ADD|AND|ANDN|OR|SUB|NOR|XOR) x y)) && v.Block == z.Block => (CMPconst [0] convertPPC64OpToOpCC(z))
50-
(CMPconst [0] z:((NEG|CNTLZD) x)) && v.Block == z.Block => (CMPconst [0] convertPPC64OpToOpCC(z))
47+
(CMPconst [0] z:((NEG|CNTLZD|RLDICL) x)) && v.Block == z.Block => (CMPconst [0] convertPPC64OpToOpCC(z))
5148
// Note: ADDCCconst only assembles to 1 instruction for int16 constants.
5249
(CMPconst [0] z:(ADDconst [c] x)) && int64(int16(c)) == c && v.Block == z.Block => (CMPconst [0] convertPPC64OpToOpCC(z))
50+
(CMPconst [0] z:(ANDconst [c] x)) && int64(uint16(c)) == c && v.Block == z.Block => (CMPconst [0] convertPPC64OpToOpCC(z))
5351
// And finally, fixup the flag user.
5452
(CMPconst <t> [0] (Select0 z:((ADD|AND|ANDN|OR|SUB|NOR|XOR)CC x y))) => (Select1 <t> z)
55-
(CMPconst <t> [0] (Select0 z:((ADDCCconst|NEGCC|CNTLZDCC) y))) => (Select1 <t> z)
53+
(CMPconst <t> [0] (Select0 z:((ADDCCconst|ANDCCconst|NEGCC|CNTLZDCC|RLDICLCC) y))) => (Select1 <t> z)
54+
55+
// After trying to convert ANDconst to ANDCCconst above, if the CC result is not needed, try to avoid using
56+
// ANDconst which clobbers CC.
57+
(ANDconst [m] x) && isPPC64ValidShiftMask(m) => (RLDICL [encodePPC64RotateMask(0,m,64)] x)
58+
59+
// Likewise, trying converting RLDICLCC back to ANDCCconst as it is faster.
60+
(RLDICLCC [a] x) && convertPPC64RldiclAndccconst(a) != 0 => (ANDCCconst [convertPPC64RldiclAndccconst(a)] x)

Diff for: src/cmd/compile/internal/ssa/opGen.go

+31
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: src/cmd/compile/internal/ssa/rewrite.go

+11
Original file line numberDiff line numberDiff line change
@@ -1745,9 +1745,11 @@ func convertPPC64OpToOpCC(op *Value) *Value {
17451745
OpPPC64ADD: OpPPC64ADDCC,
17461746
OpPPC64ADDconst: OpPPC64ADDCCconst,
17471747
OpPPC64AND: OpPPC64ANDCC,
1748+
OpPPC64ANDconst: OpPPC64ANDCCconst,
17481749
OpPPC64ANDN: OpPPC64ANDNCC,
17491750
OpPPC64CNTLZD: OpPPC64CNTLZDCC,
17501751
OpPPC64OR: OpPPC64ORCC,
1752+
OpPPC64RLDICL: OpPPC64RLDICLCC,
17511753
OpPPC64SUB: OpPPC64SUBCC,
17521754
OpPPC64NEG: OpPPC64NEGCC,
17531755
OpPPC64NOR: OpPPC64NORCC,
@@ -1761,6 +1763,15 @@ func convertPPC64OpToOpCC(op *Value) *Value {
17611763
return op
17621764
}
17631765

1766+
// Try converting a RLDICL to ANDCC. If successful, return the mask otherwise 0.
1767+
func convertPPC64RldiclAndccconst(sauxint int64) int64 {
1768+
r, _, _, mask := DecodePPC64RotateMask(sauxint)
1769+
if r != 0 || mask&0xFFFF != mask {
1770+
return 0
1771+
}
1772+
return int64(mask)
1773+
}
1774+
17641775
// Convenience function to rotate a 32 bit constant value by another constant.
17651776
func rotateLeft32(v, rotate int64) int64 {
17661777
return int64(bits.RotateLeft32(uint32(v), int(rotate)))

0 commit comments

Comments
 (0)