From d801c10de6cd1760f0994452c0e78156782d9fca Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Sat, 28 Nov 2009 21:27:49 +0000 Subject: [PATCH] Teach memdep to look for memory use intrinsics during dependency queries. Fixes PR5574. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@90045 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/MemoryDependenceAnalysis.cpp | 39 ++++++++++++++----- .../DeadStoreElimination/lifetime.ll | 20 +++++++++- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp index 4cbb62790d8..eec6d6bb11c 100644 --- a/lib/Analysis/MemoryDependenceAnalysis.cpp +++ b/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -201,7 +201,7 @@ getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad, // If we reach a lifetime begin or end marker, then the query ends here // because the value is undefined. } else if (II->getIntrinsicID() == Intrinsic::lifetime_start || - II->getIntrinsicID() == Intrinsic::lifetime_end) { + II->getIntrinsicID() == Intrinsic::lifetime_end) { uint64_t invariantSize = ~0ULL; if (ConstantInt *CI = dyn_cast(II->getOperand(1))) invariantSize = CI->getZExtValue(); @@ -369,20 +369,41 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) { // calls to free() erase the entire structure, not just a field. MemSize = ~0UL; } else if (isa(QueryInst) || isa(QueryInst)) { - CallSite QueryCS = CallSite::get(QueryInst); - bool isReadOnly = AA->onlyReadsMemory(QueryCS); - LocalCache = getCallSiteDependencyFrom(QueryCS, isReadOnly, ScanPos, - QueryParent); + int IntrinsicID = 0; // Intrinsic IDs start at 1. + if (IntrinsicInst *II = dyn_cast(QueryInst)) + IntrinsicID = II->getIntrinsicID(); + + switch (IntrinsicID) { + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::invariant_start: + MemPtr = QueryInst->getOperand(2); + MemSize = cast(QueryInst->getOperand(1))->getZExtValue(); + break; + case Intrinsic::invariant_end: + MemPtr = QueryInst->getOperand(3); + MemSize = cast(QueryInst->getOperand(2))->getZExtValue(); + break; + default: + CallSite QueryCS = CallSite::get(QueryInst); + bool isReadOnly = AA->onlyReadsMemory(QueryCS); + LocalCache = getCallSiteDependencyFrom(QueryCS, isReadOnly, ScanPos, + QueryParent); + } } else { // Non-memory instruction. LocalCache = MemDepResult::getClobber(--BasicBlock::iterator(ScanPos)); } // If we need to do a pointer scan, make it happen. - if (MemPtr) - LocalCache = getPointerDependencyFrom(MemPtr, MemSize, - isa(QueryInst), - ScanPos, QueryParent); + if (MemPtr) { + bool isLoad = !QueryInst->mayWriteToMemory(); + if (IntrinsicInst *II = dyn_cast(QueryInst)) { + isLoad |= II->getIntrinsicID() == Intrinsic::lifetime_end; + } + LocalCache = getPointerDependencyFrom(MemPtr, MemSize, isLoad, ScanPos, + QueryParent); + } // Remember the result! if (Instruction *I = LocalCache.getInst()) diff --git a/test/Transforms/DeadStoreElimination/lifetime.ll b/test/Transforms/DeadStoreElimination/lifetime.ll index b2da790db27..fd127d9f51b 100644 --- a/test/Transforms/DeadStoreElimination/lifetime.ll +++ b/test/Transforms/DeadStoreElimination/lifetime.ll @@ -1,6 +1,9 @@ ; RUN: opt -S -dse < %s | FileCheck %s -declare void @llvm.lifetime.end(i64, i8*) +target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" + +declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind +declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind declare void @llvm.memset.i8(i8*, i8, i8, i32) define void @test1() { @@ -17,3 +20,18 @@ define void @test1() { ret void ; CHECK: ret void } + +define void @test2(i32* %P) { +; CHECK: test2 + %Q = getelementptr i32* %P, i32 1 + %R = bitcast i32* %Q to i8* + call void @llvm.lifetime.start(i64 4, i8* %R) +; CHECK: lifetime.start + store i32 0, i32* %Q ;; This store is dead. +; CHECK-NOT: store + call void @llvm.lifetime.end(i64 4, i8* %R) +; CHECK: lifetime.end + ret void +} + +