4 memarg(Ref
*r
, int op
, Ins
*i
)
6 if (isload(op
) || op
== Ocall
)
7 return r
== &i
->arg
[0];
9 return r
== &i
->arg
[1];
14 immarg(Ref
*r
, int op
, Ins
*i
)
16 return rv64_op
[op
].imm
&& r
== &i
->arg
[1];
20 fixarg(Ref
*r
, int k
, Ins
*i
, Fn
*fn
)
28 op
= i
? i
->op
: Ocopy
;
32 if (c
->type
== CAddr
&& memarg(r
, op
, i
))
34 if (c
->type
== CBits
&& immarg(r
, op
, i
))
35 if (-2048 <= c
->bits
.i
&& c
->bits
.i
< 2048)
37 r1
= newtmp("isel", k
, fn
);
39 /* load floating points from memory
40 * slots, they can't be used as
43 assert(c
->type
== CBits
);
44 n
= stashbits(&c
->bits
, KWIDE(k
) ? 8 : 4);
45 vgrow(&fn
->con
, ++fn
->ncon
);
46 c
= &fn
->con
[fn
->ncon
-1];
47 sprintf(buf
, "\"%sfp%d\"", T
.asloc
, n
);
48 *c
= (Con
){.type
= CAddr
};
49 c
->sym
.id
= intern(buf
);
50 emit(Oload
, k
, r1
, CON(c
-fn
->con
), R
);
53 emit(Ocopy
, k
, r1
, r0
, R
);
58 s
= fn
->tmp
[r0
.val
].slot
;
60 /* aggregate passed by value on
61 * stack, or fast local address,
62 * replace with slot if we can
64 if (memarg(r
, op
, i
)) {
68 r1
= newtmp("isel", k
, fn
);
69 emit(Oaddr
, k
, r1
, SLOT(s
), R
);
72 if (k
== Kw
&& fn
->tmp
[r0
.val
].cls
== Kl
) {
73 /* TODO: this sign extension isn't needed
74 * for 32-bit arithmetic instructions
76 r1
= newtmp("isel", k
, fn
);
77 emit(Oextsw
, Kl
, r1
, r0
, R
);
79 assert(k
== fn
->tmp
[r0
.val
].cls
);
87 negate(Ref
*pr
, Fn
*fn
)
91 r
= newtmp("isel", Kw
, fn
);
92 emit(Oxor
, Kw
, *pr
, r
, getcon(1, fn
));
97 selcmp(Ins i
, int k
, int op
, Fn
*fn
)
105 r
= newtmp("isel", k
, fn
);
106 emit(Oreqz
, i
.cls
, i
.to
, r
, R
);
107 emit(Oxor
, k
, r
, i
.arg
[0], i
.arg
[1]);
109 fixarg(&icmp
->arg
[0], k
, icmp
, fn
);
110 fixarg(&icmp
->arg
[1], k
, icmp
, fn
);
113 r
= newtmp("isel", k
, fn
);
114 emit(Ornez
, i
.cls
, i
.to
, r
, R
);
115 emit(Oxor
, k
, r
, i
.arg
[0], i
.arg
[1]);
117 fixarg(&icmp
->arg
[0], k
, icmp
, fn
);
118 fixarg(&icmp
->arg
[1], k
, icmp
, fn
);
120 case Cisge
: sign
= 1, swap
= 0, neg
= 1; break;
121 case Cisgt
: sign
= 1, swap
= 1, neg
= 0; break;
122 case Cisle
: sign
= 1, swap
= 1, neg
= 1; break;
123 case Cislt
: sign
= 1, swap
= 0, neg
= 0; break;
124 case Ciuge
: sign
= 0, swap
= 0, neg
= 1; break;
125 case Ciugt
: sign
= 0, swap
= 1, neg
= 0; break;
126 case Ciule
: sign
= 0, swap
= 1, neg
= 1; break;
127 case Ciult
: sign
= 0, swap
= 0, neg
= 0; break;
139 r0
= newtmp("isel", i
.cls
, fn
);
140 r1
= newtmp("isel", i
.cls
, fn
);
141 emit(Oand
, i
.cls
, i
.to
, r0
, r1
);
142 op
= KWIDE(k
) ? Oceqd
: Oceqs
;
143 emit(op
, i
.cls
, r0
, i
.arg
[0], i
.arg
[0]);
145 fixarg(&icmp
->arg
[0], k
, icmp
, fn
);
146 fixarg(&icmp
->arg
[1], k
, icmp
, fn
);
147 emit(op
, i
.cls
, r1
, i
.arg
[1], i
.arg
[1]);
149 fixarg(&icmp
->arg
[0], k
, icmp
, fn
);
150 fixarg(&icmp
->arg
[1], k
, icmp
, fn
);
154 i
.op
= KWIDE(k
) ? Oceqd
: Oceqs
;
157 assert(0 && "unknown comparison");
160 i
.op
= sign
? Ocsltl
: Ocultl
;
170 fixarg(&icmp
->arg
[0], k
, icmp
, fn
);
171 fixarg(&icmp
->arg
[1], k
, icmp
, fn
);
180 if (INRANGE(i
.op
, Oalloc
, Oalloc1
)) {
182 salloc(i
.to
, i
.arg
[0], fn
);
183 fixarg(&i0
->arg
[0], Kl
, i0
, fn
);
186 if (iscmp(i
.op
, &ck
, &cc
)) {
187 selcmp(i
, ck
, cc
, fn
);
192 i0
= curi
; /* fixarg() can change curi */
193 fixarg(&i0
->arg
[0], argcls(&i
, 0), i0
, fn
);
194 fixarg(&i0
->arg
[1], argcls(&i
, 1), i0
, fn
);
199 seljmp(Blk
*b
, Fn
*fn
)
201 /* TODO: replace cmp+jnz with beq/bne/blt[u]/bge[u] */
202 if (b
->jmp
.type
== Jjnz
)
203 fixarg(&b
->jmp
.arg
, Kw
, 0, fn
);
216 /* assign slots to fast allocs */
218 /* specific to NAlign == 3 */ /* or change n=4 and sz /= 4 below */
219 for (al
=Oalloc
, n
=4; al
<=Oalloc1
; al
++, n
*=2)
220 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++)
222 if (rtype(i
->arg
[0]) != RCon
)
224 sz
= fn
->con
[i
->arg
[0].val
].bits
.i
;
225 if (sz
< 0 || sz
>= INT_MAX
-15)
226 err("invalid alloc size %"PRId64
, sz
);
227 sz
= (sz
+ n
-1) & -n
;
229 if (sz
> INT_MAX
- fn
->slot
)
230 die("alloc too large");
231 fn
->tmp
[i
->to
.val
].slot
= fn
->slot
;
233 *i
= (Ins
){.op
= Onop
};
236 for (b
=fn
->start
; b
; b
=b
->link
) {
238 for (sb
=(Blk
*[3]){b
->s1
, b
->s2
, 0}; *sb
; sb
++)
239 for (p
=(*sb
)->phi
; p
; p
=p
->link
) {
240 for (n
=0; p
->blk
[n
] != b
; n
++)
241 assert(n
+1 < p
->narg
);
242 fixarg(&p
->arg
[n
], p
->cls
, 0, fn
);
245 for (i
=&b
->ins
[b
->nins
]; i
!=b
->ins
;)
247 b
->nins
= &insb
[NIns
] - curi
;
248 idup(&b
->ins
, curi
, b
->nins
);
252 fprintf(stderr
, "\n> After instruction selection:\n");