There is essentially three cases where kill_instruction() is called: 1) when implicitely removing an instruction via kill_use()/remove_usage() once all users of (the target of) this instruction have been removed and so this instruction become unneeded. 2) when explicitely removing a specific instruction. 3) when explicitely removing all instructions in a basic block because it became unreachable. For 'pure' instructions, like the arithmetic operators, these three cases can be handled exactly the same but for instructions having side-effects, special care is needed. For them case 1) should do nothing while cases 2) & 3) should remove the instruction and adjust the usage of its operands like for normal instructions. To handle this gracefully: - rename kill_instruction() into kill_insn() - add a new argument ('force') to kill_insn() - create kill_instruction() & kill_instruction_force() as inline functions calling kill_insn() with 'force' set respectively to 0 & 1. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- flow.c | 3 +-- flow.h | 11 ++++++++++- simplify.c | 11 ++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/flow.c b/flow.c index ef07b6db9..8409fac60 100644 --- a/flow.c +++ b/flow.c @@ -759,13 +759,12 @@ void kill_bb(struct basic_block *bb) struct basic_block *child, *parent; FOR_EACH_PTR(bb->insns, insn) { - kill_instruction(insn); + kill_instruction_force(insn); kill_defs(insn); /* * We kill unreachable instructions even if they * otherwise aren't "killable" (e.g. volatile loads) */ - insn->bb = NULL; } END_FOR_EACH_PTR(insn); bb->insns = NULL; diff --git a/flow.h b/flow.h index 370aaddf1..31ed80d40 100644 --- a/flow.h +++ b/flow.h @@ -23,9 +23,18 @@ extern int simplify_instruction(struct instruction *); extern void kill_bb(struct basic_block *); extern void kill_use(pseudo_t *); -extern void kill_instruction(struct instruction *); extern void kill_unreachable_bbs(struct entrypoint *ep); +extern void kill_insn(struct instruction *, int force); +static inline void kill_instruction(struct instruction *insn) +{ + kill_insn(insn, 0); +} +static inline void kill_instruction_force(struct instruction *insn) +{ + kill_insn(insn, 1); +} + void check_access(struct instruction *insn); void convert_load_instruction(struct instruction *, pseudo_t); void rewrite_load_instruction(struct instruction *, struct pseudo_list *); diff --git a/simplify.c b/simplify.c index 1fbad1060..b8944f0f7 100644 --- a/simplify.c +++ b/simplify.c @@ -182,7 +182,16 @@ static void kill_use_list(struct pseudo_list *list) } END_FOR_EACH_PTR(p); } -void kill_instruction(struct instruction *insn) +/* + * kill an instruction: + * - remove it from its bb + * - remove the usage of all its operands + * If forse is zero, the normal case, the function only for + * instructions free of (possible) side-effects. Otherwise + * the function does that unconditionally (must only be used + * for unreachable instructions. + */ +void kill_insn(struct instruction *insn, int force) { if (!insn || !insn->bb) return; -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html