[llvm] r251487 - [ValueTracking] Use !range metadata more aggressively in KnownBits

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 27 20:20:15 PDT 2015


Author: sanjoy
Date: Tue Oct 27 22:20:15 2015
New Revision: 251487

URL: http://llvm.org/viewvc/llvm-project?rev=251487&view=rev
Log:
[ValueTracking] Use !range metadata more aggressively in KnownBits

Summary:
Teach `computeKnownBitsFromRangeMetadata` to use `!range` metadata more
aggressively.

Reviewers: majnemer, nlewycky, jingyue

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D14100

Added:
    llvm/trunk/test/Analysis/ValueTracking/known-bits-from-range-md.ll
Modified:
    llvm/trunk/include/llvm/Analysis/ValueTracking.h
    llvm/trunk/lib/Analysis/ValueTracking.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=251487&r1=251486&r2=251487&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original)
+++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Tue Oct 27 22:20:15 2015
@@ -49,8 +49,9 @@ namespace llvm {
                         const DominatorTree *DT = nullptr);
   /// Compute known bits from the range metadata.
   /// \p KnownZero the set of bits that are known to be zero
+  /// \p KnownOne the set of bits that are known to be one
   void computeKnownBitsFromRangeMetadata(const MDNode &Ranges,
-                                         APInt &KnownZero);
+                                         APInt &KnownZero, APInt &KnownOne);
   /// Return true if LHS and RHS have no common bits set.
   bool haveNoCommonBitsSet(Value *LHS, Value *RHS, const DataLayout &DL,
                            AssumptionCache *AC = nullptr,

Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=251487&r1=251486&r2=251487&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Tue Oct 27 22:20:15 2015
@@ -367,24 +367,30 @@ static void computeKnownBitsMul(Value *O
 }
 
 void llvm::computeKnownBitsFromRangeMetadata(const MDNode &Ranges,
-                                             APInt &KnownZero) {
+                                             APInt &KnownZero,
+                                             APInt &KnownOne) {
   unsigned BitWidth = KnownZero.getBitWidth();
   unsigned NumRanges = Ranges.getNumOperands() / 2;
   assert(NumRanges >= 1);
 
-  // Use the high end of the ranges to find leading zeros.
-  unsigned MinLeadingZeros = BitWidth;
+  KnownZero.setAllBits();
+  KnownOne.setAllBits();
+
   for (unsigned i = 0; i < NumRanges; ++i) {
     ConstantInt *Lower =
         mdconst::extract<ConstantInt>(Ranges.getOperand(2 * i + 0));
     ConstantInt *Upper =
         mdconst::extract<ConstantInt>(Ranges.getOperand(2 * i + 1));
     ConstantRange Range(Lower->getValue(), Upper->getValue());
-    unsigned LeadingZeros = Range.getUnsignedMax().countLeadingZeros();
-    MinLeadingZeros = std::min(LeadingZeros, MinLeadingZeros);
-  }
 
-  KnownZero = APInt::getHighBitsSet(BitWidth, MinLeadingZeros);
+    // The first CommonPrefixBits of all values in Range are equal.
+    unsigned CommonPrefixBits =
+        (Range.getUnsignedMax() ^ Range.getUnsignedMin()).countLeadingZeros();
+
+    APInt Mask = APInt::getHighBitsSet(BitWidth, CommonPrefixBits);
+    KnownOne &= Range.getUnsignedMax() & Mask;
+    KnownZero &= ~Range.getUnsignedMax() & Mask;
+  }
 }
 
 static bool isEphemeralValueOf(Instruction *I, const Value *E) {
@@ -1060,7 +1066,7 @@ static void computeKnownBitsFromOperator
   default: break;
   case Instruction::Load:
     if (MDNode *MD = cast<LoadInst>(I)->getMetadata(LLVMContext::MD_range))
-      computeKnownBitsFromRangeMetadata(*MD, KnownZero);
+      computeKnownBitsFromRangeMetadata(*MD, KnownZero, KnownOne);
     break;
   case Instruction::And: {
     // If either the LHS or the RHS are Zero, the result is zero.
@@ -1452,7 +1458,7 @@ static void computeKnownBitsFromOperator
   case Instruction::Call:
   case Instruction::Invoke:
     if (MDNode *MD = cast<Instruction>(I)->getMetadata(LLVMContext::MD_range))
-      computeKnownBitsFromRangeMetadata(*MD, KnownZero);
+      computeKnownBitsFromRangeMetadata(*MD, KnownZero, KnownOne);
     // If a range metadata is attached to this IntrinsicInst, intersect the
     // explicit range specified by the metadata and the implicit range of
     // the intrinsic.

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=251487&r1=251486&r2=251487&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Tue Oct 27 22:20:15 2015
@@ -2285,7 +2285,7 @@ void SelectionDAG::computeKnownBits(SDVa
       KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits);
     } else if (const MDNode *Ranges = LD->getRanges()) {
       if (LD->getExtensionType() == ISD::NON_EXTLOAD)
-        computeKnownBitsFromRangeMetadata(*Ranges, KnownZero);
+        computeKnownBitsFromRangeMetadata(*Ranges, KnownZero, KnownOne);
     }
     break;
   }

Added: llvm/trunk/test/Analysis/ValueTracking/known-bits-from-range-md.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ValueTracking/known-bits-from-range-md.ll?rev=251487&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/ValueTracking/known-bits-from-range-md.ll (added)
+++ llvm/trunk/test/Analysis/ValueTracking/known-bits-from-range-md.ll Tue Oct 27 22:20:15 2015
@@ -0,0 +1,34 @@
+; RUN: opt -S -instsimplify < %s | FileCheck %s
+
+define i1 @test0(i8* %ptr) {
+; CHECK-LABEL: @test0(
+ entry:
+  %val = load i8, i8* %ptr, !range !{i8 -50, i8 0}
+  %and = and i8 %val, 128
+  %is.eq = icmp eq i8 %and, 128
+  ret i1 %is.eq
+; CHECK: ret i1 true
+}
+
+define i1 @test1(i8* %ptr) {
+; CHECK-LABEL: @test1(
+ entry:
+  %val = load i8, i8* %ptr, !range !{i8 64, i8 128}
+  %and = and i8 %val, 64
+  %is.eq = icmp eq i8 %and, 64
+  ret i1 %is.eq
+; CHECK: ret i1 true
+}
+
+define i1 @test2(i8* %ptr) {
+; CHECK-LABEL: @test2(
+ entry:
+; CHECK: load
+; CHECK: and
+; CHECK: icmp eq
+; CHECK: ret
+  %val = load i8, i8* %ptr, !range !{i8 64, i8 129}
+  %and = and i8 %val, 64
+  %is.eq = icmp eq i8 %and, 64
+  ret i1 %is.eq
+}




More information about the llvm-commits mailing list