15
15
//
16
16
// ===----------------------------------------------------------------------===//
17
17
18
- #include " llvm/Transforms/Utils/PromoteMemToReg.h"
19
18
#include " llvm/ADT/ArrayRef.h"
20
19
#include " llvm/ADT/DenseMap.h"
21
20
#include " llvm/ADT/STLExtras.h"
22
21
#include " llvm/ADT/SmallPtrSet.h"
23
22
#include " llvm/ADT/SmallVector.h"
24
23
#include " llvm/ADT/Statistic.h"
25
24
#include " llvm/Analysis/AliasSetTracker.h"
25
+ #include " llvm/Analysis/AssumptionCache.h"
26
26
#include " llvm/Analysis/InstructionSimplify.h"
27
27
#include " llvm/Analysis/IteratedDominanceFrontier.h"
28
28
#include " llvm/Analysis/ValueTracking.h"
38
38
#include " llvm/IR/Metadata.h"
39
39
#include " llvm/IR/Module.h"
40
40
#include " llvm/Transforms/Utils/Local.h"
41
+ #include " llvm/Transforms/Utils/PromoteMemToReg.h"
41
42
#include < algorithm>
42
43
using namespace llvm ;
43
44
@@ -301,6 +302,18 @@ struct PromoteMem2Reg {
301
302
302
303
} // end of anonymous namespace
303
304
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
+
304
317
static void removeLifetimeIntrinsicUsers (AllocaInst *AI) {
305
318
// Knowing that this alloca is promotable, we know that it's safe to kill all
306
319
// instructions except for load and store.
@@ -334,9 +347,9 @@ static void removeLifetimeIntrinsicUsers(AllocaInst *AI) {
334
347
// / and thus must be phi-ed with undef. We fall back to the standard alloca
335
348
// / promotion algorithm in that case.
336
349
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 ) {
340
353
StoreInst *OnlyStore = Info.OnlyStore ;
341
354
bool StoringGlobalVal = !isa<Instruction>(OnlyStore->getOperand (0 ));
342
355
BasicBlock *StoreBB = OnlyStore->getParent ();
@@ -387,6 +400,14 @@ static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
387
400
// code.
388
401
if (ReplVal == LI)
389
402
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
+
390
411
LI->replaceAllUsesWith (ReplVal);
391
412
if (AST && LI->getType ()->isPointerTy ())
392
413
AST->deleteValue (LI);
@@ -435,7 +456,9 @@ static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
435
456
// / }
436
457
static bool promoteSingleBlockAlloca (AllocaInst *AI, const AllocaInfo &Info,
437
458
LargeBlockInfo &LBI,
438
- AliasSetTracker *AST) {
459
+ AliasSetTracker *AST,
460
+ DominatorTree &DT,
461
+ AssumptionCache *AC) {
439
462
// The trickiest case to handle is when we have large blocks. Because of this,
440
463
// this code is optimized assuming that large blocks happen. This does not
441
464
// significantly pessimize the small block case. This uses LargeBlockInfo to
@@ -476,10 +499,17 @@ static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
476
499
// There is no store before this load, bail out (load may be affected
477
500
// by the following stores - see main comment).
478
501
return false ;
479
- }
480
- else
502
+ } else {
481
503
// 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
+ }
483
513
484
514
if (AST && LI->getType ()->isPointerTy ())
485
515
AST->deleteValue (LI);
@@ -553,7 +583,7 @@ void PromoteMem2Reg::run() {
553
583
// If there is only a single store to this value, replace any loads of
554
584
// it that are directly dominated by the definition with the value stored.
555
585
if (Info.DefiningBlocks .size () == 1 ) {
556
- if (rewriteSingleStoreAlloca (AI, Info, LBI, DT, AST)) {
586
+ if (rewriteSingleStoreAlloca (AI, Info, LBI, DT, AST, AC )) {
557
587
// The alloca has been processed, move on.
558
588
RemoveFromAllocasList (AllocaNum);
559
589
++NumSingleStore;
@@ -564,7 +594,7 @@ void PromoteMem2Reg::run() {
564
594
// If the alloca is only read and written in one basic block, just perform a
565
595
// linear sweep over the block to eliminate it.
566
596
if (Info.OnlyUsedInOneBlock &&
567
- promoteSingleBlockAlloca (AI, Info, LBI, AST)) {
597
+ promoteSingleBlockAlloca (AI, Info, LBI, AST, DT, AC )) {
568
598
// The alloca has been processed, move on.
569
599
RemoveFromAllocasList (AllocaNum);
570
600
continue ;
@@ -938,6 +968,13 @@ void PromoteMem2Reg::RenamePass(BasicBlock *BB, BasicBlock *Pred,
938
968
939
969
Value *V = IncomingVals[AI->second ];
940
970
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
+
941
978
// Anything using the load now uses the current value.
942
979
LI->replaceAllUsesWith (V);
943
980
if (AST && LI->getType ()->isPointerTy ())
0 commit comments