diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-08-22 17:31:57 +0200 |
|---|---|---|
| committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-08-24 08:18:36 +0200 |
| commit | 3f2cbce78f78cbae35a02eb318a86f78556f71aa (patch) | |
| tree | 92daecdcc157eb89fc007078e0479d48b9be9be5 | |
| parent | 240c84a3eea0649f76a2510f61475a5216fe9a81 (diff) | |
| download | sparse-dev-3f2cbce78f78cbae35a02eb318a86f78556f71aa.tar.gz | |
simplify AND(SHIFT(a | b, S), M)
The simplification of AND(SHIFT(a | b, S), M) can be done by combining
the mask M with the effective mask corresponding to SHIFT(_, S).
This instruction pattern is generated when accessing bitfields,
for example, code like:
struct u {
unsigned int :2;
unsigned int f:3;
};
int bfu(struct u s, int a)
{
s.f = a;
return s.f;
}
is now simplified into the minimal:
bfu:
and.32 %r11 <- %arg2, $7
ret.32 %r11
The simplification is done by introducing a small helper,
simplify_mask_shift(), doing the pattern matching and then calling
simplify_mask_shift_or() with the mask M.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
| -rw-r--r-- | simplify.c | 18 | ||||
| -rw-r--r-- | validation/optim/and-or-bfu.c | 1 | ||||
| -rw-r--r-- | validation/optim/bitfield-store-loadu.c | 1 |
3 files changed, 18 insertions, 2 deletions
@@ -686,6 +686,21 @@ static int simplify_mask_shift_or(struct instruction *sh, struct instruction *or return simplify_mask_or(sh, smask & mask, or); } +static int simplify_mask_shift(struct instruction *sh, unsigned long long mask) +{ + struct instruction *inner; + + if (!constant(sh->src2) || sh->tainted) + return 0; + switch (DEF_OPCODE(inner, sh->src1)) { + case OP_OR: + if (!multi_users(sh->target)) + return simplify_mask_shift_or(sh, inner, mask); + break; + } + return 0; +} + static long long check_shift_count(struct instruction *insn, unsigned long long uval) { unsigned int size = insn->size; @@ -986,6 +1001,9 @@ static int simplify_constant_mask(struct instruction *insn, unsigned long long m goto oldsize; case OP_OR: return simplify_mask_or(insn, mask, def); + case OP_LSR: + case OP_SHL: + return simplify_mask_shift(def, mask); case OP_ZEXT: osize = def->orig_type->bit_size; /* fall through */ diff --git a/validation/optim/and-or-bfu.c b/validation/optim/and-or-bfu.c index c9dcfc33..b6a080bd 100644 --- a/validation/optim/and-or-bfu.c +++ b/validation/optim/and-or-bfu.c @@ -12,7 +12,6 @@ int bfu(struct u s, int a) /* * check-name: and-or-bfu * check-command: test-linearize -Wno-decl $file - * check-known-to-fail * * check-output-ignore * check-output-pattern(1): and\\. diff --git a/validation/optim/bitfield-store-loadu.c b/validation/optim/bitfield-store-loadu.c index 4c289504..7fa1593d 100644 --- a/validation/optim/bitfield-store-loadu.c +++ b/validation/optim/bitfield-store-loadu.c @@ -12,7 +12,6 @@ int foo(struct s s, int a) /* * check-name: bitfield-store-load unsigned * check-command: test-linearize -Wno-decl $file - * check-known-to-fail * * check-output-ignore * check-output-excludes: shl\\. |
