Skip to content

Commit 3128aee

Browse files
committed
cmd/internal/obj/ppc64: remove C_UCON optab matching class
This optab matching rule was used to match signed 16 bit values shifted left by 16 bits. Unsigned 16 bit values greater than 0x7FFF<<16 were classified as C_U32CON which led to larger than necessary codegen. Instead, rewrite logical/arithmetic operations in the preprocessor pass to use the 16 bit shifted immediate operation (e.g ADDIS vs ADD). This simplifies the optab matching rules, while also minimizing codegen size for large unsigned values. Note, ADDIS sign-extends the constant argument, all others do not. For matching opcodes, this means: MOVD $is<<16,Rx becomes ADDIS $is,Rx or ORIS $is,Rx MOVW $is<<16,Rx becomes ADDIS $is,Rx ADD $is<<16,[Rx,]Ry becomes ADDIS $is[Rx,]Ry OR $is<<16,[Rx,]Ry becomes ORIS $is[Rx,]Ry XOR $is<<16,[Rx,]Ry becomes XORIS $is[Rx,]Ry Change-Id: I1a988d9f52517a04bb8dc2e41d7caf3d5fff867c Reviewed-on: https://go-review.googlesource.com/c/go/+/536735 LUCI-TryBot-Result: Go LUCI <[email protected]> Run-TryBot: Paul Murphy <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Cherry Mui <[email protected]> Reviewed-by: Lynn Boger <[email protected]>
1 parent 6b818b0 commit 3128aee

File tree

7 files changed

+84
-83
lines changed

7 files changed

+84
-83
lines changed

src/cmd/asm/internal/asm/testdata/ppc64.s

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
1717
MOVD $1, R3 // 38600001
1818
MOVD $-1, R4 // 3880ffff
1919
MOVD $65535, R5 // 6005ffff
20-
MOVD $65536, R6 // 64060001
20+
MOVD $65536, R6 // 3cc00001
2121
MOVD $-32767, R5 // 38a08001
2222
MOVD $-32768, R6 // 38c08000
2323
MOVD $1234567, R5 // 6405001260a5d687 or 0600001238a0d687
2424
MOVW $1, R3 // 38600001
2525
MOVW $-1, R4 // 3880ffff
2626
MOVW $65535, R5 // 6005ffff
27-
MOVW $65536, R6 // 64060001
27+
MOVW $65536, R6 // 3cc00001
2828
MOVW $-32767, R5 // 38a08001
2929
MOVW $-32768, R6 // 38c08000
3030
MOVW $1234567, R5 // 6405001260a5d687 or 0600001238a0d687
@@ -36,6 +36,11 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
3636
// Hex constant 0xFFFFFFFE00000002 (load of constant on < power10, pli on >= power10
3737
MOVD $-8589934590, R5 // 3ca00000e8a50000 or 0602000038a00002
3838

39+
// For backwards compatibility, MOVW $const,Rx and MOVWZ $const,Rx assemble identically
40+
// and accept the same constants.
41+
MOVW $2147483648, R5 // 64058000
42+
MOVWZ $-2147483648, R5 // 3ca08000
43+
3944
// TODO: These are preprocessed by the assembler into MOVD $const>>shift, R5; SLD $shift, R5.
4045
// This only captures the MOVD. Should the SLD be appended to the encoding by the test?
4146
// Hex constant 0x20004000000
@@ -192,6 +197,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
192197
ADDEX R3, R5, $3, R6 // 7cc32f54
193198
ADDEX R3, $3, R5, R6 // 7cc32f54
194199
ADDIS $8, R3 // 3c630008
200+
ADD $524288, R3 // 3c630008
195201
ADDIS $1000, R3, R4 // 3c8303e8
196202

197203
ANDCC $1, R3 // 70630001
@@ -210,6 +216,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
210216
ANDCC $1234567, R5, R6 // 641f001263ffd6877fe62839
211217
ANDISCC $1, R3 // 74630001
212218
ANDISCC $1000, R3, R4 // 746403e8
219+
ANDCC $65536000, R3, R4 // 746403e8
213220

