<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>