On Mon, Aug 20, 2018 at 05:51:54PM +0100, Ramsay Jones wrote: > On 17/08/18 22:17, Luc Van Oostenryck wrote: > > On Fri, Aug 17, 2018 at 08:45:02PM +0100, Ramsay Jones wrote: > >> On 16/08/18 23:12, Luc Van Oostenryck wrote: > >>> Doing a LSR(X, N) will drop the N right bits. > >>> So any simplification that can be made when using an AND clearing > >>> the right N bits can also be used on LSR (as if its first operand > >>> would first be implicitly be ANDed with such a mask). > >>> > >>> So, in order to not duplicate complex simplifications involving > >>> ANDs & ORs masks, merge these both function in a single one, > >>> using the mask corresponding to the operation. > >>> > >>> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> > >>> --- > >>> simplify.c | 56 ++++++++++++++++++++++-------------------------------- > >>> 1 file changed, 23 insertions(+), 33 deletions(-) > >>> > >>> diff --git a/simplify.c b/simplify.c > >>> index ef98b205a..ce48b3a91 100644 > >>> --- a/simplify.c > >>> +++ b/simplify.c > >>> @@ -546,6 +546,24 @@ undef: > >>> return NULL; > >>> } > >>> > >>> +static int simplify_mask_or_and(struct instruction *insn, unsigned long long mask, > >>> + pseudo_t src, pseudo_t other) > >>> +{ > >>> + unsigned long long omask, nmask; > >>> + pseudo_t src2 = src->def->src2; > >>> + > >>> + if (!constant(src2)) > >>> + return 0; > >>> + omask = src2->value; > >>> + nmask = omask & mask; > >>> + if (nmask != 0) > >>> + return 0; > >>> + // replace OP(((A & M') | B), C) > >> > >> Huh?, should that be OP(((A & M') | B), C) & M ? > >> and ... > >>> + // by OP(B, C) > >> > >> OP(B, C) & M ? > >> > >> confused. > > > > Yes, sorry. > > All this merits much better documentation. > > OP(x, C) that I'm using here stand (or will stand) for either: > > * AND(x, M) and then mask = M > > * LSR(x, S) and then mask = (-1 << S) > > * SHL(x, S) and then mask = (-1 >> S) > > * TRUNC(x) and then mask = $mask(newbitsize) = (1 << newbitsize) - 1 > > [Sorry for the delay; $LIFE is hectic at the moment.] No worries, please. It's already really great that you're reviewing conscienciouslty all these patches. I'll never be able to thank you enough. > So, are you saying that the 'mask' given above is M' (or omask > in the code) and M is the function parameter 'mask'. ;-) > > So src2->value in the above instructions are all 'mask' values > rather than (say) the shift count S? Hmm, so, Huh! :-D No, sorry. In comments & explanations I use uppercase letters for constants: 'M' for a constant mask, 'S' for a constant shift, 'N' for a constant number of bits and 'C' for others constants. I also sometimes use '$mask(N)' for ((1 << N) -1), and (-1 << S) as a shorthand for '(-1 << S) truncated to the size of the instruction'. Also M is (normaly) reserved for the outer mask, I use M', M'', ... for other masks if present. Lowercase letters 'a', 'b', 'x', 'y' are for other variables/pseudos. For the code here, the variable 'mask' n the code correspond to a known/constant mask and is represented as 'M' in the formulae. * if OP(_,_) is AND(x, M), obviously M is M is mask. * if OP(_,_) is TRUNC(x, N) then mask is ((1 << N) -1), that I also note as '$mask(N)', where N is the new size. * if OP(_,_) is LSR(x, S) then mask is (-1 << S) (truncated to the size of the instruction). * if OP(_,_) is SHL(x, S) then mask is (-1 >> S). This is done because: * TRUNC(x, N) is always equivalent to TRUNC(AND(x, ((1 << N) -1))) * LSR(X, S) is always equivalent to LSR(AND(x, (-1 << S)), S) * SHL(X, S) is always equivalent to SHL(AND(x, (-1 >> S)), S) In other words: * TRUNC(x, N) simplify the same as AND(x, ((1 << N) - 1)) * LSR(x, S) simplify the same as AND(x, (-1 << N)) * SHL(x, S) simplify the same as AND(x, (-1 >> N)) or equivalently: * to TRUNC(x, N) correspond an equivalent mask ((1 << N) -1) * to LSR(x, S) correspond an equivalent mask (-1 << S) * to SHL(x, S) correspond an equivalent mask (-1 >> S) and so I use the notation 'OP(x, C)' for all these operations and sometimes I abuse the notation and directly use 'OP(x, M)' where M is the the mask corresponding to OP(x, C). For completeness, ZEXT() is a no-op as outer mask but as it has the equivalent mask ((1 << oldsize) -1). I hope this make things a bit more clear. -- Luc