When an instruction is replaced by a pseudo, the 'usage' of its operands should be removed too but it's not the case. The fix consists in calling kill_use() for each operands after the pseudo is replaced. Not all types of instruction are considered, only those which can be replaced by a pseudo. The following example illustrate the situation. When looking at the output of test-linearize, the following function: static int kill_add(int a, int b) { return (a + b) && 0; } without the patch, gives this output: kill_add: add.32 %r3 <- %arg1, %arg2 ret.32 $0 The 'add' instruction is obviously unneeded but nevertheless present. Before any optimization the code was something like: kill_add: add.32 %r3 <- %arg1, %arg2 and_bool.32 %r4 <- %r3, $0 ret.32 %r4 During the simplification phase, the result of the 'and' instruction (%r4) have been replaced by '0' and the instruction itself is discarded. But '%r3' usage has not been adjusted and the further phases are not aware that '%r3' is not needed anymore and so the 'add' instruction is kept while not needed by anything. With the patch the 'add' instruction is correctly discarded, giving the expected output: kill_add: ret.32 $0 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- simplify.c | 20 +++++++++++++++ validation/kill-replaced-insn.c | 54 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 validation/kill-replaced-insn.c diff --git a/simplify.c b/simplify.c index 3dea03b5e..ed41e441a 100644 --- a/simplify.c +++ b/simplify.c @@ -253,6 +253,26 @@ static inline int constant(pseudo_t pseudo) static int replace_with_pseudo(struct instruction *insn, pseudo_t pseudo) { convert_instruction_target(insn, pseudo); + + switch (insn->opcode) { + case OP_SEL: + case OP_RANGE: + kill_use(&insn->src3); + case OP_BINARY ... OP_BINCMP_END: + kill_use(&insn->src2); + case OP_NOT: + case OP_NEG: + case OP_SYMADDR: + case OP_CAST: + case OP_SCAST: + case OP_FPCAST: + case OP_PTRCAST: + kill_use(&insn->src1); + break; + + default: + assert(0); + } insn->bb = NULL; return REPEAT_CSE; } diff --git a/validation/kill-replaced-insn.c b/validation/kill-replaced-insn.c new file mode 100644 index 000000000..be031b6c1 --- /dev/null +++ b/validation/kill-replaced-insn.c @@ -0,0 +1,54 @@ +// See if the replaced operation is effectively killed or not + +static int kill_add(int a, int b) +{ + return (a + b) && 0; +} + +static int kill_scast(short a) +{ + return ((int) a) && 0; +} + +static int kill_ucast(unsigned char a) +{ + return ((int) a) && 0; +} + +static int kill_pcast(int *a) +{ + return ((void*) a) && 0; +} + +static int kill_fcast(double a) +{ + return ((int) a) && 0; +} + +static int kill_select(int a) +{ + return (a ? 1 : 0) && 0; +} + +static int kill_load(int *a) +{ + return *a && 0; +} + +static int kill_store(int *a) +{ + return (*a = 1) && 0; +} + +/* + * check-name: kill-replaced-insn + * check-command: test-linearize $file + * + * check-output-ignore + * check-output-excludes: add\\. + * check-output-excludes: scast\\. + * check-output-excludes: \\<cast\\. + * check-output-excludes: ptrcast\\. + * check-output-excludes: fpcast\\. + * check-output-excludes: sel\\. + */ -- 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