[PATCH] D112060: [NARY-REASSOCIATE] Fix infinite recursion optimizing min\max
Evgeniy via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 19 22:53:31 PDT 2021
ebrevnov added inline comments.
================
Comment at: llvm/lib/Transforms/Scalar/NaryReassociate.cpp:615
continue;
- // Transform 'I = (A op RHS) op B' 'I = (B op RHS) op A' on the second
+ // Transform 'I = (A op C) op B' to 'I = (B op C) op A' on the second
// iteration.
----------------
nikic wrote:
> spatel wrote:
> > This code comment doesn't match the code?
> Something that also confuses me about this code is why it performs a loop with two iterations over `j`, and then has completely separate behavior for them. Wouldn't this whole loop be equivalent to the following?
> ```
> if (BExpr != CExpr) {
> std::swap(BExpr, CExpr);
> std::swap(B, C);
> }
> if (AExpr != CExpr) {
> std::swap(AExpr, CExpr);
> std::swap(A, C);
> }
> ```
> Or if we allow some redundant swaps just:
> ```
> std::swap(BExpr, CExpr);
> std::swap(B, C);
> std::swap(AExpr, CExpr);
> std::swap(A, C);
> ```
> Which reorders `A B C` into `B C A`.
>
> Though as all of these variables are under your control I think you could just directly match them into the right variables rather than swapping them after the fact.
>
> Am I missing something here?
> This code comment doesn't match the code?
It does matches the code but not easy to follow. The trick is that pointers named A, B, and C refers to different expressions on each iteration. For example, after the first swap B points to what C used to point.... I agree all that looks confusing ... I will try to restructure the code to make it simpler for understanding.
================
Comment at: llvm/lib/Transforms/Scalar/NaryReassociate.cpp:615
continue;
- // Transform 'I = (A op RHS) op B' 'I = (B op RHS) op A' on the second
+ // Transform 'I = (A op C) op B' to 'I = (B op C) op A' on the second
// iteration.
----------------
ebrevnov wrote:
> nikic wrote:
> > spatel wrote:
> > > This code comment doesn't match the code?
> > Something that also confuses me about this code is why it performs a loop with two iterations over `j`, and then has completely separate behavior for them. Wouldn't this whole loop be equivalent to the following?
> > ```
> > if (BExpr != CExpr) {
> > std::swap(BExpr, CExpr);
> > std::swap(B, C);
> > }
> > if (AExpr != CExpr) {
> > std::swap(AExpr, CExpr);
> > std::swap(A, C);
> > }
> > ```
> > Or if we allow some redundant swaps just:
> > ```
> > std::swap(BExpr, CExpr);
> > std::swap(B, C);
> > std::swap(AExpr, CExpr);
> > std::swap(A, C);
> > ```
> > Which reorders `A B C` into `B C A`.
> >
> > Though as all of these variables are under your control I think you could just directly match them into the right variables rather than swapping them after the fact.
> >
> > Am I missing something here?
> > This code comment doesn't match the code?
>
> It does matches the code but not easy to follow. The trick is that pointers named A, B, and C refers to different expressions on each iteration. For example, after the first swap B points to what C used to point.... I agree all that looks confusing ... I will try to restructure the code to make it simpler for understanding.
>
> Something that also confuses me about this code is why it performs a loop with two iterations over `j`, and then has completely separate behavior for them. Wouldn't this whole loop be equivalent to the following?
> ```
> if (BExpr != CExpr) {
> std::swap(BExpr, CExpr);
> std::swap(B, C);
> }
> if (AExpr != CExpr) {
> std::swap(AExpr, CExpr);
> std::swap(A, C);
> }
> ```
> Or if we allow some redundant swaps just:
> ```
> std::swap(BExpr, CExpr);
> std::swap(B, C);
> std::swap(AExpr, CExpr);
> std::swap(A, C);
> ```
> Which reorders `A B C` into `B C A`.
>
> Though as all of these variables are under your control I think you could just directly match them into the right variables rather than swapping them after the fact.
>
> Am I missing something here?
No, this is not semantically equivalent code. The idea is to try two combinations: (AopC)opB and then (BopC)opA. That's why the loop of two iterations.
I agree all that look confusing...I will try to restructure the code to make it simpler for understanding.
================
Comment at: llvm/lib/Transforms/Scalar/NaryReassociate.cpp:642
+ SmallVector<const SCEV *, 2> Ops2{SE->getUnknown(C),
+ SE->getUnknown(R1MinMax)};
const SCEV *R2Expr = SE->getMinMaxExpr(SCEVType, Ops2);
----------------
nikic wrote:
> You can pass these directly, no need to create SmallVector for an ArrayRef.
> You can pass these directly, no need to create SmallVector for an ArrayRef.
Thanks. Will fix.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D112060/new/
https://reviews.llvm.org/D112060
More information about the llvm-commits
mailing list