Skip to content

Commit 6a42312

Browse files
committed
liblink, cmd/internal/obj: prefer positive immediates
Rewrite instructions that use negative immediates as the "negative" instruction variant with a positive operand. E.g. ADD $-2, R becomes SUB $2, R Updates golang#6
1 parent 076d34d commit 6a42312

File tree

4 files changed

+62
-2
lines changed

4 files changed

+62
-2
lines changed

src/cmd/internal/obj/arm64/asm7.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ func addpool(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
818818
so we need to know what to do with C_MOVCON.
819819
820820
The correct fix is to use the "negation" instruction variant,
821-
e.g. CMN $0, R instead of CMP $-1, R, or SUB $1, R instead
821+
e.g. CMN $1, R instead of CMP $-1, R, or SUB $1, R instead
822822
of ADD $-1, R. */
823823
case C_MOVCON,
824824

src/cmd/internal/obj/arm64/obj7.go

+31
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,17 @@ func settextflag(p *obj.Prog, f int) {
8888
p.Reg = uint8(f)
8989
}
9090

91+
var complements = []int16{
92+
AADD: ASUB,
93+
AADDW: ASUBW,
94+
ASUB: AADD,
95+
ASUBW: AADDW,
96+
ACMP: ACMN,
97+
ACMPW: ACMNW,
98+
ACMN: ACMP,
99+
ACMNW: ACMPW,
100+
}
101+
91102
func progedit(ctxt *obj.Link, p *obj.Prog) {
92103
var literal string
93104
var s *obj.LSym
@@ -142,6 +153,26 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
142153

143154
break
144155
}
156+
157+
// Rewrite negative immediates as positive immediates with
158+
// complementary instruction.
159+
switch p.As {
160+
161+
case AADD,
162+
AADDW,
163+
ASUB,
164+
ASUBW,
165+
ACMP,
166+
ACMPW,
167+
ACMN,
168+
ACMNW:
169+
if p.From.Type == D_CONST && p.From.Offset < 0 {
170+
p.From.Offset = -p.From.Offset
171+
p.As = complements[p.As]
172+
}
173+
174+
break
175+
}
145176
}
146177

147178
func follow(ctxt *obj.Link, s *obj.LSym) {

src/liblink/asm7.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,7 @@ addpool(Link *ctxt, Prog *p, Addr *a)
911911
so we need to know what to do with C_MOVCON.
912912
913913
The correct fix is to use the "negation" instruction variant,
914-
e.g. CMN $0, R instead of CMP $-1, R, or SUB $1, R instead
914+
e.g. CMN $1, R instead of CMP $-1, R, or SUB $1, R instead
915915
of ADD $-1, R. */
916916
case C_MOVCON:
917917

src/liblink/obj7.c

+29
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ settextflag(Prog *p, int f)
102102
p->reg = f;
103103
}
104104

105+
static short complements[] = {
106+
[AADD] ASUB,
107+
[AADDW] ASUBW,
108+
[ASUB] AADD,
109+
[ASUBW] AADDW,
110+
[ACMP] ACMN,
111+
[ACMPW] ACMNW,
112+
[ACMN] ACMP,
113+
[ACMNW] ACMPW,
114+
};
115+
105116
static void
106117
progedit(Link *ctxt, Prog *p)
107118
{
@@ -156,6 +167,24 @@ progedit(Link *ctxt, Prog *p)
156167
}
157168
break;
158169
}
170+
171+
// Rewrite negative immediates as positive immediates with
172+
// complementary instruction.
173+
switch(p->as) {
174+
case AADD:
175+
case AADDW:
176+
case ASUB:
177+
case ASUBW:
178+
case ACMP:
179+
case ACMPW:
180+
case ACMN:
181+
case ACMNW:
182+
if(p->from.type == D_CONST && p->from.offset < 0) {
183+
p->from.offset = -p->from.offset;
184+
p->as = complements[p->as];
185+
}
186+
break;
187+
}
159188
}
160189

161190
static void

0 commit comments

Comments
 (0)