[PATCH] D48828: [InstSimplify] fold extracting from std::pair

Roman Lebedev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 19 11:35:32 PDT 2018


lebedev.ri added a comment.

Some more comments.
Please enhance test coverage, and note the note about possible miscompile.

In https://reviews.llvm.org/D48828#1167921, @inouehrs wrote:

> > ! In https://reviews.llvm.org/D48828#1166791, @lebedev.ri wrote:
> >  Can you explain that in layman terms?
> >  I don't see anything phi-related in instsimplify changes.
>
> To help jump threading, actually we need to optimize the code sequence spanning multiple BBs. For an example of `shl->or->and` case looks like
>
>   BB1:
>     %shl = shl nuw i64 %val, 32
>     %or = or i64 %shl, 1
>     br %BB2
>   BB2:
>     %phi = phi i64 [ %or, %BB1 ], ... 
>     %and = and i64 %phi, 1
>
>
> The current instcombine cannot optimize such cases.
>  My instsimplify patch does not handle phi by itself. The NewGVN calls instsimplify to check opportunities for simplifying instructions over phi.


Aha, that is the bit i was looking for. Please update the differential's description with that.



================
Comment at: lib/Analysis/InstructionSimplify.cpp:1814
+  // from X and Y are disjoint in (X << A) | Y.
+  // ((X << A) | Y) & 1 -> Y  if effective width of Y is 1 (i.e. boolean).
+  // ((X << A) | Y) & (1 << A) -> X << A  if effective width of X is 1.
----------------
inouehrs wrote:
> lebedev.ri wrote:
> > I do not understand.
> > Why is this only handling the case where `Y` is `bool`?
> > 
> I made the code more generic. What we really need to check is that this AND op selects all bits of X or Y, and no bit from the another.
> 
> What we really need to check is that this AND op selects all bits of X or Y, and no bit from the another.

That was exactly my point :)


================
Comment at: lib/Analysis/InstructionSimplify.cpp:1287-1288
+    unsigned EffWidthY = Width - YKnown.countMinLeadingZeros();
+    if (EffWidthY <= ShiftCnt)
+      return X;
+  }
----------------
Please add some negative test where this fails.


================
Comment at: lib/Analysis/InstructionSimplify.cpp:1823
+      match(Op0, m_c_Or(m_NUWShl(m_Value(X), m_APInt(ShAmt)), m_Value(Y)))) {
+    APInt Mask = cast<ConstantInt>(Op1)->getValue();
+    unsigned ShiftCnt = ShAmt->getZExtValue();
----------------
I think you can use `const APInt& Mask` here.


================
Comment at: lib/Analysis/InstructionSimplify.cpp:1825
+    unsigned ShiftCnt = ShAmt->getZExtValue();
+    if (Mask == 1 || Mask == (1uLL << ShiftCnt)) {
+      KnownBits YKnown = computeKnownBits(Y, Q.DL, 0, Q.AC, Q.CxtI, Q.DT);
----------------
But it seems like this only supports extraction of a bit-wide values?
Please at least add a `FIXME` comment then.


================
Comment at: lib/Analysis/InstructionSimplify.cpp:1832-1833
+        unsigned EffWidthX = Width - XKnown.countMinLeadingZeros();
+        uint64_t EffBitsY = (1uL << EffWidthY) - 1;
+        uint64_t EffBitsX = ((1uL << EffWidthX) - 1) << ShiftCnt;
+        // If the mask is extracting all bits from X or Y as is, we can skip
----------------
Aha. This will miscompile if you are operating on types wider than `i64`.

Please add tests with wider types (`i128`, with elements of `i64`, e.g.),
and use `APInt` in these calculations.


================
Comment at: lib/Analysis/InstructionSimplify.cpp:1843
+            return cast<Instruction>(Op0)->getOperand(0);
+        }
+      }
----------------
This also needs //some// negative tests.


================
Comment at: test/Transforms/InstSimplify/AndOrXor.ll:994
+  ret i64 %5
+}
----------------
Please also add two tests with `i32 | i32` - test extracting low part, and test high part.


https://reviews.llvm.org/D48828





More information about the llvm-commits mailing list