A OP_AND with a constant value followed by a sign or zero-extension can often be moved after the extension. This is good because it can trigger the cancellation of the OP[ZS]EXT with a preceding OP_TRUNC, a common situation with bitfields. Note: This 'simplification' is less desirable if there is no preceding OP_TRUNC, for example, in a sequence like: and.32 %t <- %a, $mask *ext.64 %r <- %t If needed, this can be filtered out at some later stage. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- simplify.c | 24 ++++++++++++++++++++++++ validation/optim/and-extend.c | 1 - validation/optim/and-extendx.c | 1 - validation/optim/trunc-mask-zext.c | 1 - 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/simplify.c b/simplify.c index 336339fac..a0f7aa327 100644 --- a/simplify.c +++ b/simplify.c @@ -1011,6 +1011,30 @@ static int simplify_cast(struct instruction *insn) mask &= (1ULL << size) - 1; insn->src2 = value_pseudo(mask); return REPEAT_CSE; + + case OP_SEXT: + if (val->value & (1 << (def->size - 1))) + break; + // OK, sign bit is 0 + case OP_ZEXT: + if (nbr_users(src) > 1) + break; + // transform: + // and.n %b <- %a, M + // *ext.m %c <- (n) %b + // into: + // zext.m %b <- %a + // and.m %c <- %b, M + // For ZEXT, the mask will always be small + // enough. For SEXT, it can only be done if + // the mask force the sign bit to 0. + def->opcode = OP_ZEXT; + def->orig_type = insn->orig_type; + def->type = insn->type; + def->size = insn->size; + insn->opcode = OP_AND; + insn->src2 = val; + return REPEAT_CSE; } break; case OP_TRUNC: diff --git a/validation/optim/and-extend.c b/validation/optim/and-extend.c index fdcf470f0..eb5892369 100644 --- a/validation/optim/and-extend.c +++ b/validation/optim/and-extend.c @@ -18,7 +18,6 @@ u32 sfoo(u32 x) /* * check-name: and-extend * check-command: test-linearize -Wno-decl $file - * check-known-to-fail * * check-output-ignore * check-output-excludes: trunc\\. diff --git a/validation/optim/and-extendx.c b/validation/optim/and-extendx.c index a580bd0d6..5c181c933 100644 --- a/validation/optim/and-extendx.c +++ b/validation/optim/and-extendx.c @@ -18,7 +18,6 @@ u64 sfoo(int x) /* * check-name: and-extend * check-command: test-linearize -Wno-decl $file - * check-known-to-fail * * check-output-ignore * check-output-contains: and\\.64.*0x7fff diff --git a/validation/optim/trunc-mask-zext.c b/validation/optim/trunc-mask-zext.c index 30ae5aeeb..9b6041746 100644 --- a/validation/optim/trunc-mask-zext.c +++ b/validation/optim/trunc-mask-zext.c @@ -6,7 +6,6 @@ unsigned long long foo(unsigned long long x) /* * check-name: trunc-mask-zext * check-command: test-linearize -Wno-decl $file - * check-known-to-fail * * check-output-ignore * check-output-excludes: trunc\\. -- 2.18.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