Commit c23ab8cd authored by Matthias Braun's avatar Matthias Braun
Browse files

bearch: Introduce kills_value constraint and use it for ia32_fisttp

The kills value constraint indicated that the value in a register is
modified after it is read. A copy is inserted if the value is still
required after a kills_value use.
parent 24512e42
......@@ -222,6 +222,9 @@ struct arch_register_req_t {
bool ignore : 1;
/** The registernumber should be aligned (in case of multiregister values)*/
bool aligned : 1;
/** The instructions modifies the value in the register in an unknown way,
* the value has to be copied if it is needed afterwards. */
bool kills_value : 1;
};
static inline bool reg_reqs_equal(const arch_register_req_t *req1,
......
......@@ -167,6 +167,8 @@ static void dump_register_req(FILE *const F, arch_register_req_t const *const re
fputs(" aligned", F);
if (req->ignore)
fputs(" ignore", F);
if (req->kills_value)
fputs(" kills_value", F);
}
static void dump_req_reg(FILE *const F, char const *const ctx, unsigned const idx, arch_register_req_t const *const req, arch_register_t const *const reg)
......
......@@ -770,9 +770,6 @@ static void prepare_constr_insn(ir_node *const node)
rbitset_set(def_constr, reg->global_index);
}
);
/* no output constraints => we're good */
if (def_constr == NULL)
return;
/* Insert copies for all constrained arguments living through the node and
* being constrained to a register which also occurs in out constraints. */
......@@ -783,25 +780,33 @@ static void prepare_constr_insn(ir_node *const node)
* 3) is constrained to a register occurring in out constraints. */
const arch_register_req_t *const req
= arch_get_irn_register_req_in(node, i);
if (req->limited == NULL)
continue;
ir_node *in = get_irn_n(node, i);
const arch_register_req_t *const in_req = arch_get_irn_register_req(in);
if (in_req->ignore)
continue;
if (!be_value_live_after(in, node))
continue;
ir_node *const in = get_irn_n(node, i);
if (req->kills_value) {
/* we need a copy */
} else {
if (def_constr == NULL || req->limited == NULL)
continue;
if (!req->kills_value) {
const arch_register_req_t *const in_req
= arch_get_irn_register_req(in);
if (in_req->ignore)
continue;
}
bool common_limits = false;
arch_register_class_t const *const cls = req->cls;
rbitset_foreach(req->limited, cls->n_regs, e) {
const arch_register_t *reg = arch_register_for_index(cls, e);
if (rbitset_is_set(def_constr, reg->global_index)) {
common_limits = true;
break;
bool common_limits = false;
arch_register_class_t const *const cls = req->cls;
rbitset_foreach(req->limited, cls->n_regs, e) {
const arch_register_t *reg = arch_register_for_index(cls, e);
if (rbitset_is_set(def_constr, reg->global_index)) {
common_limits = true;
break;
}
}
if (!common_limits)
continue;
}
if (!common_limits)
if (!be_value_live_after(in, node))
continue;
/* TODO: This is suboptimal, we should rather have the node use the old
......
......@@ -1617,10 +1617,10 @@ fist => {
fisttp => {
op_flags => [ "uses_memory", "fragile" ],
state => "exc_pinned",
in_reqs => [ "gp", "gp", "mem", "fp" ],
out_reqs => [ "mem", "exec", "exec", "in_r3" ],
in_reqs => [ "gp", "gp", "mem", "fp:K" ],
out_reqs => [ "mem", "exec", "exec" ],
ins => [ "base", "index", "mem", "val" ],
outs => [ "M", "X_regular", "X_except", "res" ],
outs => [ "M", "X_regular", "X_except" ],
emit => "fisttp%FM %AM",
latency => 4,
attr_type => "ia32_x87_attr_t",
......
......@@ -886,9 +886,7 @@ static void sim_fisttp(x87_state *state, ir_node *n)
ir_node *const val = get_irn_n(n, n_ia32_fisttp_val);
DB((dbg, LEVEL_1, ">>> %+F %s ->\n", n, arch_get_irn_register(val)->name));
/* Note: although the value is still live here, it is destroyed because
* of the pop. The register allocator is aware of that and introduced a copy
* if the value must be alive. */
assert(!is_fp_live(val, fp_live_args_after(state->sim, n, 0)));
/* we can only store the tos to memory */
move_to_tos(state, n, val);
......
......@@ -875,7 +875,9 @@ sub generate_requirements
if (defined($flags)) {
foreach my $f (split(/\|/, $flags)) {
if ($f eq "I") {
$extra .= "\n\t.ignore = true,";
$extra .= "\n\t.ignore = true,";
} elsif ($f eq "K") {
$extra .= "\n\t.kills_value = true,";
} elsif ($f eq "a") {
$extra .= "\n\t.aligned = true,";
} elsif ($f eq "2" or $f eq "4" or $f eq "8") {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment