diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-11-25 22:46:22 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-11-27 22:17:37 +0100 |
commit | 2eb69efa7f912e604092b46d7b12a9bce3ea9995 (patch) | |
tree | d7e4de407a26032c8e5d514b28402d9320bf9c68 | |
parent | 3aaa16eac7f07302bcf3d733aeee901d378b7e9d (diff) | |
download | sparse-2eb69efa7f912e604092b46d7b12a9bce3ea9995.tar.gz |
factorize SEL(x, OP(y,z), y) into OP(SEL(x, z, 0), y)
'Factorize' and expression like:
x ? (y | z) : y;
into
(x ? z : 0) | y;
and some positional variants as well as replacing '|' by '+' or '^'.
Note: it's not very clear if this is really an improvement but it
allows some very nice simplification of 'bits translations'.
Note: the same can be done for others operations, for example it can
be done for '&' if '0' (the neuter value for '|', '+' and '^')
by '~0' (same with '*' and '1').
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | simplify.c | 40 | ||||
-rw-r--r-- | validation/optim/fact-select01.c | 1 |
2 files changed, 40 insertions, 1 deletions
@@ -554,6 +554,16 @@ static inline int swap_insn(struct instruction *out, struct instruction *in, pse return replace_insn_pair(out, in->opcode, in, out->opcode, a, b, c); } +/// +// create an instruction pair OUT(SELECT(a, b, c), d) +static int swap_select(struct instruction *out, struct instruction *in, pseudo_t a, pseudo_t b, pseudo_t c, pseudo_t d) +{ + use_pseudo(in, c, &in->src3); + swap_insn(out, in, a, b, d); + kill_use(&out->src3); + return REPEAT_CSE; +} + static inline int def_opcode(pseudo_t p) { if (p->type != PSEUDO_REG) @@ -2254,6 +2264,36 @@ static int simplify_select(struct instruction *insn) } break; } + + switch (DEF_OPCODE(def, src1)) { + case OP_ADD: case OP_OR: case OP_XOR: + if ((def->src1 == src2) && can_move_to(cond, def)) { + // SEL(x, OP(y,z), y) --> OP(SEL(x, z, 0), y) + swap_select(insn, def, cond, def->src2, value_pseudo(0), src2); + return REPEAT_CSE; + } + if ((def->src2 == src2) && can_move_to(cond, def)) { + // SEL(x, OP(z,y), y) --> OP(SEL(x, z, 0), y) + swap_select(insn, def, cond, def->src1, value_pseudo(0), src2); + return REPEAT_CSE; + } + break; + } + + switch (DEF_OPCODE(def, src2)) { + case OP_ADD: case OP_OR: case OP_XOR: + if ((def->src1 == src1) && can_move_to(cond, def)) { + // SEL(x, y, OP(y,z)) --> OP(SEL(x, 0, z), y) + swap_select(insn, def, cond, value_pseudo(0), def->src2, src1); + return REPEAT_CSE; + } + if ((def->src2 == src1) && can_move_to(cond, def)) { + // SEL(x, y, OP(z,y)) --> OP(SEL(x, 0, z), y) + swap_select(insn, def, cond, value_pseudo(0), def->src1, src1); + return REPEAT_CSE; + } + break; + } return 0; } diff --git a/validation/optim/fact-select01.c b/validation/optim/fact-select01.c index ef4e5e89..9232fc90 100644 --- a/validation/optim/fact-select01.c +++ b/validation/optim/fact-select01.c @@ -19,7 +19,6 @@ int xor_y_yx(int p, int x, int y) { return (p ? y : (y^x)) == ((p ? 0 : x) ^ y); /* * check-name: fact-select01 * check-command: test-linearize -Wno-decl $file - * check-known-to-fail * * check-output-ignore * check-output-returns: 1 |