diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 273c9951c62..118a42d5153 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -31,6 +31,10 @@ class APInt; class LLVMContext; class DominatorTree; +/// MaximumAlignment - This is the greatest alignment value supported by +/// load, store, and alloca instructions. +static const unsigned MaximumAlignment = 1u << 29; + //===----------------------------------------------------------------------===// // AllocaInst Class //===----------------------------------------------------------------------===// diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 61b1ae5e97c..e581a694586 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -1154,6 +1154,8 @@ bool LLParser::ParseOptionalAlignment(unsigned &Alignment) { if (ParseUInt32(Alignment)) return true; if (!isPowerOf2_32(Alignment)) return Error(AlignLoc, "alignment is not a power of two"); + if (Alignment > MaximumAlignment) + return Error(AlignLoc, "huge alignments are not supported yet"); return false; } @@ -1176,6 +1178,7 @@ bool LLParser::ParseOptionalCommaAlign(unsigned &Alignment, if (Lex.getKind() != lltok::kw_align) return Error(Lex.getLoc(), "expected metadata or 'align'"); + LocTy AlignLoc = Lex.getLoc(); if (ParseOptionalAlignment(Alignment)) return true; } diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 0d5e30205a0..fdb2dd693d9 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -104,11 +104,15 @@ unsigned InstCombiner::GetOrEnforceKnownAlignment(Value *V, ComputeMaskedBits(V, Mask, KnownZero, KnownOne); unsigned TrailZ = KnownZero.countTrailingOnes(); - // LLVM doesn't support alignments larger than this currently. + // Avoid trouble with rediculously large TrailZ values, such as + // those computed from a null pointer. TrailZ = std::min(TrailZ, unsigned(sizeof(unsigned) * CHAR_BIT - 1)); unsigned Align = 1u << std::min(BitWidth - 1, TrailZ); + // LLVM doesn't support alignments larger than this currently. + Align = std::min(Align, MaximumAlignment); + if (PrefAlign > Align) Align = EnforceKnownAlignment(V, Align, PrefAlign); diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 57b7f3f3d64..e03cc827580 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -891,6 +891,8 @@ AllocaInst::~AllocaInst() { void AllocaInst::setAlignment(unsigned Align) { assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); + assert(Align <= MaximumAlignment && + "Alignment is greater than MaximumAlignment!"); setInstructionSubclassData(Log2_32(Align) + 1); assert(getAlignment() == Align && "Alignment representation error!"); } @@ -1026,8 +1028,11 @@ LoadInst::LoadInst(Value *Ptr, const char *Name, bool isVolatile, void LoadInst::setAlignment(unsigned Align) { assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); + assert(Align <= MaximumAlignment && + "Alignment is greater than MaximumAlignment!"); setInstructionSubclassData((getSubclassDataFromInstruction() & 1) | ((Log2_32(Align)+1)<<1)); + assert(getAlignment() == Align && "Alignment representation error!"); } //===----------------------------------------------------------------------===// @@ -1122,8 +1127,11 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, void StoreInst::setAlignment(unsigned Align) { assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); + assert(Align <= MaximumAlignment && + "Alignment is greater than MaximumAlignment!"); setInstructionSubclassData((getSubclassDataFromInstruction() & 1) | ((Log2_32(Align)+1) << 1)); + assert(getAlignment() == Align && "Alignment representation error!"); } //===----------------------------------------------------------------------===// diff --git a/test/Assembler/align-inst-alloca.ll b/test/Assembler/align-inst-alloca.ll new file mode 100644 index 00000000000..0343bebf187 --- /dev/null +++ b/test/Assembler/align-inst-alloca.ll @@ -0,0 +1,6 @@ +; RUN: not llvm-as %s -o /dev/null 2>/dev/null + +define void @foo() { + %p = alloca i1, align 1073741824 + ret void +} diff --git a/test/Assembler/align-inst-load.ll b/test/Assembler/align-inst-load.ll new file mode 100644 index 00000000000..3586be2d6e0 --- /dev/null +++ b/test/Assembler/align-inst-load.ll @@ -0,0 +1,6 @@ +; RUN: not llvm-as %s -o /dev/null 2>/dev/null + +define void @foo() { + load i1* %p, align 1073741824 + ret void +} diff --git a/test/Assembler/align-inst-store.ll b/test/Assembler/align-inst-store.ll new file mode 100644 index 00000000000..8c3b7124b43 --- /dev/null +++ b/test/Assembler/align-inst-store.ll @@ -0,0 +1,6 @@ +; RUN: not llvm-as %s -o /dev/null 2>/dev/null + +define void @foo() { + store i1 false, i1* %p, align 1073741824 + ret void +} diff --git a/test/Assembler/align-inst.ll b/test/Assembler/align-inst.ll new file mode 100644 index 00000000000..7bf0b6493b6 --- /dev/null +++ b/test/Assembler/align-inst.ll @@ -0,0 +1,8 @@ +; RUN: llvm-as %s -o /dev/null + +define void @foo() { + %p = alloca i1, align 536870912 + load i1* %p, align 536870912 + store i1 false, i1* %p, align 536870912 + ret void +}