fix killing OP_CAST & friends
commita903d3a56a9e0d51f2603815e5d2394b1c94c57a
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>
Sun, 29 Jan 2017 10:48:04 +0000 (29 11:48 +0100)
committerChristopher Li <sparse@chrisli.org>
Mon, 13 Feb 2017 01:34:45 +0000 (13 09:34 +0800)
tree3a77fef5fa1c956c6f064221e352325aa27f5fab
parente8cb94f5ecd7ecc5eae7e03c62cbcfe3886f96fb
fix killing OP_CAST & friends

Currently  kill_instruction() doesn't do anything with the
operands of casts instructions. But when theses instructions
are removed the operands 'usage' must be adjusted and this is
not done and as result the instructions producing the operands
of these casts are not optimized away as expected.

This patch fixes that by killing these casts the same way as others
unary instructions (OP_NOT & OP_NEG).

To illustrate the situation, the output of test-linearize
on the following code:
extern void __abort(void);
struct s {
int elem:3;
};
void foo(struct s *x);
void foo(struct s *x)
{
if (x->elem == 0) {
if (x->elem != 0 && x->elem != 1)
__abort();
}
}

gives this output without the patch:
foo:
load.32     %r2 <- 0[%arg1]
cast.32     %r3 <- (3) %r2
br          .L1
.L1:
ret

Since x->elem can't be at the same time == 0 & != 0, the inner if is never
true and the whole code should have been optimized away.
The 'cast' instruction is obviously not needed but nevertheless present.

With the patch, the output is much closer to what's expected:
foo:
load.32     %r2 <- 0[%arg1]
br          .L1
.L1:
ret

Note 1) The 'load' instruction is also dead but it's a separate problem.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
simplify.c
validation/kill-casts.c [new file with mode: 0644]