<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 26 October 2015 at 19:49, 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"><span class=""><br>
<br>
Nick Lewycky wrote:<br>
> On 26 October 2015 at 18:46, Sanjoy Das <<a href="mailto:sanjoy@playingwithpointers.com" target="_blank">sanjoy@playingwithpointers.com</a><br></span><span class="">
> <mailto:<a href="mailto:sanjoy@playingwithpointers.com" target="_blank">sanjoy@playingwithpointers.com</a>>> wrote:<br>
><br>
>     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>
><br>
><br>
> I think that's overly specialized. If you have a range of i8 [64..127]<br>
> then you know the top two bits are '01'.<br>
<br></span>
How about:<br>
<br>
  for R in MD.ranges() { // now I wish we had a range iterator for this :P<br>
    find N such that the highest N bits are common between R.unsignedMin and R.unsignedMax<br>
    KnownZero &= bitmask with zeroes in R.unsignedMax[BitWidth..N] set to 1<br>
    KnownOne  &= bitmask with ones in R.unsignedMax[BitWidth..N] set to 1<br>
  }<br>
<br>
?</blockquote><div><br></div><div>Just double-checking, given a range that's wrapping, unsignedMin/Max will return 0 and uintmax, right? If so, that logic sounds correct to me!</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">
>     <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 -<br>
>     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 =<br>
>     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<br>
>     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 =<br>
>     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 =<br>
>     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,<br>
>     intersect the<br>
>           // explicit range specified by the metadata and the implicit<br>
>     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<br>
>     &KnownOne);<br>
>         /// Return true if LHS and RHS have no common bits set.<br>
>         bool haveNoCommonBitsSet(Value *LHS, Value *RHS, const<br>
>     DataLayout &DL,<br>
>                                  AssumptionCache *AC = nullptr,<br>
><br>
><br>
><br>
</div></div></blockquote></div></div></div>