<div dir="ltr">That's annoying. Any of you knows the best way to reproduce this locally?<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Nov 28, 2017 at 3:21 AM, Davide Italiano <span dir="ltr"><<a href="mailto:davide@freebsd.org" target="_blank">davide@freebsd.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto">Rafael is going to revert this soon as I don't have access to a machine now.</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Nov 27, 2017 5:13 PM, "Davide Italiano" <<a href="mailto:davide@freebsd.org" target="_blank">davide@freebsd.org</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto">cc: ing ariel.<div dir="auto">Matt, I can't repro this locally. Can you plwase revert while we investigate?</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Nov 27, 2017 4:03 PM, "Matt Morehouse" <<a href="mailto:mascasa@google.com" target="_blank">mascasa@google.com</a>> wrote:<br type="attribution"><blockquote class="m_-4554666398787392766m_4083902752971351750quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">This patch seems to be <a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-android/builds/5319" target="_blank">breaking</a> <a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux/builds/5900" target="_blank">several</a> <a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap-ubsan/builds/826" target="_blank">bots</a> with:<div><pre style="font-family:"Courier New",courier,monotype,monospace;color:rgb(0,0,0);font-size:medium"><span class="m_-4554666398787392766m_4083902752971351750m_-7473020265063078859gmail-stdout">clang-6.0: /var/lib/buildbot/sanitizer-bu<wbr>ildbot6/sanitizer-x86_64-linux<wbr>-android/build/llvm/lib/Transf<wbr>orms/Utils/PromoteMemoryToRegi<wbr>ster.cpp:254: SmallVector<(anonymous namespace)::GuaranteedExecutio<wbr>nRange, 4> (anonymous namespace)::LargeBlockInfo::co<wbr>mputeGEI(const llvm::BasicBlock *): Assertion `It != InstNumbers.end() && InstNo <= It->second && "missing number for interesting instruction"' failed.
</span></pre></div><div><span class="m_-4554666398787392766m_4083902752971351750m_-7473020265063078859gmail-stdout">Please take a look.</span></div></div><div class="m_-4554666398787392766m_4083902752971351750elided-text"><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Nov 27, 2017 at 1:25 PM, Davide Italiano via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: davide<br>
Date: Mon Nov 27 13:25:13 2017<br>
New Revision: 319096<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=319096&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=319096&view=rev</a><br>
Log:<br>
[SROA] Propagate !range metadata when moving loads.<br>
<br>
This tries to propagate !range metadata to a pre-existing load<br>
when a load is optimized out. This is done instead of adding an<br>
assume because converting loads to and from assumes creates a<br>
lot of IR.<br>
<br>
Patch by Ariel Ben-Yehuda.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D37216" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3721<wbr>6</a><br>
<br>
Modified:<br>
llvm/trunk/lib/Transforms/Scal<wbr>ar/SROA.cpp<br>
llvm/trunk/lib/Transforms/Util<wbr>s/Local.cpp<br>
llvm/trunk/lib/Transforms/Util<wbr>s/PromoteMemoryToRegister.cpp<br>
llvm/trunk/test/Transforms/SRO<wbr>A/preserve-nonnull.ll<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scal<wbr>ar/SROA.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SROA.cpp?rev=319096&r1=319095&r2=319096&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Scalar/SROA.cpp?rev=319096&r<wbr>1=319095&r2=319096&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/Scal<wbr>ar/SROA.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scal<wbr>ar/SROA.cpp Mon Nov 27 13:25:13 2017<br>
@@ -2455,15 +2455,10 @@ private:<br>
// are different types, for example by mapping !nonnull metadata to<br>
// !range metadata by modeling the null pointer constant converted to the<br>
// integer type.<br>
- // FIXME: Add support for range metadata here. Currently the utilities<br>
- // for this don't propagate range metadata in trivial cases from one<br>
- // integer load to another, don't handle non-addrspace-0 null pointers<br>
- // correctly, and don't have any support for mapping ranges as the<br>
- // integer type becomes winder or narrower.<br>
if (MDNode *N = LI.getMetadata(LLVMContext::MD<wbr>_nonnull))<br>
copyNonnullMetadata(LI, N, *NewLI);<br>
-<br>
- // Try to preserve nonnull metadata<br>
+ if (MDNode *N = LI.getMetadata(LLVMContext::MD<wbr>_range))<br>
+ copyRangeMetadata(DL, LI, N, *NewLI);<br>
V = NewLI;<br>
<br>
// If this is an integer load past the end of the slice (which means the<br>
@@ -3654,7 +3649,7 @@ bool SROA::presplitLoadsAndStores(A<wbr>lloca<br>
PartPtrTy, BasePtr->getName() + "."),<br>
getAdjustedAlignment(LI, PartOffset, DL), /*IsVolatile*/ false,<br>
LI->getName());<br>
- PLoad->copyMetadata(*LI, LLVMContext::MD_mem_parallel_l<wbr>oop_access);<br>
+ PLoad->copyMetadata(*LI, LLVMContext::MD_mem_parallel_l<wbr>oop_access);<br>
<br>
// Append this load onto the list of split loads so we can find it later<br>
// to rewrite the stores.<br>
<br>
Modified: llvm/trunk/lib/Transforms/Util<wbr>s/Local.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=319096&r1=319095&r2=319096&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Utils/Local.cpp?rev=319096&r<wbr>1=319095&r2=319096&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/Util<wbr>s/Local.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Util<wbr>s/Local.cpp Mon Nov 27 13:25:13 2017<br>
@@ -1947,18 +1947,24 @@ void llvm::copyNonnullMetadata(cons<wbr>t Loa<br>
void llvm::copyRangeMetadata(const DataLayout &DL, const LoadInst &OldLI,<br>
MDNode *N, LoadInst &NewLI) {<br>
auto *NewTy = NewLI.getType();<br>
+ auto *OldTy = OldLI.getType();<br>
<br>
- // Give up unless it is converted to a pointer where there is a single very<br>
- // valuable mapping we can do reliably.<br>
- // FIXME: It would be nice to propagate this in more ways, but the type<br>
- // conversions make it hard.<br>
- if (!NewTy->isPointerTy())<br>
+ if (DL.getTypeStoreSizeInBits(New<wbr>Ty) == DL.getTypeSizeInBits(OldTy) &&<br>
+ NewTy->isIntegerTy()) {<br>
+ // An integer with the same number of bits - give it the range<br>
+ // metadata!.<br>
+ NewLI.setMetadata(LLVMContext:<wbr>:MD_range, N);<br>
return;<br>
+ }<br>
<br>
- unsigned BitWidth = DL.getTypeSizeInBits(NewTy);<br>
- if (!getConstantRangeFromMetadata<wbr>(*N).contains(APInt(BitWidth, 0))) {<br>
- MDNode *NN = MDNode::get(OldLI.getContext()<wbr>, None);<br>
- NewLI.setMetadata(LLVMContext:<wbr>:MD_nonnull, NN);<br>
+ if (NewTy->isPointerTy()) {<br>
+ // Try to convert the !range metadata to !nonnull metadata on the<br>
+ // new pointer.<br>
+ unsigned BitWidth = DL.getTypeSizeInBits(NewTy);<br>
+ if (!getConstantRangeFromMetadata<wbr>(*N).contains(APInt(BitWidth, 0))) {<br>
+ MDNode *NN = MDNode::get(OldLI.getContext()<wbr>, None);<br>
+ NewLI.setMetadata(LLVMContext:<wbr>:MD_nonnull, NN);<br>
+ }<br>
}<br>
}<br>
<br>
<br>
Modified: llvm/trunk/lib/Transforms/Util<wbr>s/PromoteMemoryToRegister.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp?rev=319096&r1=319095&r2=319096&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Utils/PromoteMemoryToRegiste<wbr>r.cpp?rev=319096&r1=319095&r2=<wbr>319096&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/Util<wbr>s/PromoteMemoryToRegister.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Util<wbr>s/PromoteMemoryToRegister.cpp Mon Nov 27 13:25:13 2017<br>
@@ -17,6 +17,7 @@<br>
<br>
#include "llvm/ADT/ArrayRef.h"<br>
#include "llvm/ADT/DenseMap.h"<br>
+#include "llvm/ADT/Optional.h"<br>
#include "llvm/ADT/STLExtras.h"<br>
#include "llvm/ADT/SmallPtrSet.h"<br>
#include "llvm/ADT/SmallVector.h"<br>
@@ -48,7 +49,7 @@<br>
#include "llvm/Transforms/Utils/Local.h<wbr>"<br>
#include "llvm/Transforms/Utils/Promote<wbr>MemToReg.h"<br>
#include <algorithm><br>
-#include <cassert><br>
+<br>
#include <iterator><br>
#include <utility><br>
#include <vector><br>
@@ -177,6 +178,16 @@ public:<br>
ValVector Values;<br>
};<br>
<br>
+/// \brief Semi-open interval of instructions that are guaranteed to<br>
+/// all execute if the first one does.<br>
+class GuaranteedExecutionRange {<br>
+public:<br>
+ unsigned Start;<br>
+ unsigned End;<br>
+<br>
+ GuaranteedExecutionRange(unsig<wbr>ned S, unsigned E): Start(S), End(E) {}<br>
+};<br>
+<br>
/// \brief This assigns and keeps a per-bb relative ordering of load/store<br>
/// instructions in the block that directly load or store an alloca.<br>
///<br>
@@ -190,14 +201,109 @@ class LargeBlockInfo {<br>
/// the block.<br>
DenseMap<const Instruction *, unsigned> InstNumbers;<br>
<br>
+ /// \brief For each basic block we track, keep track of the intervals<br>
+ /// of instruction numbers of instructions that transfer control<br>
+ /// to their successors, for propagating metadata.<br>
+ DenseMap<const BasicBlock *, Optional<SmallVector<Guarantee<wbr>dExecutionRange, 4>>><br>
+ GuaranteedExecutionIntervals;<br>
+<br>
public:<br>
<br>
- /// This code only looks at accesses to allocas.<br>
+ /// This code looks for stores to allocas, and for loads both for<br>
+ /// allocas and for transferring metadata.<br>
static bool isInterestingInstruction(const Instruction *I) {<br>
- return (isa<LoadInst>(I) && isa<AllocaInst>(I->getOperand(<wbr>0))) ||<br>
+ return isa<LoadInst>(I) ||<br>
(isa<StoreInst>(I) && isa<AllocaInst>(I->getOperand(<wbr>1)));<br>
}<br>
<br>
+ /// Compute the GuaranteedExecutionIntervals for a given BB.<br>
+ ///<br>
+ /// This is valid and remains valid as long as each interesting<br>
+ /// instruction (see isInterestingInstruction) that<br>
+ /// A) existed when this LBI was cleared<br>
+ /// B) has not been deleted (deleting interesting instructions is fine)<br>
+ /// are run in the same program executions and in the same order<br>
+ /// as when this LBI was cleared.<br>
+ ///<br>
+ /// Because `PromoteMemoryToRegister` does not move memory loads at<br>
+ /// all, this assumption is satisfied in this pass.<br>
+ SmallVector<GuaranteedExecutio<wbr>nRange, 4> computeGEI(const BasicBlock *BB) {<br>
+ SmallVector<GuaranteedExecutio<wbr>nRange, 4> GuaranteedExecutionIntervals;<br>
+<br>
+ unsigned InstNo = 0;<br>
+ bool InRange = false;<br>
+ unsigned FirstInstInRange = 0;<br>
+ for (const Instruction &BBI : *BB) {<br>
+ if (isGuaranteedToTransferExecuti<wbr>onToSuccessor(&BBI)) {<br>
+ if (!InRange && isInterestingInstruction(&BBI)<wbr>) {<br>
+ InRange = true;<br>
+ FirstInstInRange = InstNo;<br>
+ }<br>
+ } else {<br>
+ if (InRange) {<br>
+ assert(FirstInstInRange < InstNo && "Can't push an empty range here.");<br>
+ GuaranteedExecutionIntervals.e<wbr>mplace_back(FirstInstInRange, InstNo);<br>
+ }<br>
+ InRange = false;<br>
+ }<br>
+<br>
+ if (isInterestingInstruction(&BBI<wbr>)) {<br>
+ auto It = InstNumbers.find(&BBI);<br>
+ assert(It != InstNumbers.end() &&<br>
+ InstNo <= It->second &&<br>
+ "missing number for interesting instruction");<br>
+ InstNo = It->second + 1;<br>
+ }<br>
+ }<br>
+<br>
+ if (InRange) {<br>
+ assert(FirstInstInRange < InstNo && "Can't push an empty range here.");<br>
+ GuaranteedExecutionIntervals.e<wbr>mplace_back(FirstInstInRange, InstNo);<br>
+ }<br>
+<br>
+ return GuaranteedExecutionIntervals;<br>
+ }<br>
+<br>
+ /// Return true if, when CxtI executes, it is guaranteed that either<br>
+ /// I had executed already or that I is guaranteed to be later executed.<br>
+ ///<br>
+ /// The useful property this guarantees is that if I exhibits undefined<br>
+ /// behavior under some circumstances, then the whole program will exhibit<br>
+ /// undefined behavior at CxtI.<br>
+ bool isGuaranteedToBeExecuted(const Instruction *CxtI, const Instruction *I) {<br>
+ const BasicBlock *BB = CxtI->getParent();<br>
+<br>
+ if (BB != I->getParent()) {<br>
+ // Instructions in different basic blocks, so control flow<br>
+ // can diverge between them (we could track this with<br>
+ // postdoms, but we don't bother).<br>
+ return false;<br>
+ }<br>
+<br>
+ unsigned Index1 = getInstructionIndex(CxtI);<br>
+ unsigned Index2 = getInstructionIndex(I);<br>
+<br>
+ auto& BBGEI = GuaranteedExecutionIntervals[B<wbr>B];<br>
+ if (!BBGEI.hasValue()) {<br>
+ BBGEI.emplace(computeGEI(BB));<br>
+ }<br>
+<br>
+ // We want to check whether I and CxtI are in the same range. To do that,<br>
+ // we notice that CxtI can only be in the first range R where<br>
+ // CxtI.end < R.end. If we find that range using binary search,<br>
+ // we can check whether I and CxtI are both in it.<br>
+ GuaranteedExecutionRange Bound(Index1, Index1);<br>
+ auto R = std::upper_bound(<br>
+ BBGEI->begin(), BBGEI->end(), Bound,<br>
+ [](GuaranteedExecutionRange I_, GuaranteedExecutionRange R) {<br>
+ return I_.End < R.End;<br>
+ });<br>
+<br>
+ return R != BBGEI->end() &&<br>
+ R->Start <= Index1 && Index1 < R->End &&<br>
+ R->Start <= Index2 && Index2 < R->End;<br>
+ }<br>
+<br>
/// Get or calculate the index of the specified instruction.<br>
unsigned getInstructionIndex(const Instruction *I) {<br>
assert(isInterestingInstructi<wbr>on(I) &&<br>
@@ -213,9 +319,11 @@ public:<br>
// avoid gratuitus rescans.<br>
const BasicBlock *BB = I->getParent();<br>
unsigned InstNo = 0;<br>
+ GuaranteedExecutionIntervals.e<wbr>rase(BB);<br>
for (const Instruction &BBI : *BB)<br>
if (isInterestingInstruction(&BBI<wbr>))<br>
InstNumbers[&BBI] = InstNo++;<br>
+<br>
It = InstNumbers.find(I);<br>
<br>
assert(It != InstNumbers.end() && "Didn't insert instruction?");<br>
@@ -224,7 +332,10 @@ public:<br>
<br>
void deleteValue(const Instruction *I) { InstNumbers.erase(I); }<br>
<br>
- void clear() { InstNumbers.clear(); }<br>
+ void clear() {<br>
+ InstNumbers.clear();<br>
+ GuaranteedExecutionIntervals.c<wbr>lear();<br>
+ }<br>
};<br>
<br>
struct PromoteMem2Reg {<br>
@@ -303,6 +414,7 @@ private:<br>
SmallPtrSetImpl<BasicBlock *> &LiveInBlocks);<br>
void RenamePass(BasicBlock *BB, BasicBlock *Pred,<br>
RenamePassData::ValVector &IncVals,<br>
+ LargeBlockInfo &LBI,<br>
std::vector<RenamePassData> &Worklist);<br>
bool QueuePhiNode(BasicBlock *BB, unsigned AllocaIdx, unsigned &Version);<br>
};<br>
@@ -321,6 +433,32 @@ static void addAssumeNonNull(AssumptionC<br>
AC->registerAssumption(CI);<br>
}<br>
<br>
+static void addAssumptionsFromMetadata(Loa<wbr>dInst *LI,<br>
+ Value *ReplVal,<br>
+ DominatorTree &DT,<br>
+ const DataLayout &DL,<br>
+ LargeBlockInfo &LBI,<br>
+ AssumptionCache *AC)<br>
+{<br>
+ if (LI->getMetadata(LLVMContext::<wbr>MD_nonnull) &&<br>
+ !isKnownNonZero(ReplVal, DL, 0, AC, LI, &DT)) {<br>
+ addAssumeNonNull(AC, LI);<br>
+ }<br>
+<br>
+ if (auto *N = LI->getMetadata(LLVMContext::M<wbr>D_range)) {<br>
+ // Range metadata is harder to use as an assumption,<br>
+ // so don't try to add one, but *do* try to copy<br>
+ // the metadata to a load in the same BB.<br>
+ if (LoadInst *NewLI = dyn_cast<LoadInst>(ReplVal)) {<br>
+ DEBUG(dbgs() << "trying to move !range metadata from" <<<br>
+ *LI << " to" << *NewLI << "\n");<br>
+ if (LBI.isGuaranteedToBeExecuted(<wbr>LI, NewLI)) {<br>
+ copyRangeMetadata(DL, *LI, N, *NewLI);<br>
+ }<br>
+ }<br>
+ }<br>
+}<br>
+<br>
static void removeLifetimeIntrinsicUsers(A<wbr>llocaInst *AI) {<br>
// Knowing that this alloca is promotable, we know that it's safe to kill all<br>
// instructions except for load and store.<br>
@@ -409,9 +547,7 @@ static bool rewriteSingleStoreAlloca(All<br>
// If the load was marked as nonnull we don't want to lose<br>
// that information when we erase this Load. So we preserve<br>
// it with an assume.<br>
- if (AC && LI->getMetadata(LLVMContext::M<wbr>D_nonnull) &&<br>
- !isKnownNonZero(ReplVal, DL, 0, AC, LI, &DT))<br>
- addAssumeNonNull(AC, LI);<br>
+ addAssumptionsFromMetadata(LI, ReplVal, DT, DL, LBI, AC);<br>
<br>
LI->replaceAllUsesWith(ReplVa<wbr>l);<br>
LI->eraseFromParent();<br>
@@ -505,9 +641,7 @@ static bool promoteSingleBlockAlloca(All<br>
// Note, if the load was marked as nonnull we don't want to lose that<br>
// information when we erase it. So we preserve it with an assume.<br>
Value *ReplVal = std::prev(I)->second->getOpera<wbr>nd(0);<br>
- if (AC && LI->getMetadata(LLVMContext::M<wbr>D_nonnull) &&<br>
- !isKnownNonZero(ReplVal, DL, 0, AC, LI, &DT))<br>
- addAssumeNonNull(AC, LI);<br>
+ addAssumptionsFromMetadata(LI, ReplVal, DT, DL, LBI, AC);<br>
<br>
LI->replaceAllUsesWith(ReplVa<wbr>l);<br>
}<br>
@@ -643,7 +777,6 @@ void PromoteMem2Reg::run() {<br>
<br>
if (Allocas.empty())<br>
return; // All of the allocas must have been trivial!<br>
-<br>
LBI.clear();<br>
<br>
// Set the incoming values for the basic block to be null values for all of<br>
@@ -661,9 +794,10 @@ void PromoteMem2Reg::run() {<br>
RenamePassData RPD = std::move(RenamePassWorkList.b<wbr>ack());<br>
RenamePassWorkList.pop_back()<wbr>;<br>
// RenamePass may add new worklist entries.<br>
- RenamePass(<a href="http://RPD.BB" rel="noreferrer" target="_blank">RPD.BB</a>, RPD.Pred, RPD.Values, RenamePassWorkList);<br>
+ RenamePass(<a href="http://RPD.BB" rel="noreferrer" target="_blank">RPD.BB</a>, RPD.Pred, RPD.Values, LBI, RenamePassWorkList);<br>
} while (!RenamePassWorkList.empty());<br>
<br>
+ LBI.clear();<br>
// The renamer uses the Visited set to avoid infinite loops. Clear it now.<br>
Visited.clear();<br>
<br>
@@ -875,6 +1009,7 @@ bool PromoteMem2Reg::QueuePhiNode(B<wbr>asicB<br>
/// predecessor block Pred.<br>
void PromoteMem2Reg::RenamePass(Bas<wbr>icBlock *BB, BasicBlock *Pred,<br>
RenamePassData::ValVector &IncomingVals,<br>
+ LargeBlockInfo &LBI,<br>
std::vector<RenamePassData> &Worklist) {<br>
NextIteration:<br>
// If we are inserting any phi nodes into this BB, they will already be in the<br>
@@ -941,13 +1076,12 @@ NextIteration:<br>
// If the load was marked as nonnull we don't want to lose<br>
// that information when we erase this Load. So we preserve<br>
// it with an assume.<br>
- if (AC && LI->getMetadata(LLVMContext::M<wbr>D_nonnull) &&<br>
- !isKnownNonZero(V, SQ.DL, 0, AC, LI, &DT))<br>
- addAssumeNonNull(AC, LI);<br>
+ addAssumptionsFromMetadata(LI, V, DT, SQ.DL, LBI, AC);<br>
<br>
// Anything using the load now uses the current value.<br>
LI->replaceAllUsesWith(V);<br>
BB->getInstList().erase(LI);<br>
+ LBI.deleteValue(LI);<br>
} else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {<br>
// Delete this instruction and mark the name as the current holder of the<br>
// value<br>
@@ -965,6 +1099,7 @@ NextIteration:<br>
for (DbgInfoIntrinsic *DII : AllocaDbgDeclares[ai->second])<br>
ConvertDebugDeclareToDebugVal<wbr>ue(DII, SI, DIB);<br>
BB->getInstList().erase(SI);<br>
+ LBI.deleteValue(SI);<br>
}<br>
}<br>
<br>
<br>
Modified: llvm/trunk/test/Transforms/SRO<wbr>A/preserve-nonnull.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SROA/preserve-nonnull.ll?rev=319096&r1=319095&r2=319096&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/Transfor<wbr>ms/SROA/preserve-nonnull.ll?re<wbr>v=319096&r1=319095&r2=319096&v<wbr>iew=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/SRO<wbr>A/preserve-nonnull.ll (original)<br>
+++ llvm/trunk/test/Transforms/SRO<wbr>A/preserve-nonnull.ll Mon Nov 27 13:25:13 2017<br>
@@ -3,6 +3,8 @@<br>
; Make sure that SROA doesn't lose nonnull metadata<br>
; on loads from allocas that get optimized out.<br>
<br>
+%pair = type { i64, [0 x i64], [1 x i64] }<br>
+<br>
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1)<br>
<br>
; Check that we do basic propagation of nonnull when rewriting.<br>
@@ -42,6 +44,23 @@ entry:<br>
ret float* %ret<br>
}<br>
<br>
+; Make sure we propagate the !range attribute when we expand loads.<br>
+define i64 @propagate_range(%pair* dereferenceable(16)) {<br>
+; CHECK-LABEL: define i64 @propagate_range(<br>
+; CHECK-NEXT: start:<br>
+; CHECK-NEXT: %[[SROA_IDX:.*]] = getelementptr inbounds %pair<br>
+; CHECK-NEXT: %[[RESULT:.*]] = load i64, i64* %[[SROA_IDX]], align 8, !range !1<br>
+; CHECK: ret i64 %[[RESULT]]<br>
+start:<br>
+ %a = alloca %pair<br>
+ %1 = bitcast %pair* %0 to i8*<br>
+ %2 = bitcast %pair* %a to i8*<br>
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* %1, i64 16, i32 8, i1 false)<br>
+ %3 = getelementptr inbounds %pair, %pair* %a, i32 0, i32 0<br>
+ %4 = load i64, i64* %3, !range !1<br>
+ ret i64 %4<br>
+}<br>
+<br>
; Make sure we properly handle the !nonnull attribute when we convert<br>
; a pointer load to an integer load.<br>
; FIXME: While this doesn't do anythnig actively harmful today, it really<br>
@@ -90,3 +109,4 @@ entry:<br>
}<br>
<br>
!0 = !{}<br>
+!1 = !{i64 0, i64 2}<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</div></blockquote></div><br></div>
</blockquote></div></div>
</div></div></blockquote></div><br></div>