[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