Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 0028e44

Browse files
committed
Preserve nonnull metadata on Loads through SROA & mem2reg.
Summary: https://llvm.org/bugs/show_bug.cgi?id=31142 : SROA was dropping the nonnull metadata on loads from allocas that got optimized out. This patch simply preserves nonnull metadata on loads through SROA and mem2reg. Reviewers: chandlerc, efriedma Reviewed By: efriedma Subscribers: hfinkel, spatel, efriedma, arielb1, davide, llvm-commits Differential Revision: https://reviews.llvm.org/D27114 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298540 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 6d53d18 commit 0028e44

File tree

4 files changed

+166
-10
lines changed

4 files changed

+166
-10
lines changed

lib/Transforms/Scalar/SROA.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -2390,6 +2390,10 @@ class llvm::sroa::AllocaSliceRewriter
23902390
LI.isVolatile(), LI.getName());
23912391
if (LI.isVolatile())
23922392
NewLI->setAtomic(LI.getOrdering(), LI.getSynchScope());
2393+
2394+
// Try to preserve nonnull metadata
2395+
if (TargetTy->isPointerTy())
2396+
NewLI->copyMetadata(LI, LLVMContext::MD_nonnull);
23932397
V = NewLI;
23942398

23952399
// If this is an integer load past the end of the slice (which means the

lib/Transforms/Utils/PromoteMemoryToRegister.cpp

+47-10
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717

18-
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
1918
#include "llvm/ADT/ArrayRef.h"
2019
#include "llvm/ADT/DenseMap.h"
2120
#include "llvm/ADT/STLExtras.h"
2221
#include "llvm/ADT/SmallPtrSet.h"
2322
#include "llvm/ADT/SmallVector.h"
2423
#include "llvm/ADT/Statistic.h"
2524
#include "llvm/Analysis/AliasSetTracker.h"
25+
#include "llvm/Analysis/AssumptionCache.h"
2626
#include "llvm/Analysis/InstructionSimplify.h"
2727
#include "llvm/Analysis/IteratedDominanceFrontier.h"
2828
#include "llvm/Analysis/ValueTracking.h"
@@ -38,6 +38,7 @@
3838
#include "llvm/IR/Metadata.h"
3939
#include "llvm/IR/Module.h"
4040
#include "llvm/Transforms/Utils/Local.h"
41+
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
4142
#include <algorithm>
4243
using namespace llvm;
4344

@@ -301,6 +302,18 @@ struct PromoteMem2Reg {
301302

302303
} // end of anonymous namespace
303304

305+
/// Given a LoadInst LI this adds assume(LI != null) after it.
306+
static void addAssumeNonNull(AssumptionCache *AC, LoadInst *LI) {
307+
Function *AssumeIntrinsic =
308+
Intrinsic::getDeclaration(LI->getModule(), Intrinsic::assume);
309+
ICmpInst *LoadNotNull = new ICmpInst(ICmpInst::ICMP_NE, LI,
310+
Constant::getNullValue(LI->getType()));
311+
LoadNotNull->insertAfter(LI);
312+
CallInst *CI = CallInst::Create(AssumeIntrinsic, {LoadNotNull});
313+
CI->insertAfter(LoadNotNull);
314+
AC->registerAssumption(CI);
315+
}
316+
304317
static void removeLifetimeIntrinsicUsers(AllocaInst *AI) {
305318
// Knowing that this alloca is promotable, we know that it's safe to kill all
306319
// instructions except for load and store.
@@ -334,9 +347,9 @@ static void removeLifetimeIntrinsicUsers(AllocaInst *AI) {
334347
/// and thus must be phi-ed with undef. We fall back to the standard alloca
335348
/// promotion algorithm in that case.
336349
static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
337-
LargeBlockInfo &LBI,
338-
DominatorTree &DT,
339-
AliasSetTracker *AST) {
350+
LargeBlockInfo &LBI, DominatorTree &DT,
351+
AliasSetTracker *AST,
352+
AssumptionCache *AC) {
340353
StoreInst *OnlyStore = Info.OnlyStore;
341354
bool StoringGlobalVal = !isa<Instruction>(OnlyStore->getOperand(0));
342355
BasicBlock *StoreBB = OnlyStore->getParent();
@@ -387,6 +400,14 @@ static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
387400
// code.
388401
if (ReplVal == LI)
389402
ReplVal = UndefValue::get(LI->getType());
403+
404+
// If the load was marked as nonnull we don't want to lose
405+
// that information when we erase this Load. So we preserve
406+
// it with an assume.
407+
if (AC && LI->getMetadata(LLVMContext::MD_nonnull) &&
408+
!llvm::isKnownNonNullAt(ReplVal, LI, &DT))
409+
addAssumeNonNull(AC, LI);
410+
390411
LI->replaceAllUsesWith(ReplVal);
391412
if (AST && LI->getType()->isPointerTy())
392413
AST->deleteValue(LI);
@@ -435,7 +456,9 @@ static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
435456
/// }
436457
static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
437458
LargeBlockInfo &LBI,
438-
AliasSetTracker *AST) {
459+
AliasSetTracker *AST,
460+
DominatorTree &DT,
461+
AssumptionCache *AC) {
439462
// The trickiest case to handle is when we have large blocks. Because of this,
440463
// this code is optimized assuming that large blocks happen. This does not
441464
// significantly pessimize the small block case. This uses LargeBlockInfo to
@@ -476,10 +499,17 @@ static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
476499
// There is no store before this load, bail out (load may be affected
477500
// by the following stores - see main comment).
478501
return false;
479-
}
480-
else
502+
} else {
481503
// Otherwise, there was a store before this load, the load takes its value.
482-
LI->replaceAllUsesWith(std::prev(I)->second->getOperand(0));
504+
// Note, if the load was marked as nonnull we don't want to lose that
505+
// information when we erase it. So we preserve it with an assume.
506+
Value *ReplVal = std::prev(I)->second->getOperand(0);
507+
if (AC && LI->getMetadata(LLVMContext::MD_nonnull) &&
508+
!llvm::isKnownNonNullAt(ReplVal, LI, &DT))
509+
addAssumeNonNull(AC, LI);
510+
511+
LI->replaceAllUsesWith(ReplVal);
512+
}
483513

