diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2021-02-25 23:10:31 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2021-02-25 23:10:31 +0100 |
commit | 3d617353dda682db8b3eb6ea8c1fdfa89edfe5e2 (patch) | |
tree | 5b304807553a44b79ff430d838b1e1b9f72e10e7 | |
parent | 60c1f2706e30eacc29296e6cb5d9327c85a01340 (diff) | |
parent | 2f92df710ef708c5e5fabb551189213e9ad5127e (diff) | |
download | sparse-3d617353dda682db8b3eb6ea8c1fdfa89edfe5e2.tar.gz |
Merge branch 'asm-dom'
* asm: output *memory* operands need their address as *input*
* asm: teach dominates() about OP_ASM
-rw-r--r-- | flow.c | 17 | ||||
-rw-r--r-- | linearize.c | 63 | ||||
-rw-r--r-- | linearize.h | 2 | ||||
-rw-r--r-- | validation/linear/asm-out0.c | 25 | ||||
-rw-r--r-- | validation/mem2reg/asm-reload0.c | 14 |
5 files changed, 97 insertions, 24 deletions
@@ -490,12 +490,21 @@ static inline int distinct_symbols(pseudo_t a, pseudo_t b) */ int dominates(pseudo_t pseudo, struct instruction *insn, struct instruction *dom, int local) { - int opcode = dom->opcode; - - if (opcode == OP_CALL || opcode == OP_ENTRY) + switch (dom->opcode) { + case OP_CALL: case OP_ENTRY: return local ? 0 : -1; - if (opcode != OP_LOAD && opcode != OP_STORE) + case OP_LOAD: case OP_STORE: + break; + case OP_ASM: + if (dom->clobber_memory) + return -1; + if (dom->output_memory) + return -1; + return 0; + default: return 0; + } + if (dom->src != pseudo) { if (local) return 0; diff --git a/linearize.c b/linearize.c index 7a6f745f..0c9b0e59 100644 --- a/linearize.c +++ b/linearize.c @@ -2127,43 +2127,55 @@ static pseudo_t linearize_range(struct entrypoint *ep, struct statement *stmt) ALLOCATOR(asm_rules, "asm rules"); ALLOCATOR(asm_constraint, "asm constraints"); -static void add_asm_input(struct entrypoint *ep, struct instruction *insn, struct asm_operand *op) +static void add_asm_rule(struct instruction *insn, struct asm_constraint_list **list, struct asm_operand *op, pseudo_t pseudo) { - pseudo_t pseudo = linearize_expression(ep, op->expr); struct asm_constraint *rule = __alloc_asm_constraint(0); - + rule->is_memory = op->is_memory; rule->ident = op->name; rule->constraint = op->constraint ? op->constraint->string->data : ""; use_pseudo(insn, pseudo, &rule->pseudo); - add_ptr_list(&insn->asm_rules->inputs, rule); + add_ptr_list(list, rule); +} + +static void add_asm_input(struct entrypoint *ep, struct instruction *insn, struct asm_operand *op) +{ + pseudo_t pseudo = linearize_expression(ep, op->expr); + + add_asm_rule(insn, &insn->asm_rules->inputs, op, pseudo); +} + +static void add_asm_output_address(struct entrypoint *ep, struct instruction *insn, struct asm_operand *op) +{ + pseudo_t pseudo; + + if (!op->is_memory) + return; + + pseudo = linearize_expression(ep, op->expr); + add_asm_rule(insn, &insn->asm_rules->outputs, op, pseudo); + insn->output_memory = 1; } static void add_asm_output(struct entrypoint *ep, struct instruction *insn, struct asm_operand *op) { struct access_data ad = { NULL, }; pseudo_t pseudo; - struct asm_constraint *rule; - if (op->is_memory) { - pseudo = linearize_expression(ep, op->expr); - } else { - if (!linearize_address_gen(ep, op->expr, &ad)) - return; - pseudo = alloc_pseudo(insn); - linearize_store_gen(ep, pseudo, &ad); - } - rule = __alloc_asm_constraint(0); - rule->is_memory = op->is_memory; - rule->ident = op->name; - rule->constraint = op->constraint ? op->constraint->string->data : ""; - use_pseudo(insn, pseudo, &rule->pseudo); - add_ptr_list(&insn->asm_rules->outputs, rule); + if (op->is_memory) + return; + + if (!linearize_address_gen(ep, op->expr, &ad)) + return; + pseudo = alloc_pseudo(insn); + linearize_store_gen(ep, pseudo, &ad); + + add_asm_rule(insn, &insn->asm_rules->outputs, op, pseudo); } static pseudo_t linearize_asm_statement(struct entrypoint *ep, struct statement *stmt) { struct instruction *insn; - struct expression *expr; + struct expression *expr, *clob; struct asm_rules *rules; struct asm_operand *op; @@ -2183,6 +2195,11 @@ static pseudo_t linearize_asm_statement(struct entrypoint *ep, struct statement add_asm_input(ep, insn, op); } END_FOR_EACH_PTR(op); + /* ... and the addresses for memory outputs */ + FOR_EACH_PTR(stmt->asm_outputs, op) { + add_asm_output_address(ep, insn, op); + } END_FOR_EACH_PTR(op); + add_one_insn(ep, insn); /* Assign the outputs */ @@ -2190,6 +2207,12 @@ static pseudo_t linearize_asm_statement(struct entrypoint *ep, struct statement add_asm_output(ep, insn, op); } END_FOR_EACH_PTR(op); + /* and finally, look if it clobbers memory */ + FOR_EACH_PTR(stmt->asm_clobbers, clob) { + if (!strcmp(clob->string->data, "memory")) + insn->clobber_memory = 1; + } END_FOR_EACH_PTR(clob); + return VOID; } diff --git a/linearize.h b/linearize.h index a77e4b3e..cf0cf066 100644 --- a/linearize.h +++ b/linearize.h @@ -150,6 +150,8 @@ struct instruction { struct /* asm */ { const char *string; struct asm_rules *asm_rules; + int clobber_memory:1; + int output_memory:1; }; }; }; diff --git a/validation/linear/asm-out0.c b/validation/linear/asm-out0.c new file mode 100644 index 00000000..a8e0be69 --- /dev/null +++ b/validation/linear/asm-out0.c @@ -0,0 +1,25 @@ +static void asm_out0(void) +{ + int mem; + asm volatile ("[%1] <= 0" : "=m" (mem)); +} + +/* + * check-name: asm-out0 + * check-command: test-linearize -fdump-ir $file + * + * check-output-start +asm_out0: +.L0: + <entry-point> + symaddr.64 %r1 <- mem + asm "[%1] <= 0" + out: "=m" (%r1) + br .L1 + +.L1: + ret + + + * check-output-end + */ diff --git a/validation/mem2reg/asm-reload0.c b/validation/mem2reg/asm-reload0.c new file mode 100644 index 00000000..ce1829e0 --- /dev/null +++ b/validation/mem2reg/asm-reload0.c @@ -0,0 +1,14 @@ +static int asm_reload(void) +{ + int mem = 0; + asm volatile ("[%1] <= 1" : "=m" (mem)); + return mem; +} + +/* + * check-name: asm-reload0 + * check-command: test-linearize $file + * + * check-output-ignore + * check-output-contains: load\\. + */ |