mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
Memory Dependence Analysis (not mem-dep test) take advantage of "invariant.load" metadata.
The "invariant.load" metadata indicates the memory unit being accessed is immutable. A load annotated with this metadata can be moved across any store. As I am not sure if it is legal to move such loads across barrier/fence, this change dose not allow such transformation. rdar://11311484 Thank Arnold for code review. llvm-svn: 176562
This commit is contained in:
parent
8dd9a160c8
commit
048b100cc5
@ -391,14 +391,17 @@ namespace llvm {
|
||||
/// getPointerDependencyFrom - Return the instruction on which a memory
|
||||
/// location depends. If isLoad is true, this routine ignores may-aliases
|
||||
/// with read-only operations. If isLoad is false, this routine ignores
|
||||
/// may-aliases with reads from read-only locations.
|
||||
/// may-aliases with reads from read-only locations. If possible, pass
|
||||
/// the query instruction as well; this function may take advantage of
|
||||
/// the metadata annotated to the query instruction to refine the result.
|
||||
///
|
||||
/// Note that this is an uncached query, and thus may be inefficient.
|
||||
///
|
||||
MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc,
|
||||
bool isLoad,
|
||||
BasicBlock::iterator ScanIt,
|
||||
BasicBlock *BB);
|
||||
BasicBlock *BB,
|
||||
Instruction *QueryInst = 0);
|
||||
|
||||
|
||||
/// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that
|
||||
|
@ -46,7 +46,8 @@ public:
|
||||
MD_prof = 2, // "prof"
|
||||
MD_fpmath = 3, // "fpmath"
|
||||
MD_range = 4, // "range"
|
||||
MD_tbaa_struct = 5 // "tbaa.struct"
|
||||
MD_tbaa_struct = 5, // "tbaa.struct"
|
||||
MD_invariant_load = 6 // "invariant.load"
|
||||
};
|
||||
|
||||
/// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
|
||||
|
@ -351,15 +351,23 @@ getLoadLoadClobberFullWidthSize(const Value *MemLocBase, int64_t MemLocOffs,
|
||||
/// getPointerDependencyFrom - Return the instruction on which a memory
|
||||
/// location depends. If isLoad is true, this routine ignores may-aliases with
|
||||
/// read-only operations. If isLoad is false, this routine ignores may-aliases
|
||||
/// with reads from read-only locations.
|
||||
/// with reads from read-only locations. If possible, pass the query
|
||||
/// instruction as well; this function may take advantage of the metadata
|
||||
/// annotated to the query instruction to refine the result.
|
||||
MemDepResult MemoryDependenceAnalysis::
|
||||
getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad,
|
||||
BasicBlock::iterator ScanIt, BasicBlock *BB) {
|
||||
BasicBlock::iterator ScanIt, BasicBlock *BB,
|
||||
Instruction *QueryInst) {
|
||||
|
||||
const Value *MemLocBase = 0;
|
||||
int64_t MemLocOffset = 0;
|
||||
|
||||
unsigned Limit = BlockScanLimit;
|
||||
bool isInvariantLoad = false;
|
||||
if (isLoad && QueryInst) {
|
||||
LoadInst *LI = dyn_cast<LoadInst>(QueryInst);
|
||||
if (LI && LI->getMetadata(LLVMContext::MD_invariant_load) != 0)
|
||||
isInvariantLoad = true;
|
||||
}
|
||||
|
||||
// Walk backwards through the basic block, looking for dependencies.
|
||||
while (ScanIt != BB->begin()) {
|
||||
@ -474,6 +482,8 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad,
|
||||
continue;
|
||||
if (R == AliasAnalysis::MustAlias)
|
||||
return MemDepResult::getDef(Inst);
|
||||
if (isInvariantLoad)
|
||||
continue;
|
||||
return MemDepResult::getClobber(Inst);
|
||||
}
|
||||
|
||||
@ -571,7 +581,7 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) {
|
||||
isLoad |= II->getIntrinsicID() == Intrinsic::lifetime_start;
|
||||
|
||||
LocalCache = getPointerDependencyFrom(MemLoc, isLoad, ScanPos,
|
||||
QueryParent);
|
||||
QueryParent, QueryInst);
|
||||
} else if (isa<CallInst>(QueryInst) || isa<InvokeInst>(QueryInst)) {
|
||||
CallSite QueryCS(QueryInst);
|
||||
bool isReadOnly = AA->onlyReadsMemory(QueryCS);
|
||||
|
@ -58,6 +58,11 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
|
||||
unsigned TBAAStructID = getMDKindID("tbaa.struct");
|
||||
assert(TBAAStructID == MD_tbaa_struct && "tbaa.struct kind id drifted");
|
||||
(void)TBAAStructID;
|
||||
|
||||
// Create the 'invariant.load' metadata kind.
|
||||
unsigned InvariantLdId = getMDKindID("invariant.load");
|
||||
assert(InvariantLdId == MD_invariant_load && "invariant.load kind id drifted");
|
||||
(void)InvariantLdId;
|
||||
}
|
||||
LLVMContext::~LLVMContext() { delete pImpl; }
|
||||
|
||||
|
29
test/Analysis/BasicAA/invariant_load.ll
Normal file
29
test/Analysis/BasicAA/invariant_load.ll
Normal file
@ -0,0 +1,29 @@
|
||||
; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
|
||||
|
||||
; The input *.ll is obtained by manually annotating "invariant.load" to the
|
||||
; two loads. With "invariant.load" metadata, the second load is redundant.
|
||||
;
|
||||
; int foo(int *p, char *q) {
|
||||
; *q = (char)*p;
|
||||
; return *p + 1;
|
||||
; }
|
||||
|
||||
define i32 @foo(i32* nocapture %p, i8* nocapture %q) {
|
||||
entry:
|
||||
%0 = load i32* %p, align 4, !tbaa !0, !invariant.load !3
|
||||
%conv = trunc i32 %0 to i8
|
||||
store i8 %conv, i8* %q, align 1, !tbaa !1
|
||||
%1 = load i32* %p, align 4, !tbaa !0, !invariant.load !3
|
||||
%add = add nsw i32 %1, 1
|
||||
ret i32 %add
|
||||
|
||||
; CHECK: foo
|
||||
; CHECK: %0 = load i32* %p
|
||||
; CHECK: store i8 %conv, i8* %q,
|
||||
; CHECK: %add = add nsw i32 %0, 1
|
||||
}
|
||||
|
||||
!0 = metadata !{metadata !"int", metadata !1}
|
||||
!1 = metadata !{metadata !"omnipotent char", metadata !2}
|
||||
!2 = metadata !{metadata !"Simple C/C++ TBAA"}
|
||||
!3 = metadata !{}
|
Loading…
x
Reference in New Issue
Block a user