<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 26 October 2015 at 18:46, Sanjoy Das <span dir="ltr"><<a href="mailto:sanjoy@playingwithpointers.com" target="_blank">sanjoy@playingwithpointers.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">sanjoy created this revision.<br>
sanjoy added reviewers: jingyue, majnemer, nlewycky.<br>
sanjoy added a subscriber: llvm-commits.<br>
<br>
Teach `computeKnownBitsFromRangeMetadata` to use `!range` metadata to<br>
prove that a value is always negative, and hence always has a sign bit<br>
set.<br></blockquote><div><br></div><div>I think that's overly specialized. If you have a range of i8 [64..127] then you know the top two bits are '01'.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
<a href="http://reviews.llvm.org/D14100" rel="noreferrer" target="_blank">http://reviews.llvm.org/D14100</a><br>
<br>
Files:<br>
  include/llvm/Analysis/ValueTracking.h<br>
  lib/Analysis/ValueTracking.cpp<br>
  lib/CodeGen/SelectionDAG/SelectionDAG.cpp<br>
  test/Analysis/ValueTracking/sign-bit-from-md.ll<br>
<br>
Index: test/Analysis/ValueTracking/sign-bit-from-md.ll<br>
===================================================================<br>
--- /dev/null<br>
+++ test/Analysis/ValueTracking/sign-bit-from-md.ll<br>
@@ -0,0 +1,13 @@<br>
+; RUN: opt -S -instsimplify < %s | FileCheck %s<br>
+<br>
+define i1 @f(i8* %ptr) {<br>
+; CHECK-LABEL: @f(<br>
+ entry:<br>
+  %val = load i8, i8* %ptr, !range !0<br>
+  %and = and i8 %val, 128<br>
+  %is.eq = icmp eq i8 %and, 128<br>
+  ret i1 %is.eq<br>
+; CHECK: true<br>
+}<br>
+<br>
+!0 = !{i8 -50, i8 0}<br>
Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp<br>
===================================================================<br>
--- lib/CodeGen/SelectionDAG/SelectionDAG.cpp<br>
+++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp<br>
@@ -2284,7 +2284,7 @@<br>
       unsigned MemBits = VT.getScalarType().getSizeInBits();<br>
       KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits);<br>
     } else if (const MDNode *Ranges = LD->getRanges()) {<br>
-      computeKnownBitsFromRangeMetadata(*Ranges, KnownZero);<br>
+      computeKnownBitsFromRangeMetadata(*Ranges, KnownZero, KnownOne);<br>
     }<br>
     break;<br>
   }<br>
Index: lib/Analysis/ValueTracking.cpp<br>
===================================================================<br>
--- lib/Analysis/ValueTracking.cpp<br>
+++ lib/Analysis/ValueTracking.cpp<br>
@@ -367,11 +367,14 @@<br>
 }<br>
<br>
 void llvm::computeKnownBitsFromRangeMetadata(const MDNode &Ranges,<br>
-                                             APInt &KnownZero) {<br>
+                                             APInt &KnownZero,<br>
+                                             APInt &KnownOne) {<br>
   unsigned BitWidth = KnownZero.getBitWidth();<br>
   unsigned NumRanges = Ranges.getNumOperands() / 2;<br>
   assert(NumRanges >= 1);<br>
<br>
+  bool AlwaysNegative = true;<br>
+<br>
   // Use the high end of the ranges to find leading zeros.<br>
   unsigned MinLeadingZeros = BitWidth;<br>
   for (unsigned i = 0; i < NumRanges; ++i) {<br>
@@ -382,9 +385,14 @@<br>
     ConstantRange Range(Lower->getValue(), Upper->getValue());<br>
     unsigned LeadingZeros = Range.getUnsignedMax().countLeadingZeros();<br>
     MinLeadingZeros = std::min(LeadingZeros, MinLeadingZeros);<br>
+    AlwaysNegative &= Range.getSignedMax().isNegative();<br>
   }<br>
<br>
   KnownZero = APInt::getHighBitsSet(BitWidth, MinLeadingZeros);<br>
+  if (AlwaysNegative) {<br>
+    assert(MinLeadingZeros == 0 && "We found at least one negative number!");<br>
+    KnownOne = APInt::getHighBitsSet(BitWidth, 1);<br>
+  }<br>
 }<br>
<br>
 static bool isEphemeralValueOf(Instruction *I, const Value *E) {<br>
@@ -1060,7 +1068,7 @@<br>
   default: break;<br>
   case Instruction::Load:<br>
     if (MDNode *MD = cast<LoadInst>(I)->getMetadata(LLVMContext::MD_range))<br>
-      computeKnownBitsFromRangeMetadata(*MD, KnownZero);<br>
+      computeKnownBitsFromRangeMetadata(*MD, KnownZero, KnownOne);<br>
     break;<br>
   case Instruction::And: {<br>
     // If either the LHS or the RHS are Zero, the result is zero.<br>
@@ -1452,7 +1460,7 @@<br>
   case Instruction::Call:<br>
   case Instruction::Invoke:<br>
     if (MDNode *MD = cast<Instruction>(I)->getMetadata(LLVMContext::MD_range))<br>
-      computeKnownBitsFromRangeMetadata(*MD, KnownZero);<br>
+      computeKnownBitsFromRangeMetadata(*MD, KnownZero, KnownOne);<br>
     // If a range metadata is attached to this IntrinsicInst, intersect the<br>
     // explicit range specified by the metadata and the implicit range of<br>
     // the intrinsic.<br>
Index: include/llvm/Analysis/ValueTracking.h<br>
===================================================================<br>
--- include/llvm/Analysis/ValueTracking.h<br>
+++ include/llvm/Analysis/ValueTracking.h<br>
@@ -49,8 +49,9 @@<br>
                         const DominatorTree *DT = nullptr);<br>
   /// Compute known bits from the range metadata.<br>
   /// \p KnownZero the set of bits that are known to be zero<br>
+  /// \p KnownOne the set of bits that are known to be one<br>
   void computeKnownBitsFromRangeMetadata(const MDNode &Ranges,<br>
-                                         APInt &KnownZero);<br>
+                                         APInt &KnownZero, APInt &KnownOne);<br>
   /// Return true if LHS and RHS have no common bits set.<br>
   bool haveNoCommonBitsSet(Value *LHS, Value *RHS, const DataLayout &DL,<br>
                            AssumptionCache *AC = nullptr,<br>
<br>
<br>
</blockquote></div><br></div></div>