[PATCH] D34029: Infer lowest bits of an integer Multiply when the low bits of the operands are known

Pedro Ferreira via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 20 02:07:51 PDT 2017


PFerreira updated this revision to Diff 103176.
PFerreira added a comment.

Update diff following Craig's comment.


https://reviews.llvm.org/D34029

Files:
  lib/Analysis/ValueTracking.cpp
  unittests/Analysis/ValueTrackingTest.cpp


Index: unittests/Analysis/ValueTrackingTest.cpp
===================================================================
--- unittests/Analysis/ValueTrackingTest.cpp
+++ unittests/Analysis/ValueTrackingTest.cpp
@@ -15,6 +15,7 @@
 #include "llvm/IR/Module.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/KnownBits.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
@@ -258,3 +259,31 @@
       cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0);
   EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1u);
 }
+
+TEST(ValueTracking, ComputeKnownBits) {
+  StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { "
+                       "  %ash = mul i32 %a, 8 "
+                       "  %aad = add i32 %ash, 7 "
+                       "  %aan = and i32 %aad, 4095 "
+                       "  %bsh = shl i32 %b, 4 "
+                       "  %bad = or i32 %bsh, 6 "
+                       "  %ban = and i32 %bad, 4095 "
+                       "  %mul = mul i32 %aan, %ban "
+                       "  ret i32 %mul "
+                       "} ";
+
+  LLVMContext Context;
+  SMDiagnostic Error;
+  auto M = parseAssemblyString(Assembly, Error, Context);
+  assert(M && "Bad assembly?");
+
+  auto *F = M->getFunction("f");
+  assert(F && "Bad assembly?");
+
+  auto *RVal =
+      cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0);
+  auto Known = computeKnownBits(RVal, M->getDataLayout());
+  ASSERT_FALSE(Known.hasConflict());
+  EXPECT_EQ(Known.One.getZExtValue(), 42u);
+  EXPECT_EQ(Known.Zero.getZExtValue(), 4278190101u);
+}
Index: lib/Analysis/ValueTracking.cpp
===================================================================
--- lib/Analysis/ValueTracking.cpp
+++ lib/Analysis/ValueTracking.cpp
@@ -350,6 +350,16 @@
     }
   }
 
+  // The result of the bottom bits of an integer multiply can
+  // be inferred by looking at the bottom bits of both operands
+  // and multiplying them together.
+  assert(!Known.hasConflict() && !Known2.hasConflict());
+  APInt Bottom0 = Known.One;
+  APInt Bottom1 = Known2.One;
+  // Find the last bit known on both operands.
+  unsigned TrailBitsKnown = (Known.Zero | Known.One).countTrailingOnes();
+  TrailBitsKnown = std::min(TrailBitsKnown, (Known2.Zero | Known2.One).countTrailingOnes());
+
   // If low bits are zero in either operand, output low known-0 bits.
   // Also compute a conservative estimate for high known-0 bits.
   // More trickiness is possible, but this is sufficient for the
@@ -366,6 +376,15 @@
   Known.Zero.setLowBits(TrailZ);
   Known.Zero.setHighBits(LeadZ);
 
+  if (TrailBitsKnown != 0) {
+    // Finally, these are the known bottom bits of the result.
+    APInt BottomKnown = Bottom0.getLoBits(TrailBitsKnown) *
+                        Bottom1.getLoBits(TrailBitsKnown);
+    unsigned TrailKnown = std::min(BottomKnown.getActiveBits(), Known.getBitWidth());
+    Known.Zero |= (~BottomKnown).getLoBits(TrailKnown);
+    Known.One |= BottomKnown.getLoBits(TrailKnown);
+  }
+
   // Only make use of no-wrap flags if we failed to compute the sign bit
   // directly.  This matters if the multiplication always overflows, in
   // which case we prefer to follow the result of the direct computation,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D34029.103176.patch
Type: text/x-patch
Size: 3278 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170620/29598766/attachment.bin>


More information about the llvm-commits mailing list