Index: include/llvm/IR/IRBuilder.h =================================================================== --- include/llvm/IR/IRBuilder.h +++ include/llvm/IR/IRBuilder.h @@ -54,6 +54,9 @@ class MDNode; class Use; + +enum class AlignmentSign { Signed, Unsigned}; + /// This provides the default implementation of the IRBuilder /// 'InsertHelper' method that is called whenever an instruction is created by /// IRBuilder and needs to be inserted. @@ -2182,7 +2185,7 @@ /// This overload handles the condition where the Alignment is dependent /// on an existing value rather than a static value. CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, - Value *Alignment, + Value *Alignment, AlignmentSign Sign, Value *OffsetValue = nullptr) { assert(isa(PtrValue->getType()) && "trying to create an alignment assumption on a non-pointer?"); @@ -2190,15 +2193,30 @@ Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); if (Alignment->getType() != IntPtrTy) - Alignment = CreateIntCast(Alignment, IntPtrTy, /*isSigned*/ true, + Alignment = CreateIntCast(Alignment, IntPtrTy, + /*isSigned*/ Sign == AlignmentSign::Signed, "alignmentcast"); - Value *IsPositive = - CreateICmp(CmpInst::ICMP_SGT, Alignment, - ConstantInt::get(Alignment->getType(), 0), "ispositive"); - Value *PositiveMask = - CreateSub(Alignment, ConstantInt::get(IntPtrTy, 1), "positivemask"); - Value *Mask = CreateSelect(IsPositive, PositiveMask, - ConstantInt::get(IntPtrTy, 0), "mask"); + + // Alignments are only valid if > 0 && IsPowerOf2. + Value *IsPositive = CreateICmp( + Sign == AlignmentSign::Signed ? CmpInst::ICMP_SGT : CmpInst::ICMP_UGT, + Alignment, ConstantInt::get(Alignment->getType(), 0), "ispositive"); + + // Save alignment - 1, which is valuable for both IsPowerOf2 and creating + // the mask. + Value *Sub1 = CreateSub( + Alignment, ConstantInt::get(Alignment->getType(), 1), "alignsubone"); + + // Calculate Alignment & (Alignment - 1) == 0 + Value *AlignAndMinus1 = CreateAnd(Alignment, Sub1, "alignandsubone"); + Value *IsPowerOf2 = + CreateICmpEQ(AlignAndMinus1, ConstantInt::get(Alignment->getType(), 0), + "ispowertwo"); + + Value *ValidMask = CreateAnd(IsPositive, IsPowerOf2, "alignisvalid"); + + Value *Mask = CreateSelect( + ValidMask, Sub1, ConstantInt::get(Alignment->getType(), 0), "mask"); return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, OffsetValue);