[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
Thu Jun 8 04:50:42 PDT 2017


PFerreira created this revision.

When the lowest bits of the operands to an integer multiply are known, the low bits of the result are deducible.
Code to deduce known-zero bottom bits already existed, but this change improves on that by deducing known-ones.


Repository:
  rL LLVM

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 = add 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,15 @@
     }
   }
 
+  // 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.
+  APInt bottom0 = Known.One & ~Known.Zero;
+  APInt bottom1 = Known2.One & ~Known2.Zero;
+  // 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 +375,23 @@
   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 = bottomKnown.getBitWidth() - bottomKnown.countLeadingZeros();
+    trailKnown = std::min(trailKnown, Known.getBitWidth());
+    for (unsigned bit = TrailZ; bit < trailKnown; ++bit) {
+      if ((bottomKnown & (1<<bit)) == 0) {
+        Known.Zero.setBit(bit);
+        Known.One.clearBit(bit);
+      } else {
+        Known.Zero.clearBit(bit);
+        Known.One.setBit(bit);
+      }
+    }
+  }
+
   // 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.101893.patch
Type: text/x-patch
Size: 3472 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170608/bb4169fb/attachment.bin>


More information about the llvm-commits mailing list