summaryrefslogtreecommitdiffhomepage
path: root/ir/be
diff options
context:
space:
mode:
authorChristoph Mallon <christoph.mallon@gmx.de>2019-03-22 23:37:49 +0100
committerChristoph Mallon <christoph.mallon@gmx.de>2019-03-24 08:13:29 +0100
commitf6e223b6d1711cc4e58d0248f5b22a3d5cc79fd2 (patch)
tree1d70c1a3f871ef47d08baa2280bf7ac1b8e729ea /ir/be
parent3569ffd30ee6608a0f8466415600c57d4c6102a7 (diff)
be: Refine modelling of additional register pressure.
Now additional pressure is applied to the register pressure either before (positive value) or after (negative value) the instruction. So far the value was applied to both the register pressure before and after the instruction. This leads to overapproximation, e.g. for cltd (in: eax, out: edx). When the input lives through then the register pressure after the instruction is 2, but +1 additional pressure unnecessarily increases it to 3. Now the additional pressure is applied to either the register pressure before or after the instruction. For cltd applying it only before the instruction is optimal, because the output can never be paired with the input. Typical symptom was overspilling around cltd+idiv. This still can overapproximate the actual register demand when in/out pairing depends on whether an input lives through. E.g. in: eax+reg, out: edx. Then 3 registers are needed when the reg input lives through. (additional pressure before 1) But only 2 registers are needed when the reg input dies. (no additional pressure) This fixes lit/overspill_cltd.c.
Diffstat (limited to 'ir/be')
-rw-r--r--ir/be/be_types.h4
-rw-r--r--ir/be/beasm.c2
-rw-r--r--ir/be/bedump.c5
-rw-r--r--ir/be/bespillbelady.c4
-rw-r--r--ir/be/bespilldaemel.c7
-rw-r--r--ir/be/ia32/ia32_transform.c2
6 files changed, 15 insertions, 9 deletions
diff --git a/ir/be/be_types.h b/ir/be/be_types.h
index ee44fb6..fe04dbd 100644
--- a/ir/be/be_types.h
+++ b/ir/be/be_types.h
@@ -63,6 +63,8 @@ typedef struct regalloc_if_t regalloc_if_t;
typedef struct be_register_name_t be_register_name_t;
-typedef uint8_t be_add_pressure_t;
+/** Additional register pressure applied to before (positive value) or after
+ * (negative value) a instruction. */
+typedef int8_t be_add_pressure_t;
#endif
diff --git a/ir/be/beasm.c b/ir/be/beasm.c
index c13a458..150f238 100644
--- a/ir/be/beasm.c
+++ b/ir/be/beasm.c
@@ -324,7 +324,7 @@ ir_node *be_make_asm(ir_node const *const node, be_asm_info_t const *const info,
if (!inreq->cls->manual_ra) {
assert(inreq->cls->index < ARRAY_SIZE(add_pressure));
if (!match_requirement(out_reqs, n_outs, used_outs, inreq))
- add_pressure[inreq->cls->index]++;
+ add_pressure[inreq->cls->index]--;
}
}
}
diff --git a/ir/be/bedump.c b/ir/be/bedump.c
index 742edbb..9ba98c5 100644
--- a/ir/be/bedump.c
+++ b/ir/be/bedump.c
@@ -248,8 +248,9 @@ void be_dump_reqs_and_registers(FILE *const F, ir_node const *const node)
for (size_t i = 0; i != ARRAY_SIZE(info->add_pressure); ++i) {
be_add_pressure_t const add = info->add_pressure[i];
if (add != 0) {
- char const *const name = ir_target.isa->register_classes[i].name;
- fprintf(F, "additional pressure %s = %d\n", name, add);
+ char const *const name = ir_target.isa->register_classes[i].name;
+ char const *const where = add > 0 ? "before" : "after";
+ fprintf(F, "additional pressure %s = %d %s\n", name, abs(add), where);
}
}
diff --git a/ir/be/bespillbelady.c b/ir/be/bespillbelady.c
index d27ec8c..7db98c1 100644
--- a/ir/be/bespillbelady.c
+++ b/ir/be/bespillbelady.c
@@ -687,7 +687,7 @@ static void process_block(ir_node *block)
workset_insert(new_vals, in, false);
);
be_add_pressure_t const add_pressure = arch_get_additional_pressure(irn, cls);
- displace(new_vals, true, irn, add_pressure);
+ displace(new_vals, true, irn, MAX(add_pressure, 0));
/* allocate all values _defined_ by this instruction */
workset_clear(new_vals);
@@ -695,7 +695,7 @@ static void process_block(ir_node *block)
assert(req->width == 1);
workset_insert(new_vals, value, false);
);
- displace(new_vals, false, irn, add_pressure);
+ displace(new_vals, false, irn, MAX(-add_pressure, 0));
}
/* Remember end-workset for this block */
diff --git a/ir/be/bespilldaemel.c b/ir/be/bespilldaemel.c
index 6b8b826..c872f09 100644
--- a/ir/be/bespilldaemel.c
+++ b/ir/be/bespilldaemel.c
@@ -138,12 +138,15 @@ static void do_spilling(ir_nodeset_t *live_nodes, ir_node *node)
}
);
+ /* we may need additional free registers */
+ be_add_pressure_t const add_pressure = arch_get_additional_pressure(node, cls);
+ free_regs_needed += MAX( add_pressure, 0);
+ values_defined += MAX(-add_pressure, 0);
+
/* we can reuse all reloaded values for the defined values, but we might
* need even more registers */
if (values_defined > free_regs_needed)
free_regs_needed = values_defined;
- /* we may need additional free registers */
- free_regs_needed += arch_get_additional_pressure(node, cls);
size_t n_live_nodes = ir_nodeset_size(live_nodes);
int spills_needed = (n_live_nodes + free_regs_needed) - n_regs;
diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c
index 05f1971..a8b8a44 100644
--- a/ir/be/ia32/ia32_transform.c
+++ b/ir/be/ia32/ia32_transform.c
@@ -4669,7 +4669,7 @@ static ir_node *gen_Call(ir_node *node)
in_req[goti] = &ia32_single_reg_req_gp_ebx;
/* We cannot pair up the "ebx" with any output, causing additional
* register pressure */
- ++add_pressure;
+ --add_pressure;
}
assert(in_arity == n_ins);
assert(sync_arity <= n_params + 1);