214221
OR $1, R3 // 60630001
215222
OR $1, R3, R4 // 60640001
@@ -225,9 +232,10 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
225232
OR $-32768, R6, R7 // 3be080007fe73378
226233
OR $1234567, R5 // 641f001263ffd6877fe52b78
227234
OR $1234567, R5, R3 // 641f001263ffd6877fe32b78
228-
OR $2147483648, R5, R3 // 641f8000600000007fe32b78
235+
OR $2147483648, R5, R3 // 64a38000
229236
OR $2147483649, R5, R3 // 641f800063ff00017fe32b78
230-
ORIS $255, R3, R4
237+
ORIS $255, R3, R4 // 646400ff
238+
OR $16711680, R3, R4 // 646400ff
231239

232240
XOR $1, R3 // 68630001
233241
XOR $1, R3, R4 // 68640001
@@ -243,7 +251,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
243251
XOR $-32768, R6, R7 // 3be080007fe73278
244252
XOR $1234567, R5 // 641f001263ffd6877fe52a78
245253
XOR $1234567, R5, R3 // 641f001263ffd6877fe32a78
246-
XORIS $15, R3, R4
254+
XORIS $15, R3, R4 // 6c64000f
255+
XOR $983040, R3, R4 // 6c64000f
247256

248257
// TODO: the order of CR operands don't match
249258
CMP R3, R4 // 7c232000

