Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -6768,9 +6768,10 @@ :: - = load [volatile] , * [, align ][, !nontemporal !][, !invariant.load !][, !nonnull !][, !dereferenceable !][, !dereferenceable_or_null !] + = load [volatile] , * [, align ][, !nontemporal !][, !invariant.load !][, !nonnull !][, !dereferenceable !][, !dereferenceable_or_null !][, !value.align !] = load atomic [volatile] * [singlethread] , align ! = !{ i32 1 } + ! = !{ i64 } Overview: """"""""" @@ -6852,6 +6853,14 @@ attribute on parameters and return values. This metadata can only be applied to loads of a pointer type. +The optional ``!value.align`` metadata must reference a single +metadata name ```` corresponding to a metadata node with one +``i64`` entry. The existence of the ``!value.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. 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: """""""""" Index: include/llvm/IR/LLVMContext.h =================================================================== --- include/llvm/IR/LLVMContext.h +++ include/llvm/IR/LLVMContext.h @@ -62,7 +62,8 @@ MD_dereferenceable = 12, // "dereferenceable" MD_dereferenceable_or_null = 13, // "dereferenceable_or_null" MD_make_implicit = 14, // "make.implicit" - MD_unpredictable = 15 // "unpredictable" + MD_unpredictable = 15, // "unpredictable" + MD_value_align = 16 // "value.align" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -2952,6 +2952,11 @@ BaseAlign = GV->getAlignment(); else if (const Argument *A = dyn_cast(Base)) BaseAlign = A->getParamAlignment(); + else if (const LoadInst *LI = dyn_cast(Base)) + if (MDNode *MD = LI->getMetadata(LLVMContext::MD_value_align)) { + ConstantInt *CI = mdconst::extract(MD->getOperand(0)); + BaseAlign = CI->getLimitedValue(); + } if (!BaseAlign) { Type *Ty = Base->getType()->getPointerElementType(); Index: lib/IR/LLVMContext.cpp =================================================================== --- lib/IR/LLVMContext.cpp +++ lib/IR/LLVMContext.cpp @@ -116,6 +116,12 @@ assert(UnpredictableID == MD_unpredictable && "unpredictable kind id drifted"); (void)UnpredictableID; + + // Create the 'value.align' metadata kind. + unsigned ValueAlignID = getMDKindID("value.align"); + assert(ValueAlignID == MD_value_align && + "value.align kind id drifted"); + (void)ValueAlignID; } LLVMContext::~LLVMContext() { delete pImpl; } Index: test/Analysis/ValueTracking/memory-dereferenceable.ll =================================================================== --- test/Analysis/ValueTracking/memory-dereferenceable.ll +++ test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -111,6 +111,14 @@ %load21 = load i8, i8 addrspace(1)* %gep.align1.offset16, align 16 %load22 = load i8, i8 addrspace(1)* %gep.align16.offset16, 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, !value.align !{i64 16} + %load23 = load i32, i32* %d4_unaligned_load, align 16 + %load24 = load i32, i32* %d4_aligned_load, align 16 + ret void }