[PATCH] D46073: [DagCombine] De Morgan laws: 'nand' logic with an inverted operand

Roman Lebedev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu May 3 11:20:36 PDT 2018


lebedev.ri added a comment.

In https://reviews.llvm.org/D46073#1086745, @lebedev.ri wrote:

> In https://reviews.llvm.org/D46073#1085463, @spatel wrote:
>
> > In https://reviews.llvm.org/D46073#1080839, @lebedev.ri wrote:
> >
> > > - Rebased ontop of revised tests.
> > > - Handle `nor` pattern too.
> > > - Still not sure how to handle `vandnpd`/`vandnps` breakage.
> >
> >
> > I lost track of where we are in the masked merge odyssey. :)
> >  I think this is the next step, but we have to avoid regressing the x86 andnps tests?
>
>
>
>
> > Can we use TLI.hasAndNot() to predicate the transform? Ie, if you have 'andn', then there's no point trying to eliminate a 'not' that will get merged with another instruction?
>
> I think this would need to be a bit more complex. E.g.:
>
> - if this `not` is used in `and`, and the other hand of `and` ...
>   - ... is ok as per `hasAndNot()` (i.e. in x86's case, not an immediate), then there is no immediate benefit of simplification. `[A]`
>   - ... is not ok as per `hasAndNot()` (i.e. in x86's case, e.g. an immediate), then we shouldn't at least degrade the code by simplifying. `[B]`
> - else, if it is used elsewhere (not in `and`), then we shouldn't at least degrade the code by simplifying. `[B]`
> - We have two patterns. (Let's look at the inner `and`/`or`):
>   - `~(~A & B) --> (A | ~B)` <- the original form *may*  `[00]` or may not `[01]` get folded into `andn`, the transformed variant is unlikely to be folded (`ORN: logical OR NOT (Thumb only)`).
>   - `~(~A | B) --> (A & ~B)` <- the original form is unlikely to be folded into `orn`, the transformed variant *may* `[10]` or may not `[11]` to be folded. `[1]`
>
>     So we have 8 variants: (`X` being the other hand) | from                          | to                         | delta                  | | `OP   X, not(and(not(A), B))` | `OP  X,  or   (A, not(B))` | 3 -> 2, **transform**  | | `OP   X, not(andn(A, B))`     | `OP  X,  or   (A, not(B))` | 2 -> 2, keep           | | `andn X, and(not(A), B)`      | `and X,  or   (A, not(B))` | 2 -> 2, keep           | | `andn X, andn(A, B)`          | `and X,  or   (A, not(B))` | 1 -> 2, keep!          | | `OP   X, not(or(not(A), B))`  | `OP X,   and  (A, not(B))` | 3 -> 2, **transform**  | | `OP   X, not(or(not(A), B))`  | `OP X,   andn (A, B)`      | 3 -> 1, **transform!** | | `andn X, or(not(A), B)`       | `and X,  and  (A, not(B))` | 2 -> 2, keep?          | | `andn X, or(not(A), B)`       | `and X,  andn (A, B)`      | 2 -> 1, **transform**  |


In other words, there seems to be just one situation where we *certainly* should not transform.


Repository:
  rL LLVM

https://reviews.llvm.org/D46073





More information about the llvm-commits mailing list