src/cmd/internal/obj/ppc64/a.out.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,6 @@ const (
422422
C_U15CON /* 15 bit unsigned constant */
423423
C_S16CON /* 16 bit signed constant */
424424
C_U16CON /* 16 bit unsigned constant */
425-
C_32S16CON /* Any 32 bit constant of the form 0x....0000, signed or unsigned */
426425
C_32CON /* Any constant which fits into 32 bits. Can be signed or unsigned */
427426
C_S34CON /* 34 bit signed constant */
428427
C_64CON /* Any constant which fits into 64 bits. Can be signed or unsigned */
@@ -451,16 +450,13 @@ const (
451450

452451
/* Aliased names which should be cleaned up, or integrated. */
453452
C_SCON = C_U15CON
454-
C_UCON = C_32S16CON
455453
C_ADDCON = C_S16CON
456454
C_ANDCON = C_U16CON
457455
C_LCON = C_32CON
458456

459457
/* Aliased names which may be generated by ppc64map for the optab. */
460-
C_S3216CON = C_32S16CON // TODO: these should be treated differently (e.g xoris vs addis)
461-
C_U3216CON = C_32S16CON
462-
C_S32CON = C_32CON
463-
C_U32CON = C_32CON
458+
C_S32CON = C_32CON
459+
C_U32CON = C_32CON
464460
)
465461

466462
const (

src/cmd/internal/obj/ppc64/anames9.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ var cnames9 = []string{
2727
"U15CON",
2828
"S16CON",
2929
"U16CON",
30-
"32S16CON",
3130
"32CON",
3231
"S34CON",
3332
"64CON",

src/cmd/internal/obj/ppc64/asm9.go

Lines changed: 7 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,6 @@ var optabBase = []Optab{
120120
{as: AADD, a1: C_SCON, a6: C_REG, type_: 4, size: 4},
121121
{as: AADD, a1: C_ADDCON, a2: C_REG, a6: C_REG, type_: 4, size: 4},
122122
{as: AADD, a1: C_ADDCON, a6: C_REG, type_: 4, size: 4},
123-
{as: AADD, a1: C_UCON, a2: C_REG, a6: C_REG, type_: 20, size: 4},
124-
{as: AADD, a1: C_UCON, a6: C_REG, type_: 20, size: 4},
125123
{as: AADD, a1: C_ANDCON, a2: C_REG, a6: C_REG, type_: 22, size: 8},
126124
{as: AADD, a1: C_ANDCON, a6: C_REG, type_: 22, size: 8},
127125
{as: AADDIS, a1: C_ADDCON, a2: C_REG, a6: C_REG, type_: 20, size: 4},
@@ -138,14 +136,12 @@ var optabBase = []Optab{
138136
{as: AANDCC, a1: C_REG, a6: C_REG, type_: 6, size: 4},
139137
{as: AANDCC, a1: C_ANDCON, a6: C_REG, type_: 58, size: 4},
140138
{as: AANDCC, a1: C_ANDCON, a2: C_REG, a6: C_REG, type_: 58, size: 4},
141-
{as: AANDCC, a1: C_UCON, a6: C_REG, type_: 59, size: 4},
142-
{as: AANDCC, a1: C_UCON, a2: C_REG, a6: C_REG, type_: 59, size: 4},
143139
{as: AANDCC, a1: C_ADDCON, a6: C_REG, type_: 23, size: 8},
144140
{as: AANDCC, a1: C_ADDCON, a2: C_REG, a6: C_REG, type_: 23, size: 8},
145141
{as: AANDCC, a1: C_LCON, a6: C_REG, type_: 23, size: 12},
146142
{as: AANDCC, a1: C_LCON, a2: C_REG, a6: C_REG, type_: 23, size: 12},
147-
{as: AANDISCC, a1: C_ANDCON, a6: C_REG, type_: 59, size: 4},
148-
{as: AANDISCC, a1: C_ANDCON, a2: C_REG, a6: C_REG, type_: 59, size: 4},
143+
{as: AANDISCC, a1: C_ANDCON, a6: C_REG, type_: 58, size: 4},
144+
{as: AANDISCC, a1: C_ANDCON, a2: C_REG, a6: C_REG, type_: 58, size: 4},
149145
{as: AMULLW, a1: C_REG, a2: C_REG, a6: C_REG, type_: 2, size: 4},
150146
{as: AMULLW, a1: C_REG, a6: C_REG, type_: 2, size: 4},
151147
{as: AMULLW, a1: C_ADDCON, a2: C_REG, a6: C_REG, type_: 4, size: 4},
@@ -162,14 +158,12 @@ var optabBase = []Optab{
162158
{as: AOR, a1: C_REG, a6: C_REG, type_: 6, size: 4},
163159
{as: AOR, a1: C_ANDCON, a6: C_REG, type_: 58, size: 4},
164160
{as: AOR, a1: C_ANDCON, a2: C_REG, a6: C_REG, type_: 58, size: 4},
165-
{as: AOR, a1: C_UCON, a6: C_REG, type_: 59, size: 4},
166-
{as: AOR, a1: C_UCON, a2: C_REG, a6: C_REG, type_: 59, size: 4},
167161
{as: AOR, a1: C_ADDCON, a6: C_REG, type_: 23, size: 8},
168162
{as: AOR, a1: C_ADDCON, a2: C_REG, a6: C_REG, type_: 23, size: 8},
169163
{as: AOR, a1: C_LCON, a6: C_REG, type_: 23, size: 12},
170164
{as: AOR, a1: C_LCON, a2: C_REG, a6: C_REG, type_: 23, size: 12},
171-
{as: AORIS, a1: C_ANDCON, a6: C_REG, type_: 59, size: 4},
172-
{as: AORIS, a1: C_ANDCON, a2: C_REG, a6: C_REG, type_: 59, size: 4},
165+
{as: AORIS, a1: C_ANDCON, a6: C_REG, type_: 58, size: 4},
166+
{as: AORIS, a1: C_ANDCON, a2: C_REG, a6: C_REG, type_: 58, size: 4},
173167
{as: ADIVW, a1: C_REG, a2: C_REG, a6: C_REG, type_: 2, size: 4}, /* op r1[,r2],r3 */
174168
{as: ADIVW, a1: C_REG, a6: C_REG, type_: 2, size: 4},
175169
{as: ASUB, a1: C_REG, a2: C_REG, a6: C_REG, type_: 10, size: 4}, /* op r2[,r1],r3 */
@@ -240,7 +234,6 @@ var optabBase = []Optab{
240234

241235
{as: AMOVD, a1: C_ADDCON, a6: C_REG, type_: 3, size: 4},
242236
{as: AMOVD, a1: C_ANDCON, a6: C_REG, type_: 3, size: 4},
243-
{as: AMOVD, a1: C_UCON, a6: C_REG, type_: 3, size: 4},
244237
{as: AMOVD, a1: C_SACON, a6: C_REG, type_: 3, size: 4},
245238
{as: AMOVD, a1: C_SOREG, a6: C_REG, type_: 8, size: 4},
246239
{as: AMOVD, a1: C_XOREG, a6: C_REG, type_: 109, size: 4},
@@ -254,7 +247,6 @@ var optabBase = []Optab{
254247

255248
{as: AMOVW, a1: C_ADDCON, a6: C_REG, type_: 3, size: 4},
256249
{as: AMOVW, a1: C_ANDCON, a6: C_REG, type_: 3, size: 4},
257-
{as: AMOVW, a1: C_UCON, a6: C_REG, type_: 3, size: 4},
258250
{as: AMOVW, a1: C_SACON, a6: C_REG, type_: 3, size: 4},
259251
{as: AMOVW, a1: C_CREG, a6: C_REG, type_: 68, size: 4},
260252
{as: AMOVW, a1: C_SOREG, a6: C_REG, type_: 8, size: 4},
@@ -1051,10 +1043,6 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
10511043
case sbits <= 16:
10521044
return C_U16CON
10531045
case sbits <= 31:
1054-
// Special case, a positive int32 value which is a multiple of 2^16
1055-
if c.instoffset&0xFFFF == 0 {
1056-
return C_U3216CON
1057-
}
10581046
return C_U32CON
10591047
case sbits <= 32:
10601048
return C_U32CON
@@ -1069,10 +1057,6 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
10691057
case sbits <= 15:
10701058
return C_S16CON
10711059
case sbits <= 31:
1072-
// Special case, a negative int32 value which is a multiple of 2^16
1073-
if c.instoffset&0xFFFF == 0 {
1074-
return C_S3216CON
1075-
}
10761060
return C_S32CON
10771061
case sbits <= 33:
10781062
return C_S34CON
@@ -1193,15 +1177,12 @@ func cmp(a int, b int) bool {
11931177
case C_S16CON:
11941178
return cmp(C_U15CON, b)
11951179
case C_32CON:
1196-
return cmp(C_S16CON, b) || cmp(C_U16CON, b) || cmp(C_32S16CON, b)
1180+
return cmp(C_S16CON, b) || cmp(C_U16CON, b)
11971181
case C_S34CON:
11981182
return cmp(C_32CON, b)
11991183
case C_64CON:
12001184
return cmp(C_S34CON, b)
12011185

1202-
case C_32S16CON:
1203-
return cmp(C_ZCON, b)
1204-
12051186
case C_LACON:
12061187
return cmp(C_SACON, b)
12071188

@@ -2598,20 +2579,7 @@ func asmout(c *ctxt9, p *obj.Prog, o *Optab, out *[5]uint32) {
25982579
c.ctxt.Diag("literal operation on R0\n%v", p)
25992580
}
26002581
a := OP_ADDI
2601-
if o.a1 == C_UCON {
2602-
if d&0xffff != 0 {
2603-
log.Fatalf("invalid handling of %v", p)
2604-
}
2605-
// For UCON operands the value is right shifted 16, using ADDIS if the
2606-
// value should be signed, ORIS if unsigned.
2607-
v >>= 16
2608-
if r == REGZERO && isuint32(uint64(d)) {
2609-
o1 = LOP_IRR(OP_ORIS, uint32(p.To.Reg), REGZERO, uint32(v))
2610-
break
2611-
}
2612-
2613-
a = OP_ADDIS
2614-
} else if int64(int16(d)) != d {
2582+
if int64(int16(d)) != d {
26152583
// Operand is 16 bit value with sign bit set
26162584
if o.a1 == C_ANDCON {
26172585
// Needs unsigned 16 bit so use ORI
@@ -2944,14 +2912,7 @@ func asmout(c *ctxt9, p *obj.Prog, o *Optab, out *[5]uint32) {
29442912
if r == 0 {
29452913
r = int(p.To.Reg)
29462914
}
2947-
if p.As == AADD && (r0iszero == 0 /*TypeKind(100016)*/ && p.Reg == 0 || r0iszero != 0 /*TypeKind(100016)*/ && p.To.Reg == 0) {
2948-
c.ctxt.Diag("literal operation on R0\n%v", p)
2949-
}
2950-
if p.As == AADDIS {
2951-
o1 = AOP_IRR(c.opirr(p.As), uint32(p.To.Reg), uint32(r), uint32(v))
2952-
} else {
2953-
o1 = AOP_IRR(c.opirr(AADDIS), uint32(p.To.Reg), uint32(r), uint32(v)>>16)
2954-
}
2915+
o1 = AOP_IRR(c.opirr(p.As), uint32(p.To.Reg), uint32(r), uint32(v))
29552916

29562917
case 22: /* add $lcon/$andcon,r1,r2 ==> oris+ori+add/ori+add, add $s34con,r1 ==> addis+ori+slw+ori+add */
29572918
if p.To.Reg == REGTMP || p.Reg == REGTMP {
@@ -3425,24 +3386,6 @@ func asmout(c *ctxt9, p *obj.Prog, o *Optab, out *[5]uint32) {
34253386
}
34263387
o1 = LOP_IRR(c.opirr(p.As), uint32(p.To.Reg), uint32(r), uint32(v))
34273388

3428-
case 59: /* or/xor/and $ucon,,r | oris/xoris/andis $addcon,r,r */
3429-
v := c.regoff(&p.From)
3430-
3431-
r := int(p.Reg)
3432-
if r == 0 {
3433-
r = int(p.To.Reg)
3434-
}
3435-
switch p.As {
3436-
case AOR:
3437-
o1 = LOP_IRR(c.opirr(AORIS), uint32(p.To.Reg), uint32(r), uint32(v)>>16) /* oris, xoris, andis. */
3438-
case AXOR:
3439-
o1 = LOP_IRR(c.opirr(AXORIS), uint32(p.To.Reg), uint32(r), uint32(v)>>16)
3440-
case AANDCC:
3441-
o1 = LOP_IRR(c.opirr(AANDISCC), uint32(p.To.Reg), uint32(r), uint32(v)>>16)
3442-
default:
3443-
o1 = LOP_IRR(c.opirr(p.As), uint32(p.To.Reg), uint32(r), uint32(v))
3444-
}
3445-
34463389
case 60: /* tw to,a,b */
34473390
r := int(c.regoff(&p.From) & 31)
34483391

src/cmd/internal/obj/ppc64/asm_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,12 +517,10 @@ func TestAddrClassifier(t *testing.T) {
517517
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 32}, C_U8CON},
518518
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 14}, C_U15CON},
519519
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 15}, C_U16CON},
520-
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 16}, C_U3216CON},
521520
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 + 1<<16}, C_U32CON},
522521
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 32}, C_S34CON},
523522
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: 1 << 33}, C_64CON},
524523
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -1}, C_S16CON},
525-
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -0x10000}, C_S3216CON},
526524
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -0x10001}, C_S32CON},
527525
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -(1 << 33)}, C_S34CON},
528526
{obj.Addr{Type: obj.TYPE_CONST, Name: obj.NAME_NONE, Offset: -(1 << 34)}, C_64CON},

