From a7318222f5fab499eaf482945c353b3cce517cd4 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sat, 20 Feb 2021 06:37:53 +0100 Subject: asm: add testcase for problem with output addresses The addresses needed by memory output operands are linearized (and placed) after the ASM instruction needing them. So, add a test case for this. Signed-off-by: Luc Van Oostenryck --- validation/linear/asm-out0.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 validation/linear/asm-out0.c diff --git a/validation/linear/asm-out0.c b/validation/linear/asm-out0.c new file mode 100644 index 00000000..64d154ed --- /dev/null +++ b/validation/linear/asm-out0.c @@ -0,0 +1,26 @@ +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-known-to-fail + * + * check-output-start +asm_out0: +.L0: + + symaddr.64 %r1 <- mem + asm "[%1] <= 0" + out: "=m" (%r1) + br .L1 + +.L1: + ret + + + * check-output-end + */ -- cgit 1.2.3-korg From efcf0db9d27ee1f463e1d6544bdaa7d0fd769778 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sat, 20 Feb 2021 06:48:29 +0100 Subject: asm: factor out add_asm_rule() from add_asm_{in,out}put() The functions add_asm_input() and add_asm_output() are very similar. So, factorize out the common part. Signed-off-by: Luc Van Oostenryck --- linearize.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/linearize.c b/linearize.c index 7a6f745f..6efa4749 100644 --- a/linearize.c +++ b/linearize.c @@ -2127,22 +2127,27 @@ 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(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); @@ -2152,12 +2157,8 @@ static void add_asm_output(struct entrypoint *ep, struct instruction *insn, stru 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); + + add_asm_rule(insn, &insn->asm_rules->outputs, op, pseudo); } static pseudo_t linearize_asm_statement(struct entrypoint *ep, struct statement *stmt) -- cgit 1.2.3-korg From 2494587e823700458923052b17b0b981be92d776 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sat, 20 Feb 2021 06:53:18 +0100 Subject: asm: output *memory* operands need their address as *input* The addresses needed by memory output operands are linearized (and placed) after the ASM instruction needing them. So, split add_asm_output() in 2 parts: one generating only the addresses for memory operands and called before issuing the body, and another one doing the usual copy of (non-memory) output operands back into their corresponding variables. Signed-off-by: Luc Van Oostenryck --- linearize.c | 31 +++++++++++++++++++++++-------- validation/linear/asm-out0.c | 1 - 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/linearize.c b/linearize.c index 6efa4749..33d641b4 100644 --- a/linearize.c +++ b/linearize.c @@ -2144,19 +2144,29 @@ static void add_asm_input(struct entrypoint *ep, struct instruction *insn, struc 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); +} + static void add_asm_output(struct entrypoint *ep, struct instruction *insn, struct asm_operand *op) { struct access_data ad = { NULL, }; pseudo_t pseudo; - 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); - } + 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); } @@ -2184,6 +2194,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 */ diff --git a/validation/linear/asm-out0.c b/validation/linear/asm-out0.c index 64d154ed..a8e0be69 100644 --- a/validation/linear/asm-out0.c +++ b/validation/linear/asm-out0.c @@ -7,7 +7,6 @@ static void asm_out0(void) /* * check-name: asm-out0 * check-command: test-linearize -fdump-ir $file - * check-known-to-fail * * check-output-start asm_out0: -- cgit 1.2.3-korg From 8af0e8a2ebcf53dde914c9e84f09bc0c46d73d81 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sat, 20 Feb 2021 06:26:59 +0100 Subject: reorg dominates() To prepare the handling of OP_ASM instructions, reorganize the opcode tests to use a switch. Signed-off-by: Luc Van Oostenryck --- flow.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/flow.c b/flow.c index bda277aa..5751ce75 100644 --- a/flow.c +++ b/flow.c @@ -490,12 +490,15 @@ 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; + default: return 0; + } + if (dom->src != pseudo) { if (local) return 0; -- cgit 1.2.3-korg From d7361313e11c698f5aef4ab5c9bc6ea90bdb58c9 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sun, 21 Feb 2021 10:24:33 +0100 Subject: asm-mem: add testcase for missing reload after asm memops Memory simplification is done with the help of the function dominates() which determine when memory instructions interfere. This function handles OP_CALLs, OP_LOADs and OP_STOREs but memory can also be changed via OP_ASMs. Add a testcase showing this. Signed-off-by: Luc Van Oostenryck --- validation/mem2reg/asm-reload0.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 validation/mem2reg/asm-reload0.c diff --git a/validation/mem2reg/asm-reload0.c b/validation/mem2reg/asm-reload0.c new file mode 100644 index 00000000..c9e297dd --- /dev/null +++ b/validation/mem2reg/asm-reload0.c @@ -0,0 +1,15 @@ +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-known-to-fail + * + * check-output-ignore + * check-output-contains: load\\. + */ -- cgit 1.2.3-korg From 34c57a7f73e14095364a8863070f8e8c9f62cdc4 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sat, 20 Feb 2021 10:04:34 +0100 Subject: asm-mem: does it clobber memory? An asm statement can specify that it clobbers memory. Add this info directly in the corresponding instruction, avoiding the need to scan the clobber list each time. Signed-off-by: Luc Van Oostenryck --- linearize.c | 8 +++++++- linearize.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/linearize.c b/linearize.c index 33d641b4..4140b60c 100644 --- a/linearize.c +++ b/linearize.c @@ -2174,7 +2174,7 @@ static void add_asm_output(struct entrypoint *ep, struct instruction *insn, stru 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; @@ -2206,6 +2206,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..fb513276 100644 --- a/linearize.h +++ b/linearize.h @@ -150,6 +150,7 @@ struct instruction { struct /* asm */ { const char *string; struct asm_rules *asm_rules; + int clobber_memory:1; }; }; }; -- cgit 1.2.3-korg From d6721b38b376e881b4aaf8a35eda4af45740245a Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sat, 20 Feb 2021 10:08:06 +0100 Subject: asm-mem: does it output to memory? If an asm statement have a memory output operand, it modifies memory. Since this information is needed during memops simplification, add this info directly in the corresponding instruction, avoiding the need to scan the output operands list each time. Signed-off-by: Luc Van Oostenryck --- linearize.c | 1 + linearize.h | 1 + 2 files changed, 2 insertions(+) diff --git a/linearize.c b/linearize.c index 4140b60c..0c9b0e59 100644 --- a/linearize.c +++ b/linearize.c @@ -2153,6 +2153,7 @@ static void add_asm_output_address(struct entrypoint *ep, struct instruction *in 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) diff --git a/linearize.h b/linearize.h index fb513276..cf0cf066 100644 --- a/linearize.h +++ b/linearize.h @@ -151,6 +151,7 @@ struct instruction { const char *string; struct asm_rules *asm_rules; int clobber_memory:1; + int output_memory:1; }; }; }; -- cgit 1.2.3-korg From 2f92df710ef708c5e5fabb551189213e9ad5127e Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Sat, 20 Feb 2021 06:27:31 +0100 Subject: asm-mem: teach dominates() about OP_ASM The function dominates() needs to know if an OP_ASM instruction may modify. Use the information now available in the instruction to return the answer. Signed-off-by: Luc Van Oostenryck --- flow.c | 6 ++++++ validation/mem2reg/asm-reload0.c | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/flow.c b/flow.c index 5751ce75..5d630187 100644 --- a/flow.c +++ b/flow.c @@ -495,6 +495,12 @@ int dominates(pseudo_t pseudo, struct instruction *insn, struct instruction *dom return local ? 0 : -1; 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; } diff --git a/validation/mem2reg/asm-reload0.c b/validation/mem2reg/asm-reload0.c index c9e297dd..ce1829e0 100644 --- a/validation/mem2reg/asm-reload0.c +++ b/validation/mem2reg/asm-reload0.c @@ -8,7 +8,6 @@ static int asm_reload(void) /* * check-name: asm-reload0 * check-command: test-linearize $file - * check-known-to-fail * * check-output-ignore * check-output-contains: load\\. -- cgit 1.2.3-korg