From be2b2c32d38ab91bfe59b53d0dea8c8404802013 Mon Sep 17 00:00:00 2001 From: Artur Pilipenko Date: Mon, 28 Sep 2015 17:41:08 +0000 Subject: [PATCH] Introduce !align metadata for load instruction Reviewed By: hfinkel Differential Revision: http://reviews.llvm.org/D12853 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@248721 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LangRef.rst | 11 ++++++++++- include/llvm/IR/LLVMContext.h | 3 ++- lib/Analysis/ValueTracking.cpp | 5 +++++ lib/IR/LLVMContext.cpp | 4 ++++ test/Analysis/ValueTracking/memory-dereferenceable.ll | 8 ++++++++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/docs/LangRef.rst b/docs/LangRef.rst index 9b8aaa7a1fd..bc4df058646 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -6860,10 +6860,11 @@ Syntax: :: - = load [volatile] , * [, align ][, !nontemporal !][, !invariant.load !][, !invariant.group !][, !nonnull !][, !dereferenceable !][, !dereferenceable_or_null !] + = load [volatile] , * [, align ][, !nontemporal !][, !invariant.load !][, !invariant.group !][, !nonnull !][, !dereferenceable !][, !dereferenceable_or_null !][, !align !] = load atomic [volatile] * [singlethread] , align [, !invariant.group !] ! = !{ i32 1 } ! = !{i64 } + ! = !{ i64 } Overview: """"""""" @@ -6948,6 +6949,14 @@ value in the metadata node. This is analogous to the ''dereferenceable_or_null'' attribute on parameters and return values. This metadata can only be applied to loads of a pointer type. +The optional ``!align`` metadata must reference a single metadata name +```` corresponding to a metadata node with one ``i64`` entry. +The existence of the ``!align`` metadata on the instruction tells the +optimizer that the value loaded is known to be aligned to a boundary specified +by the integer value in the metadata node. The alignment must be a power of 2. +This is analogous to the ''align'' attribute on parameters and return values. +This metadata can only be applied to loads of a pointer type. + Semantics: """""""""" diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index 336aca2d5ba..24e95f6a62f 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -63,7 +63,8 @@ public: MD_dereferenceable_or_null = 13, // "dereferenceable_or_null" MD_make_implicit = 14, // "make.implicit" MD_unpredictable = 15, // "unpredictable" - MD_invariant_group = 16 // "invariant.group" + MD_invariant_group = 16, // "invariant.group" + MD_align = 17 // "align" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index 736077dc477..5481e722e53 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -2979,6 +2979,11 @@ static bool isAligned(const Value *Base, APInt Offset, unsigned Align, BaseAlign = A->getParamAlignment(); else if (auto CS = ImmutableCallSite(Base)) BaseAlign = CS.getAttributes().getParamAlignment(AttributeSet::ReturnIndex); + else if (const LoadInst *LI = dyn_cast(Base)) + if (MDNode *MD = LI->getMetadata(LLVMContext::MD_align)) { + ConstantInt *CI = mdconst::extract(MD->getOperand(0)); + BaseAlign = CI->getLimitedValue(); + } if (!BaseAlign) { Type *Ty = Base->getType()->getPointerElementType(); diff --git a/lib/IR/LLVMContext.cpp b/lib/IR/LLVMContext.cpp index ee971c1be19..cecc6335ef1 100644 --- a/lib/IR/LLVMContext.cpp +++ b/lib/IR/LLVMContext.cpp @@ -123,6 +123,10 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) { "invariant.group kind id drifted"); (void)InvariantGroupId; + // Create the 'align' metadata kind. + unsigned AlignID = getMDKindID("align"); + assert(AlignID == MD_align && "align kind id drifted"); + (void)AlignID; } LLVMContext::~LLVMContext() { delete pImpl; } diff --git a/test/Analysis/ValueTracking/memory-dereferenceable.ll b/test/Analysis/ValueTracking/memory-dereferenceable.ll index 550b01c4c9a..c7ca21ab061 100644 --- a/test/Analysis/ValueTracking/memory-dereferenceable.ll +++ b/test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -122,6 +122,14 @@ entry: %load24 = load i32, i32* %deref_return, align 16 %load25 = load i32, i32* %deref_and_aligned_return, align 16 + ; Load from a dereferenceable and aligned load +; CHECK: %d4_unaligned_load{{.*}}(unaligned) +; CHECK: %d4_aligned_load{{.*}}(aligned) + %d4_unaligned_load = load i32*, i32** @globali32ptr, !dereferenceable !0 + %d4_aligned_load = load i32*, i32** @globali32ptr, !dereferenceable !0, !align !{i64 16} + %load26 = load i32, i32* %d4_unaligned_load, align 16 + %load27 = load i32, i32* %d4_aligned_load, align 16 + ret void } -- 2.34.1