src/cmd/internal/obj/ppc64/obj9.go

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,48 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
113113
}
114114
}
115115

116+
case AMOVW, AMOVWZ:
117+
// Note, for backwards compatibility, MOVW $const, Rx and MOVWZ $const, Rx are identical.
118+
if p.From.Type == obj.TYPE_CONST && p.From.Offset != 0 && p.From.Offset&0xFFFF == 0 {
119+
// This is a constant shifted 16 bits to the left, convert it to ADDIS/ORIS $const,...
120+
p.As = AADDIS
121+
// Use ORIS for large constants which should not be sign extended.
122+
if p.From.Offset >= 0x80000000 {
123+
p.As = AORIS
124+
}
125+
p.Reg = REG_R0
126+
p.From.Offset >>= 16
127+
}
128+
116129
case AMOVD:
130+
// Skip this opcode if it is not a constant load.
131+
if p.From.Type != obj.TYPE_CONST || p.From.Name != obj.NAME_NONE || p.From.Reg != 0 {
132+
break
133+
}
134+
117135
// 32b constants (signed and unsigned) can be generated via 1 or 2 instructions. They can be assembled directly.
118136
isS32 := int64(int32(p.From.Offset)) == p.From.Offset
119137
isU32 := uint64(uint32(p.From.Offset)) == uint64(p.From.Offset)
120-
121138
// If prefixed instructions are supported, a 34b signed constant can be generated by one pli instruction.
122139
isS34 := pfxEnabled && (p.From.Offset<<30)>>30 == p.From.Offset
123-
if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && !isS32 && !isU32 && !isS34 {
124140

141+
// Try converting MOVD $const,Rx into ADDIS/ORIS $s32>>16,R0,Rx
142+
switch {
143+
case isS32 && p.From.Offset&0xFFFF == 0 && p.From.Offset != 0:
144+
p.As = AADDIS
145+
p.From.Offset >>= 16
146+
p.Reg = REG_R0
147+
148+
case isU32 && p.From.Offset&0xFFFF == 0 && p.From.Offset != 0:
149+
p.As = AORIS
150+
p.From.Offset >>= 16
151+
p.Reg = REG_R0
152+
153+
case isS32 || isU32 || isS34:
154+
// The assembler can generate this opcode in 1 (on Power10) or 2 opcodes.
155+
156+
// Otherwise, see if the large constant can be generated with 2 instructions. If not, load it from memory.
157+
default:
125158
// Is this a shifted 16b constant? If so, rewrite it to avoid a creating and loading a constant.
126159
val := p.From.Offset
127160
shift := bits.TrailingZeros64(uint64(val))
@@ -134,8 +167,8 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
134167
q.To = p.To
135168
p.From.Offset >>= shift
136169
p = q
137-
// Is this constant a mask value? If so, generate MOVD $-1, Rto; RLDIC Rto, ^me, mb, Rto
138170
} else if isPPC64DoublewordRotateMask(val) {
171+
// This constant is a mask value, generate MOVD $-1, Rto; RLDIC Rto, ^me, mb, Rto
139172
mb, me := encodePPC64RLDCMask(val)
140173
q := obj.Appendp(p, c.newprog)
141174
q.As = ARLDC
@@ -175,6 +208,29 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
175208
p.As = AADD
176209
}
177210

211+
// Rewrite ADD/OR/XOR/ANDCC $const,... forms into ADDIS/ORIS/XORIS/ANDISCC
212+
case AADD:
213+
// AADD can encode signed 34b values, ensure it is a valid signed 32b integer too.
214+
if p.From.Type == obj.TYPE_CONST && p.From.Offset&0xFFFF == 0 && int64(int32(p.From.Offset)) == p.From.Offset && p.From.Offset != 0 {
215+
p.As = AADDIS
216+
p.From.Offset >>= 16
217+
}
218+
case AOR:
219+
if p.From.Type == obj.TYPE_CONST && uint64(p.From.Offset)&0xFFFFFFFF0000FFFF == 0 && p.From.Offset != 0 {
220+
p.As = AORIS
221+
p.From.Offset >>= 16
222+
}
223+
case AXOR:
224+
if p.From.Type == obj.TYPE_CONST && uint64(p.From.Offset)&0xFFFFFFFF0000FFFF == 0 && p.From.Offset != 0 {
225+
p.As = AXORIS
226+
p.From.Offset >>= 16
227+
}
228+
case AANDCC:
229+
if p.From.Type == obj.TYPE_CONST && uint64(p.From.Offset)&0xFFFFFFFF0000FFFF == 0 && p.From.Offset != 0 {
230+
p.As = AANDISCC
231+
p.From.Offset >>= 16
232+
}
233+
178234
// To maintain backwards compatibility, we accept some 4 argument usage of
179235
// several opcodes which was likely not intended, but did work. These are not
180236
// added to optab to avoid the chance this behavior might be used with newer

test/codegen/mathbits.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,8 @@ func TrailingZeros16(n uint16) int {
340340
// arm:"ORR\t\\$65536","CLZ",-"MOVHU\tR"
341341
// arm64:"ORR\t\\$65536","RBITW","CLZW",-"MOVHU\tR",-"RBIT\t",-"CLZ\t"
342342
// s390x:"FLOGR","OR\t\\$65536"
343-
// ppc64x/power8:"POPCNTD","OR\\t\\$65536"
344-
// ppc64x/power9:"CNTTZD","OR\\t\\$65536"
343+
// ppc64x/power8:"POPCNTD","ORIS\\t\\$1"
344+
// ppc64x/power9:"CNTTZD","ORIS\\t\\$1"
345345
// wasm:"I64Ctz"
346346
return bits.TrailingZeros16(n)
347347
}

0 commit comments

Comments
 (0)