484514
if (AST && LI->getType()->isPointerTy())
485515
AST->deleteValue(LI);
@@ -553,7 +583,7 @@ void PromoteMem2Reg::run() {
553583
// If there is only a single store to this value, replace any loads of
554584
// it that are directly dominated by the definition with the value stored.
555585
if (Info.DefiningBlocks.size() == 1) {
556-
if (rewriteSingleStoreAlloca(AI, Info, LBI, DT, AST)) {
586+
if (rewriteSingleStoreAlloca(AI, Info, LBI, DT, AST, AC)) {
557587
// The alloca has been processed, move on.
558588
RemoveFromAllocasList(AllocaNum);
559589
++NumSingleStore;
@@ -564,7 +594,7 @@ void PromoteMem2Reg::run() {
564594
// If the alloca is only read and written in one basic block, just perform a
565595
// linear sweep over the block to eliminate it.
566596
if (Info.OnlyUsedInOneBlock &&
567-
promoteSingleBlockAlloca(AI, Info, LBI, AST)) {
597+
promoteSingleBlockAlloca(AI, Info, LBI, AST, DT, AC)) {
568598
// The alloca has been processed, move on.
569599
RemoveFromAllocasList(AllocaNum);
570600
continue;
@@ -938,6 +968,13 @@ void PromoteMem2Reg::RenamePass(BasicBlock *BB, BasicBlock *Pred,
938968

939969
Value *V = IncomingVals[AI->second];
940970

971+
// If the load was marked as nonnull we don't want to lose
972+
// that information when we erase this Load. So we preserve
973+
// it with an assume.
974+
if (AC && LI->getMetadata(LLVMContext::MD_nonnull) &&
975+
!llvm::isKnownNonNullAt(V, LI, &DT))
976+
addAssumeNonNull(AC, LI);
977+
941978
// Anything using the load now uses the current value.
942979
LI->replaceAllUsesWith(V);
943980
if (AST && LI->getType()->isPointerTy())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
; RUN: opt < %s -mem2reg -S | FileCheck %s
2+
3+
; This tests that mem2reg preserves the !nonnull metadata on loads
4+
; from allocas that get optimized out.
5+
6+
; Check the case where the alloca in question has a single store.
7+
define float* @single_store(float** %arg) {
8+
; CHECK-LABEL: define float* @single_store
9+
; CHECK: %arg.load = load float*, float** %arg, align 8
10+
; CHECK: [[ASSUME:%(.*)]] = icmp ne float* %arg.load, null
11+
; CHECK: call void @llvm.assume(i1 {{.*}}[[ASSUME]])
12+
; CHECK: ret float* %arg.load
13+
entry:
14+
%buf = alloca float*
15+
%arg.load = load float*, float** %arg, align 8
16+
store float* %arg.load, float** %buf, align 8
17+
%buf.load = load float*, float **%buf, !nonnull !0
18+
ret float* %buf.load
19+
}
20+
21+
; Check the case where the alloca in question has more than one
22+
; store but still within one basic block.
23+
define float* @single_block(float** %arg) {
24+
; CHECK-LABEL: define float* @single_block
25+
; CHECK: %arg.load = load float*, float** %arg, align 8
26+
; CHECK: [[ASSUME:%(.*)]] = icmp ne float* %arg.load, null
27+
; CHECK: call void @llvm.assume(i1 {{.*}}[[ASSUME]])
28+
; CHECK: ret float* %arg.load
29+
entry:
30+
%buf = alloca float*
31+
%arg.load = load float*, float** %arg, align 8
32+
store float* null, float** %buf, align 8
33+
store float* %arg.load, float** %buf, align 8
34+
%buf.load = load float*, float **%buf, !nonnull !0
35+
ret float* %buf.load
36+
}
37+
38+
; Check the case where the alloca in question has more than one
39+
; store and also reads ands writes in multiple blocks.
40+
define float* @multi_block(float** %arg) {
41+
; CHECK-LABEL: define float* @multi_block
42+
; CHECK-LABEL: entry:
43+
; CHECK: %arg.load = load float*, float** %arg, align 8
44+
; CHECK: br label %next
45+
; CHECK-LABEL: next:
46+
; CHECK: [[ASSUME:%(.*)]] = icmp ne float* %arg.load, null
47+
; CHECK: call void @llvm.assume(i1 {{.*}}[[ASSUME]])
48+
; CHECK: ret float* %arg.load
49+
entry:
50+
%buf = alloca float*
51+
%arg.load = load float*, float** %arg, align 8
52+
store float* null, float** %buf, align 8
53+
br label %next
54+
next:
55+
store float* %arg.load, float** %buf, align 8
56+
%buf.load = load float*, float** %buf, !nonnull !0
57+
ret float* %buf.load
58+
}
59+
60+
; Check that we don't add an assume if it's not
61+
; necessary i.e. the value is already implied to be nonnull
62+
define float* @no_assume(float** %arg) {
63+
; CHECK-LABEL: define float* @no_assume
64+
; CHECK-LABEL: entry:
65+
; CHECK: %arg.load = load float*, float** %arg, align 8
66+
; CHECK: %cn = icmp ne float* %arg.load, null
67+
; CHECK: br i1 %cn, label %next, label %fin
68+
; CHECK-LABEL: next:
69+
; CHECK-NOT: call void @llvm.assume
70+
; CHECK: ret float* %arg.load
71+
; CHECK-LABEL: fin:
72+
; CHECK: ret float* null
73+
entry:
74+
%buf = alloca float*
75+
%arg.load = load float*, float** %arg, align 8
76+
%cn = icmp ne float* %arg.load, null
77+
br i1 %cn, label %next, label %fin
78+
next:
79+
; At this point the above nonnull check ensures that
80+
; the value %arg.load is nonnull in this block and thus
81+
; we need not add the assume.
82+
store float* %arg.load, float** %buf, align 8
83+
%buf.load = load float*, float** %buf, !nonnull !0
84+
ret float* %buf.load
85+
fin:
86+
ret float* null
87+
}
88+
89+
!0 = !{}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; RUN: opt < %s -sroa -S | FileCheck %s
2+
;
3+
; Make sure that SROA doesn't lose nonnull metadata
4+
; on loads from allocas that get optimized out.
5+
6+
; CHECK-LABEL: define float* @yummy_nonnull
7+
; CHECK: [[RETURN:%(.*)]] = load float*, float** %arg, align 8
8+
; CHECK: [[ASSUME:%(.*)]] = icmp ne float* {{.*}}[[RETURN]], null
9+
; CHECK: call void @llvm.assume(i1 {{.*}}[[ASSUME]])
10+
; CHECK: ret float* {{.*}}[[RETURN]]
11+
12+
define float* @yummy_nonnull(float** %arg) {
13+
entry-block:
14+
%buf = alloca float*
15+
16+
%_arg_i8 = bitcast float** %arg to i8*
17+
%_buf_i8 = bitcast float** %buf to i8*
18+
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %_buf_i8, i8* %_arg_i8, i64 8, i32 8, i1 false)
19+
20+
%ret = load float*, float** %buf, align 8, !nonnull !0
21+
ret float* %ret
22+
}
23+
24+
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1)
25+
26+
!0 = !{}

0 commit comments

Comments
 (0)