summaryrefslogtreecommitdiffhomepage
path: root/ir/be/beasm.c
diff options
context:
space:
mode:
authorChristoph Mallon <mallon@cs.uni-saarland.de>2015-05-29 14:39:31 +0200
committerChristoph Mallon <mallon@cs.uni-saarland.de>2015-06-05 17:40:47 +0200
commit64a748df3508ba10300669157c8eb2a8778a0faf (patch)
tree750f6609ba575e788338c240711f78d508ec4476 /ir/be/beasm.c
parent091d358f462b68ac4b6e916057f966343ca1dcad (diff)
be: Move the code to try to make an asm node register pressure faithful into be_make_asm().
Now all users of be_make_asm() automatically use this logic.
Diffstat (limited to 'ir/be/beasm.c')
-rw-r--r--ir/be/beasm.c67
1 files changed, 66 insertions, 1 deletions
diff --git a/ir/be/beasm.c b/ir/be/beasm.c
index 266ea04..908f082 100644
--- a/ir/be/beasm.c
+++ b/ir/be/beasm.c
@@ -150,15 +150,80 @@ void be_parse_asm_constraints_internal(be_asm_constraint_t *const constraint, id
constraint->immediate_type = immediate_type;
}
+static bool can_match(arch_register_req_t const *const in, arch_register_req_t const *const out)
+{
+ if (in->cls != out->cls)
+ return false;
+ if (!arch_register_req_is(in, limited) ||
+ !arch_register_req_is(out, limited))
+ return true;
+ return (*in->limited & *out->limited) != 0;
+}
+
+static bool match_requirement(arch_register_req_t const **reqs, size_t const n_reqs, bitset_t *const used, arch_register_req_t const *const req)
+{
+ if (!req->cls)
+ return true;
+ for (size_t i = 0; i != n_reqs; ++i) {
+ if (bitset_is_set(used, i))
+ continue;
+ if (!can_match(req, reqs[i]))
+ continue;
+ bitset_set(used, i);
+ return true;
+ }
+ return false;
+}
+
ir_node *be_make_asm(ir_node const *const node, ir_node **in, arch_register_req_t const **in_reqs, arch_register_req_t const **out_reqs, void *const operands)
{
+ ir_node *const block = be_transform_nodes_block(node);
+
+ /* Attempt to make ASM node register pressure faithful.
+ * (This does not work for complicated cases yet!)
+ *
+ * Algorithm: Check if there are fewer inputs or outputs (I will call this
+ * the smaller list). Then try to match each constraint of the smaller list
+ * to 1 of the other list. If we can't match it, then we have to add a dummy
+ * input/output to the other list
+ *
+ * FIXME: This is still broken in lots of cases. But at least better than
+ * before...
+ * FIXME: need to do this per register class...
+ */
+ size_t const orig_n_ins = ARR_LEN(in_reqs);
+ size_t const orig_n_outs = ARR_LEN(out_reqs);
+ if (orig_n_outs < orig_n_ins) {
+ bitset_t *const used_ins = bitset_alloca(orig_n_ins);
+ for (size_t o = 0; o < orig_n_outs; ++o) {
+ arch_register_req_t const *const outreq = out_reqs[o];
+ if (match_requirement(in_reqs, orig_n_ins, used_ins, outreq))
+ continue;
+
+ /* add a new (dummy) input which occupies the register */
+ assert(arch_register_req_is(outreq, limited));
+ ARR_APP1(arch_register_req_t const*, in_reqs, outreq);
+ ARR_APP1(ir_node*, in, be_new_AnyVal(block, outreq->cls));
+ }
+ } else {
+ bitset_t *const used_outs = bitset_alloca(orig_n_outs);
+ for (unsigned i = 0; i < orig_n_ins; ++i) {
+ arch_register_req_t const *const inreq = in_reqs[i];
+ if (match_requirement(out_reqs, orig_n_outs, used_outs, inreq))
+ continue;
+
+ /* add a new (dummy) output which occupies the register */
+ assert(arch_register_req_is(inreq, limited));
+ ARR_APP1(arch_register_req_t const*, out_reqs, inreq);
+ }
+ }
+
/* Add memory input and output. */
ARR_APP1(ir_node*, in, be_transform_node(get_ASM_mem(node)));
ARR_APP1(arch_register_req_t const*, in_reqs, arch_no_register_req);
ARR_APP1(arch_register_req_t const*, out_reqs, arch_no_register_req);
dbg_info *const dbgi = get_irn_dbg_info(node);
- ir_node *const block = be_transform_nodes_block(node);
unsigned const n_ins = ARR_LEN(in);
unsigned const n_outs = ARR_LEN(out_reqs);
ident *const text = get_ASM_text(node);