summaryrefslogtreecommitdiffhomepage
path: root/ir/be/beasm.c
diff options
context:
space:
mode:
authorChristoph Mallon <christoph.mallon@gmx.de>2018-07-20 21:58:49 +0200
committerChristoph Mallon <christoph.mallon@gmx.de>2018-07-20 22:50:14 +0200
commit1199038f60b922e9ea6446b459cf25a0b54809eb (patch)
tree179db88788abe882baebd6ff0c2c1c015cd3da8a /ir/be/beasm.c
parent01778cceafea83955d9ad7bff19babaf7e0a0747 (diff)
beasm: Remove inputs with matching outputs from early clobber handling.
This improves handling of early clobbers but still overestimates the register demand in other cases. This fixes x86code/early_clobber2.c.
Diffstat (limited to 'ir/be/beasm.c')
-rw-r--r--ir/be/beasm.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/ir/be/beasm.c b/ir/be/beasm.c
index a4d72c8..ff614f8 100644
--- a/ir/be/beasm.c
+++ b/ir/be/beasm.c
@@ -207,19 +207,35 @@ ir_node *be_make_asm(ir_node const *const node, be_asm_info_t const *const info,
/* Handle early clobbers. */
size_t const orig_n_ins = ARR_LEN(in_reqs);
+ size_t orig_n_outs = ARR_LEN(out_reqs);
ir_asm_constraint const *const constraints = get_ASM_constraints(node);
for (unsigned o = 0, n = get_ASM_n_constraints(node); o != n; ++o) {
ir_asm_constraint const *const constraint = &constraints[o];
if (strchr(get_id_str(constraint->constraint), '&')) {
- arch_register_req_t const **const oslot = &out_reqs[constraint->out_pos];
- arch_register_req_t const *const oreq = *oslot;
+ arch_register_req_t const **const oslot = &out_reqs[constraint->out_pos];
+ arch_register_req_t const *const oreq = *oslot;
+ arch_register_class_t const *const cls = oreq->cls;
unsigned different = 0;
+
+ /* Add each input in the same register class. */
for (unsigned i = 0; i != orig_n_ins; ++i) {
- if (in_reqs[i]->cls == oreq->cls)
+ if (in_reqs[i]->cls == cls)
different |= 1U << i;
}
+ /* Remove each input which has a matching output.
+ * The output already ensures that the register is different than the
+ * early clobber output. */
+ for (unsigned i = 0; i != orig_n_outs; ++i) {
+ arch_register_req_t const *const other_oreq = out_reqs[i];
+ if (other_oreq->cls == cls) {
+ unsigned const same_as = other_oreq->should_be_same;
+ assert(is_po2_or_zero(same_as));
+ different &= ~same_as;
+ }
+ }
+
if (different != 0) {
arch_register_req_t *const req = OALLOCZ(obst, arch_register_req_t);
*req = *oreq;
@@ -283,8 +299,8 @@ ir_node *be_make_asm(ir_node const *const node, be_asm_info_t const *const info,
* before...
* FIXME: need to do this per register class...
*/
- size_t const orig_n_outs = ARR_LEN(out_reqs);
- uint8_t add_pressure[ir_target.isa->n_register_classes];
+ orig_n_outs = ARR_LEN(out_reqs); // Clobbers might add further outputs.
+ uint8_t add_pressure[ir_target.isa->n_register_classes];
memset(add_pressure, 0, sizeof(add_pressure));
if (orig_n_outs < orig_n_ins) {
bitset_t *const used_ins = bitset_alloca(orig_n_ins);