diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 58fa6fc425e..ec042f0740f 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -782,11 +782,7 @@ public: /// Create an assume intrinsic call that allows the optimizer to /// assume that the provided condition will be true. - /// - /// The optional argument \p OpBundles specifies operand bundles that are - /// added to the call instruction. - CallInst *CreateAssumption(Value *Cond, - ArrayRef OpBundles = llvm::None); + CallInst *CreateAssumption(Value *Cond); /// Create a call to the experimental.gc.statepoint intrinsic to /// start a new statepoint sequence. @@ -2504,11 +2500,13 @@ public: private: /// Helper function that creates an assume intrinsic call that - /// represents an alignment assumption on the provided pointer \p PtrValue - /// with offset \p OffsetValue and alignment value \p AlignValue. + /// represents an alignment assumption on the provided Ptr, Mask, Type + /// and Offset. It may be sometimes useful to do some other logic + /// based on this alignment check, thus it can be stored into 'TheCheck'. CallInst *CreateAlignmentAssumptionHelper(const DataLayout &DL, - Value *PtrValue, Value *AlignValue, - Value *OffsetValue); + Value *PtrValue, Value *Mask, + Type *IntPtrTy, Value *OffsetValue, + Value **TheCheck); public: /// Create an assume intrinsic call that represents an alignment @@ -2517,9 +2515,13 @@ public: /// An optional offset can be provided, and if it is provided, the offset /// must be subtracted from the provided pointer to get the pointer with the /// specified alignment. + /// + /// It may be sometimes useful to do some other logic + /// based on this alignment check, thus it can be stored into 'TheCheck'. CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, unsigned Alignment, - Value *OffsetValue = nullptr); + Value *OffsetValue = nullptr, + Value **TheCheck = nullptr); /// Create an assume intrinsic call that represents an alignment /// assumption on the provided pointer. @@ -2528,11 +2530,15 @@ public: /// must be subtracted from the provided pointer to get the pointer with the /// specified alignment. /// + /// It may be sometimes useful to do some other logic + /// based on this alignment check, thus it can be stored into 'TheCheck'. + /// /// 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 *OffsetValue = nullptr); + Value *OffsetValue = nullptr, + Value **TheCheck = nullptr); }; /// This provides a uniform API for creating instructions and inserting diff --git a/lib/Analysis/AssumeBundleQueries.cpp b/lib/Analysis/AssumeBundleQueries.cpp index af81216f652..e9da1e607b4 100644 --- a/lib/Analysis/AssumeBundleQueries.cpp +++ b/lib/Analysis/AssumeBundleQueries.cpp @@ -96,17 +96,10 @@ llvm::getKnowledgeFromBundle(CallInst &Assume, Result.AttrKind = Attribute::getAttrKindFromName(BOI.Tag->getKey()); if (bundleHasArgument(BOI, ABA_WasOn)) Result.WasOn = getValueFromBundleOpInfo(Assume, BOI, ABA_WasOn); - auto GetArgOr1 = [&](unsigned Idx) -> unsigned { - if (auto *ConstInt = dyn_cast( - getValueFromBundleOpInfo(Assume, BOI, ABA_Argument + Idx))) - return ConstInt->getZExtValue(); - return 1; - }; if (BOI.End - BOI.Begin > ABA_Argument) - Result.ArgValue = GetArgOr1(0); - if (Result.AttrKind == Attribute::Alignment) - if (BOI.End - BOI.Begin > ABA_Argument + 1) - Result.ArgValue = MinAlign(Result.ArgValue, GetArgOr1(1)); + Result.ArgValue = + cast(getValueFromBundleOpInfo(Assume, BOI, ABA_Argument)) + ->getZExtValue(); return Result; } diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp index b87dfe1c8df..1fffce015f7 100644 --- a/lib/IR/IRBuilder.cpp +++ b/lib/IR/IRBuilder.cpp @@ -71,9 +71,8 @@ Value *IRBuilderBase::getCastedInt8PtrValue(Value *Ptr) { static CallInst *createCallHelper(Function *Callee, ArrayRef Ops, IRBuilderBase *Builder, const Twine &Name = "", - Instruction *FMFSource = nullptr, - ArrayRef OpBundles = {}) { - CallInst *CI = Builder->CreateCall(Callee, Ops, OpBundles, Name); + Instruction *FMFSource = nullptr) { + CallInst *CI = Builder->CreateCall(Callee, Ops, Name); if (FMFSource) CI->copyFastMathFlags(FMFSource); return CI; @@ -450,16 +449,14 @@ CallInst *IRBuilderBase::CreateInvariantStart(Value *Ptr, ConstantInt *Size) { return createCallHelper(TheFn, Ops, this); } -CallInst * -IRBuilderBase::CreateAssumption(Value *Cond, - ArrayRef OpBundles) { +CallInst *IRBuilderBase::CreateAssumption(Value *Cond) { assert(Cond->getType() == getInt1Ty() && "an assumption condition must be of type i1"); Value *Ops[] = { Cond }; Module *M = BB->getParent()->getParent(); Function *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume); - return createCallHelper(FnAssume, Ops, this, "", nullptr, OpBundles); + return createCallHelper(FnAssume, Ops, this); } /// Create a call to a Masked Load intrinsic. @@ -1110,37 +1107,63 @@ Value *IRBuilderBase::CreatePreserveStructAccessIndex( return Fn; } -CallInst *IRBuilderBase::CreateAlignmentAssumptionHelper(const DataLayout &DL, - Value *PtrValue, - Value *AlignValue, - Value *OffsetValue) { - SmallVector Vals({PtrValue, AlignValue}); - if (OffsetValue) - Vals.push_back(OffsetValue); - OperandBundleDefT AlignOpB("align", Vals); - return CreateAssumption(ConstantInt::getTrue(getContext()), {AlignOpB}); +CallInst *IRBuilderBase::CreateAlignmentAssumptionHelper( + const DataLayout &DL, Value *PtrValue, Value *Mask, Type *IntPtrTy, + Value *OffsetValue, Value **TheCheck) { + Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); + + if (OffsetValue) { + bool IsOffsetZero = false; + if (const auto *CI = dyn_cast(OffsetValue)) + IsOffsetZero = CI->isZero(); + + if (!IsOffsetZero) { + if (OffsetValue->getType() != IntPtrTy) + OffsetValue = CreateIntCast(OffsetValue, IntPtrTy, /*isSigned*/ true, + "offsetcast"); + PtrIntValue = CreateSub(PtrIntValue, OffsetValue, "offsetptr"); + } + } + + Value *Zero = ConstantInt::get(IntPtrTy, 0); + Value *MaskedPtr = CreateAnd(PtrIntValue, Mask, "maskedptr"); + Value *InvCond = CreateICmpEQ(MaskedPtr, Zero, "maskcond"); + if (TheCheck) + *TheCheck = InvCond; + + return CreateAssumption(InvCond); } -CallInst *IRBuilderBase::CreateAlignmentAssumption(const DataLayout &DL, - Value *PtrValue, - unsigned Alignment, - Value *OffsetValue) { +CallInst *IRBuilderBase::CreateAlignmentAssumption( + const DataLayout &DL, Value *PtrValue, unsigned Alignment, + Value *OffsetValue, Value **TheCheck) { assert(isa(PtrValue->getType()) && "trying to create an alignment assumption on a non-pointer?"); assert(Alignment != 0 && "Invalid Alignment"); auto *PtrTy = cast(PtrValue->getType()); Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); - Value *AlignValue = ConstantInt::get(IntPtrTy, Alignment); - return CreateAlignmentAssumptionHelper(DL, PtrValue, AlignValue, OffsetValue); + + Value *Mask = ConstantInt::get(IntPtrTy, Alignment - 1); + return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, + OffsetValue, TheCheck); } -CallInst *IRBuilderBase::CreateAlignmentAssumption(const DataLayout &DL, - Value *PtrValue, - Value *Alignment, - Value *OffsetValue) { +CallInst *IRBuilderBase::CreateAlignmentAssumption( + const DataLayout &DL, Value *PtrValue, Value *Alignment, + Value *OffsetValue, Value **TheCheck) { assert(isa(PtrValue->getType()) && "trying to create an alignment assumption on a non-pointer?"); - return CreateAlignmentAssumptionHelper(DL, PtrValue, Alignment, OffsetValue); + auto *PtrTy = cast(PtrValue->getType()); + Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); + + if (Alignment->getType() != IntPtrTy) + Alignment = CreateIntCast(Alignment, IntPtrTy, /*isSigned*/ false, + "alignmentcast"); + + Value *Mask = CreateSub(Alignment, ConstantInt::get(IntPtrTy, 1), "mask"); + + return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, + OffsetValue, TheCheck); } IRBuilderDefaultInserter::~IRBuilderDefaultInserter() {} diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index fe06ead21a2..b5e4ce9f44b 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -4449,32 +4449,21 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { Assert(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute(Elem.Tag->getKey()), "tags must be valid attribute names"); + Assert(Elem.End - Elem.Begin <= 2, "to many arguments"); Attribute::AttrKind Kind = Attribute::getAttrKindFromName(Elem.Tag->getKey()); - unsigned ArgCount = Elem.End - Elem.Begin; - if (Kind == Attribute::Alignment) { - Assert(ArgCount <= 3 && ArgCount >= 2, - "alignment assumptions should have 2 or 3 arguments"); - Assert(Call.getOperand(Elem.Begin)->getType()->isPointerTy(), - "first argument should be a pointer"); - Assert(Call.getOperand(Elem.Begin + 1)->getType()->isIntegerTy(), - "second argument should be an integer"); - if (ArgCount == 3) - Assert(Call.getOperand(Elem.Begin + 2)->getType()->isIntegerTy(), - "third argument should be an integer if present"); - return; - } - Assert(ArgCount <= 2, "to many arguments"); if (Kind == Attribute::None) break; if (Attribute::doesAttrKindHaveArgument(Kind)) { - Assert(ArgCount == 2, "this attribute should have 2 arguments"); + Assert(Elem.End - Elem.Begin == 2, + "this attribute should have 2 arguments"); Assert(isa(Call.getOperand(Elem.Begin + 1)), "the second argument should be a constant integral value"); } else if (isFuncOnlyAttr(Kind)) { - Assert((ArgCount) == 0, "this attribute has no argument"); + Assert((Elem.End - Elem.Begin) == 0, "this attribute has no argument"); } else if (!isFuncOrArgAttr(Kind)) { - Assert((ArgCount) == 1, "this attribute should have one argument"); + Assert((Elem.End - Elem.Begin) == 1, + "this attribute should have one argument"); } } break; diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 4acace41e69..966b3246f4f 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -4220,16 +4220,11 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { break; case Intrinsic::assume: { Value *IIOperand = II->getArgOperand(0); - SmallVector OpBundles; - II->getOperandBundlesAsDefs(OpBundles); - bool HasOpBundles = !OpBundles.empty(); // Remove an assume if it is followed by an identical assume. // TODO: Do we need this? Unless there are conflicting assumptions, the // computeKnownBits(IIOperand) below here eliminates redundant assumes. Instruction *Next = II->getNextNonDebugInstruction(); - if (HasOpBundles && - match(Next, m_Intrinsic(m_Specific(IIOperand))) && - !cast(Next)->hasOperandBundles()) + if (match(Next, m_Intrinsic(m_Specific(IIOperand)))) return eraseInstFromFunction(CI); // Canonicalize assume(a && b) -> assume(a); assume(b); @@ -4239,15 +4234,14 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { Value *AssumeIntrinsic = II->getCalledOperand(); Value *A, *B; if (match(IIOperand, m_And(m_Value(A), m_Value(B)))) { - Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, A, OpBundles, - II->getName()); + Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, A, II->getName()); Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, B, II->getName()); return eraseInstFromFunction(*II); } // assume(!(a || b)) -> assume(!a); assume(!b); if (match(IIOperand, m_Not(m_Or(m_Value(A), m_Value(B))))) { Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, - Builder.CreateNot(A), OpBundles, II->getName()); + Builder.CreateNot(A), II->getName()); Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, Builder.CreateNot(B), II->getName()); return eraseInstFromFunction(*II); @@ -4263,8 +4257,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { isValidAssumeForContext(II, LHS, &DT)) { MDNode *MD = MDNode::get(II->getContext(), None); LHS->setMetadata(LLVMContext::MD_nonnull, MD); - if (!HasOpBundles) - return eraseInstFromFunction(*II); + return eraseInstFromFunction(*II); // TODO: apply nonnull return attributes to calls and invokes // TODO: apply range metadata for range check patterns? diff --git a/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp b/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp index 1c98069675a..5c008585869 100644 --- a/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp +++ b/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp @@ -206,23 +206,94 @@ bool AlignmentFromAssumptionsPass::extractAlignmentInfo(CallInst *I, Value *&AAPtr, const SCEV *&AlignSCEV, const SCEV *&OffSCEV) { - Type *Int64Ty = Type::getInt64Ty(I->getContext()); - Optional AlignOB = I->getOperandBundle("align"); - if (AlignOB.hasValue()) { - assert(AlignOB.getValue().Inputs.size() >= 2); - AAPtr = AlignOB.getValue().Inputs[0].get(); - // TODO: Consider accumulating the offset to the base. - AAPtr = AAPtr->stripPointerCastsSameRepresentation(); - AlignSCEV = SE->getSCEV(AlignOB.getValue().Inputs[1].get()); - AlignSCEV = SE->getTruncateOrZeroExtend(AlignSCEV, Int64Ty); - if (AlignOB.getValue().Inputs.size() == 3) - OffSCEV = SE->getSCEV(AlignOB.getValue().Inputs[2].get()); - else - OffSCEV = SE->getZero(Int64Ty); - OffSCEV = SE->getTruncateOrZeroExtend(OffSCEV, Int64Ty); - return true; + // An alignment assume must be a statement about the least-significant + // bits of the pointer being zero, possibly with some offset. + ICmpInst *ICI = dyn_cast(I->getArgOperand(0)); + if (!ICI) + return false; + + // This must be an expression of the form: x & m == 0. + if (ICI->getPredicate() != ICmpInst::ICMP_EQ) + return false; + + // Swap things around so that the RHS is 0. + Value *CmpLHS = ICI->getOperand(0); + Value *CmpRHS = ICI->getOperand(1); + const SCEV *CmpLHSSCEV = SE->getSCEV(CmpLHS); + const SCEV *CmpRHSSCEV = SE->getSCEV(CmpRHS); + if (CmpLHSSCEV->isZero()) + std::swap(CmpLHS, CmpRHS); + else if (!CmpRHSSCEV->isZero()) + return false; + + BinaryOperator *CmpBO = dyn_cast(CmpLHS); + if (!CmpBO || CmpBO->getOpcode() != Instruction::And) + return false; + + // Swap things around so that the right operand of the and is a constant + // (the mask); we cannot deal with variable masks. + Value *AndLHS = CmpBO->getOperand(0); + Value *AndRHS = CmpBO->getOperand(1); + const SCEV *AndLHSSCEV = SE->getSCEV(AndLHS); + const SCEV *AndRHSSCEV = SE->getSCEV(AndRHS); + if (isa(AndLHSSCEV)) { + std::swap(AndLHS, AndRHS); + std::swap(AndLHSSCEV, AndRHSSCEV); } - return false; + + const SCEVConstant *MaskSCEV = dyn_cast(AndRHSSCEV); + if (!MaskSCEV) + return false; + + // The mask must have some trailing ones (otherwise the condition is + // trivial and tells us nothing about the alignment of the left operand). + unsigned TrailingOnes = MaskSCEV->getAPInt().countTrailingOnes(); + if (!TrailingOnes) + return false; + + // Cap the alignment at the maximum with which LLVM can deal (and make sure + // we don't overflow the shift). + uint64_t Alignment; + TrailingOnes = std::min(TrailingOnes, + unsigned(sizeof(unsigned) * CHAR_BIT - 1)); + Alignment = std::min(1u << TrailingOnes, +Value::MaximumAlignment); + + Type *Int64Ty = Type::getInt64Ty(I->getParent()->getParent()->getContext()); + AlignSCEV = SE->getConstant(Int64Ty, Alignment); + + // The LHS might be a ptrtoint instruction, or it might be the pointer + // with an offset. + AAPtr = nullptr; + OffSCEV = nullptr; + if (PtrToIntInst *PToI = dyn_cast(AndLHS)) { + AAPtr = PToI->getPointerOperand(); + OffSCEV = SE->getZero(Int64Ty); + } else if (const SCEVAddExpr* AndLHSAddSCEV = + dyn_cast(AndLHSSCEV)) { + // Try to find the ptrtoint; subtract it and the rest is the offset. + for (SCEVAddExpr::op_iterator J = AndLHSAddSCEV->op_begin(), + JE = AndLHSAddSCEV->op_end(); J != JE; ++J) + if (const SCEVUnknown *OpUnk = dyn_cast(*J)) + if (PtrToIntInst *PToI = dyn_cast(OpUnk->getValue())) { + AAPtr = PToI->getPointerOperand(); + OffSCEV = SE->getMinusSCEV(AndLHSAddSCEV, *J); + break; + } + } + + if (!AAPtr) + return false; + + // Sign extend the offset to 64 bits (so that it is like all of the other + // expressions). + unsigned OffSCEVBits = OffSCEV->getType()->getPrimitiveSizeInBits(); + if (OffSCEVBits < 64) + OffSCEV = SE->getSignExtendExpr(OffSCEV, Int64Ty); + else if (OffSCEVBits > 64) + return false; + + AAPtr = AAPtr->stripPointerCasts(); + return true; } bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) { @@ -246,14 +317,13 @@ bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) { continue; if (Instruction *K = dyn_cast(J)) + if (isValidAssumeForContext(ACall, K, DT)) WorkList.push_back(K); } while (!WorkList.empty()) { Instruction *J = WorkList.pop_back_val(); if (LoadInst *LI = dyn_cast(J)) { - if (!isValidAssumeForContext(ACall, J, DT)) - continue; Align NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV, LI->getPointerOperand(), SE); if (NewAlignment > LI->getAlign()) { @@ -261,8 +331,6 @@ bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) { ++NumLoadAlignChanged; } } else if (StoreInst *SI = dyn_cast(J)) { - if (!isValidAssumeForContext(ACall, J, DT)) - continue; Align NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV, SI->getPointerOperand(), SE); if (NewAlignment > SI->getAlign()) { @@ -270,8 +338,6 @@ bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) { ++NumStoreAlignChanged; } } else if (MemIntrinsic *MI = dyn_cast(J)) { - if (!isValidAssumeForContext(ACall, J, DT)) - continue; Align NewDestAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV, MI->getDest(), SE); @@ -303,7 +369,7 @@ bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) { Visited.insert(J); for (User *UJ : J->users()) { Instruction *K = cast(UJ); - if (!Visited.count(K)) + if (!Visited.count(K) && isValidAssumeForContext(ACall, K, DT)) WorkList.push_back(K); } } diff --git a/test/Transforms/AlignmentFromAssumptions/simple.ll b/test/Transforms/AlignmentFromAssumptions/simple.ll index bb0a937c296..14e764f042c 100644 --- a/test/Transforms/AlignmentFromAssumptions/simple.ll +++ b/test/Transforms/AlignmentFromAssumptions/simple.ll @@ -4,7 +4,10 @@ target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" define i32 @foo(i32* nocapture %a) nounwind uwtable readonly { entry: - tail call void @llvm.assume(i1 true) ["align"(i32* %a, i32 32)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) %0 = load i32, i32* %a, align 4 ret i32 %0 @@ -15,7 +18,11 @@ entry: define i32 @foo2(i32* nocapture %a) nounwind uwtable readonly { entry: - tail call void @llvm.assume(i1 true) ["align"(i32* %a, i32 32, i32 24)] + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 24 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) %arrayidx = getelementptr inbounds i32, i32* %a, i64 2 %0 = load i32, i32* %arrayidx, align 4 ret i32 %0 @@ -27,7 +34,11 @@ entry: define i32 @foo2a(i32* nocapture %a) nounwind uwtable readonly { entry: - tail call void @llvm.assume(i1 true) ["align"(i32* %a, i32 32, i32 28)] + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 28 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) %arrayidx = getelementptr inbounds i32, i32* %a, i64 -1 %0 = load i32, i32* %arrayidx, align 4 ret i32 %0 @@ -39,7 +50,10 @@ entry: define i32 @goo(i32* nocapture %a) nounwind uwtable readonly { entry: - tail call void @llvm.assume(i1 true) ["align"(i32* %a, i32 32, i32 0)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) %0 = load i32, i32* %a, align 4 ret i32 %0 @@ -50,7 +64,10 @@ entry: define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly { entry: - tail call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i32 0)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) br label %for.body for.body: ; preds = %entry, %for.body @@ -81,7 +98,10 @@ for.end: ; preds = %for.body ; load(a, i0+i1+i2+32) define void @hoo2(i32* nocapture %a, i64 %id, i64 %num) nounwind uwtable readonly { entry: - tail call void @llvm.assume(i1 true) ["align"(i32* %a, i8 32, i64 0)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) %id.mul = shl nsw i64 %id, 6 %num.mul = shl nsw i64 %num, 6 br label %for0.body @@ -127,7 +147,10 @@ return: define i32 @joo(i32* nocapture %a) nounwind uwtable readonly { entry: - tail call void @llvm.assume(i1 true) ["align"(i32* %a, i8 32, i8 0)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) br label %for.body for.body: ; preds = %entry, %for.body @@ -152,13 +175,16 @@ for.end: ; preds = %for.body define i32 @koo(i32* nocapture %a) nounwind uwtable readonly { entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) br label %for.body for.body: ; preds = %entry, %for.body %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv - tail call void @llvm.assume(i1 true) ["align"(i32* %a, i8 32, i8 0)] %0 = load i32, i32* %arrayidx, align 4 %add = add nsw i32 %0, %r.06 %indvars.iv.next = add i64 %indvars.iv, 4 @@ -177,7 +203,10 @@ for.end: ; preds = %for.body define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly { entry: - tail call void @llvm.assume(i1 true) ["align"(i32* %a, i128 32, i128 0)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) br label %for.body for.body: ; preds = %entry, %for.body @@ -202,7 +231,10 @@ for.end: ; preds = %for.body define i32 @moo(i32* nocapture %a) nounwind uwtable { entry: - tail call void @llvm.assume(i1 true) ["align"(i32* %a, i16 32)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) %0 = bitcast i32* %a to i8* tail call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 64, i1 false) ret i32 undef @@ -214,9 +246,15 @@ entry: define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable { entry: - tail call void @llvm.assume(i1 true) ["align"(i32* %b, i32 128)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %ptrint1 = ptrtoint i32* %b to i64 + %maskedptr3 = and i64 %ptrint1, 127 + %maskcond4 = icmp eq i64 %maskedptr3, 0 + tail call void @llvm.assume(i1 %maskcond4) %0 = bitcast i32* %a to i8* - tail call void @llvm.assume(i1 true) ["align"(i8* %0, i16 32)] %1 = bitcast i32* %b to i8* tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 %1, i64 64, i1 false) ret i32 undef diff --git a/test/Transforms/AlignmentFromAssumptions/simple32.ll b/test/Transforms/AlignmentFromAssumptions/simple32.ll index 453899c15c4..3f0819e3641 100644 --- a/test/Transforms/AlignmentFromAssumptions/simple32.ll +++ b/test/Transforms/AlignmentFromAssumptions/simple32.ll @@ -7,12 +7,18 @@ define i32 @foo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@foo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 32 ; CHECK-NEXT: ret i32 [[TMP0]] ; entry: - call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) %0 = load i32, i32* %a, align 4 ret i32 %0 @@ -22,13 +28,21 @@ define i32 @foo2(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@foo2 ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32, i64 24) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 +; CHECK-NEXT: [[OFFSETPTR:%.*]] = add i64 [[PTRINT]], 24 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[OFFSETPTR]], 31 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 2 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16 ; CHECK-NEXT: ret i32 [[TMP0]] ; entry: - call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i64 24)] + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 24 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) %arrayidx = getelementptr inbounds i32, i32* %a, i64 2 %0 = load i32, i32* %arrayidx, align 4 ret i32 %0 @@ -39,13 +53,21 @@ define i32 @foo2a(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@foo2a ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32, i64 28) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 +; CHECK-NEXT: [[OFFSETPTR:%.*]] = add i64 [[PTRINT]], 28 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[OFFSETPTR]], 31 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 -1 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 32 ; CHECK-NEXT: ret i32 [[TMP0]] ; entry: - call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i64 28)] + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 28 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) %arrayidx = getelementptr inbounds i32, i32* %a, i64 -1 %0 = load i32, i32* %arrayidx, align 4 ret i32 %0 @@ -56,12 +78,18 @@ define i32 @goo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@goo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 32 ; CHECK-NEXT: ret i32 [[TMP0]] ; entry: - call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) %0 = load i32, i32* %a, align 4 ret i32 %0 @@ -71,7 +99,10 @@ define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@hoo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] @@ -88,7 +119,10 @@ define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-NEXT: ret i32 [[ADD_LCSSA]] ; entry: - call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) br label %for.body for.body: ; preds = %entry, %for.body @@ -112,7 +146,10 @@ define i32 @joo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@joo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 4, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] @@ -129,7 +166,10 @@ define i32 @joo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-NEXT: ret i32 [[ADD_LCSSA]] ; entry: - call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) br label %for.body for.body: ; preds = %entry, %for.body @@ -153,7 +193,10 @@ define i32 @koo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@koo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] @@ -170,7 +213,10 @@ define i32 @koo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-NEXT: ret i32 [[ADD_LCSSA]] ; entry: - call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) br label %for.body for.body: ; preds = %entry, %for.body @@ -194,7 +240,10 @@ define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@koo2 ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ -4, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] @@ -211,7 +260,10 @@ define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-NEXT: ret i32 [[ADD_LCSSA]] ; entry: - call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) br label %for.body for.body: ; preds = %entry, %for.body @@ -235,13 +287,19 @@ define i32 @moo(i32* nocapture %a) nounwind uwtable { ; CHECK-LABEL: define {{[^@]+}}@moo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #1 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) ; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[A]] to i8* ; CHECK-NEXT: tail call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP0]], i8 0, i64 64, i1 false) ; CHECK-NEXT: ret i32 undef ; entry: - call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) %0 = bitcast i32* %a to i8* tail call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 64, i1 false) ret i32 undef @@ -252,16 +310,28 @@ define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable { ; CHECK-LABEL: define {{[^@]+}}@moo2 ; CHECK-SAME: (i32* nocapture [[A:%.*]], i32* nocapture [[B:%.*]]) #1 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[B]], i64 128) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: [[PTRINT1:%.*]] = ptrtoint i32* [[B]] to i64 +; CHECK-NEXT: [[MASKEDPTR3:%.*]] = and i64 [[PTRINT1]], 127 +; CHECK-NEXT: [[MASKCOND4:%.*]] = icmp eq i64 [[MASKEDPTR3]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND4]]) ; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[A]] to i8* ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[B]] to i8* ; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 32 [[TMP0]], i8* align 128 [[TMP1]], i64 64, i1 false) ; CHECK-NEXT: ret i32 undef ; entry: - call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] - call void @llvm.assume(i1 true) ["align"(i32* %b, i64 128)] + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %ptrint1 = ptrtoint i32* %b to i64 + %maskedptr3 = and i64 %ptrint1, 127 + %maskcond4 = icmp eq i64 %maskedptr3, 0 + tail call void @llvm.assume(i1 %maskcond4) %0 = bitcast i32* %a to i8* %1 = bitcast i32* %b to i8* tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 %1, i64 64, i1 false) diff --git a/test/Transforms/Inline/align.ll b/test/Transforms/Inline/align.ll index f3a51845648..ede6c3fa7bc 100644 --- a/test/Transforms/Inline/align.ll +++ b/test/Transforms/Inline/align.ll @@ -23,7 +23,10 @@ define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 { ; CHECK-LABEL: define {{[^@]+}}@foo ; CHECK-SAME: (float* nocapture [[A:%.*]], float* nocapture readonly [[C:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[A]], i64 128) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint float* [[A]] to i64 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 127 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) ; CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4 ; CHECK-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5 ; CHECK-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I]], align 4 @@ -84,8 +87,14 @@ define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture rea ; CHECK-LABEL: define {{[^@]+}}@foo2 ; CHECK-SAME: (float* nocapture [[A:%.*]], float* nocapture [[B:%.*]], float* nocapture readonly [[C:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[A]], i64 128) ] -; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[B]], i64 128) ] +; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint float* [[A]] to i64 +; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 127 +; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: [[PTRINT1:%.*]] = ptrtoint float* [[B]] to i64 +; CHECK-NEXT: [[MASKEDPTR2:%.*]] = and i64 [[PTRINT1]], 127 +; CHECK-NEXT: [[MASKCOND3:%.*]] = icmp eq i64 [[MASKEDPTR2]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND3]]) ; CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4 ; CHECK-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5 ; CHECK-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I]], align 4 diff --git a/test/Transforms/InstCombine/assume.ll b/test/Transforms/InstCombine/assume.ll index b372f52a2cd..6f33e83ee33 100644 --- a/test/Transforms/InstCombine/assume.ll +++ b/test/Transforms/InstCombine/assume.ll @@ -377,7 +377,6 @@ define i32 @assumption_conflicts_with_known_bits(i32 %a, i32 %b) { define void @debug_interference(i8 %x) { ; CHECK-LABEL: @debug_interference( ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[X:%.*]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 false) ; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 5, metadata !7, metadata !DIExpression()), !dbg !9 ; CHECK-NEXT: tail call void @llvm.assume(i1 false) ; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 5, metadata !7, metadata !DIExpression()), !dbg !9 diff --git a/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll b/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll index eb39a3984b0..61287e35005 100644 --- a/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll +++ b/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll @@ -41,7 +41,10 @@ define void @caller1(i1 %c, i64* align 1 %ptr) { ; ASSUMPTIONS-ON-NEXT: br i1 [[C:%.*]], label [[TRUE2_CRITEDGE:%.*]], label [[FALSE1:%.*]] ; ASSUMPTIONS-ON: false1: ; ASSUMPTIONS-ON-NEXT: store volatile i64 1, i64* [[PTR:%.*]], align 8 -; ASSUMPTIONS-ON-NEXT: call void @llvm.assume(i1 true) [ "align"(i64* [[PTR]], i64 8) ] +; ASSUMPTIONS-ON-NEXT: [[PTRINT:%.*]] = ptrtoint i64* [[PTR]] to i64 +; ASSUMPTIONS-ON-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 7 +; ASSUMPTIONS-ON-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; ASSUMPTIONS-ON-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) ; ASSUMPTIONS-ON-NEXT: store volatile i64 0, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 @@ -51,7 +54,10 @@ define void @caller1(i1 %c, i64* align 1 %ptr) { ; ASSUMPTIONS-ON-NEXT: store volatile i64 3, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: ret void ; ASSUMPTIONS-ON: true2.critedge: -; ASSUMPTIONS-ON-NEXT: call void @llvm.assume(i1 true) [ "align"(i64* [[PTR]], i64 8) ] +; ASSUMPTIONS-ON-NEXT: [[PTRINT_C:%.*]] = ptrtoint i64* [[PTR]] to i64 +; ASSUMPTIONS-ON-NEXT: [[MASKEDPTR_C:%.*]] = and i64 [[PTRINT_C]], 7 +; ASSUMPTIONS-ON-NEXT: [[MASKCOND_C:%.*]] = icmp eq i64 [[MASKEDPTR_C]], 0 +; ASSUMPTIONS-ON-NEXT: tail call void @llvm.assume(i1 [[MASKCOND_C]]) ; ASSUMPTIONS-ON-NEXT: store volatile i64 0, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 @@ -98,6 +104,12 @@ define amdgpu_kernel void @caller2() { ; ASSUMPTIONS-OFF-NEXT: ret void ; ; ASSUMPTIONS-ON-LABEL: @caller2( +; ASSUMPTIONS-ON-NEXT: [[ALLOCA:%.*]] = alloca i64, align 8, addrspace(5) +; ASSUMPTIONS-ON-NEXT: [[CAST:%.*]] = addrspacecast i64 addrspace(5)* [[ALLOCA]] to i64* +; ASSUMPTIONS-ON-NEXT: [[PTRINT:%.*]] = ptrtoint i64* [[CAST]] to i64 +; ASSUMPTIONS-ON-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 7 +; ASSUMPTIONS-ON-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 +; ASSUMPTIONS-ON-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) ; ASSUMPTIONS-ON-NEXT: ret void ; %alloca = alloca i64, align 8, addrspace(5) diff --git a/test/Verifier/assume-bundles.ll b/test/Verifier/assume-bundles.ll index 6e260f25129..302421715c7 100644 --- a/test/Verifier/assume-bundles.ll +++ b/test/Verifier/assume-bundles.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: not opt -verify < %s 2>&1 | FileCheck %s declare void @llvm.assume(i1) @@ -7,21 +6,14 @@ define void @func(i32* %P, i32 %P1, i32* %P2, i32* %P3) { ; CHECK: tags must be valid attribute names call void @llvm.assume(i1 true) ["adazdazd"()] ; CHECK: the second argument should be a constant integral value - call void @llvm.assume(i1 true) ["dereferenceable"(i32* %P, i32 %P1)] + call void @llvm.assume(i1 true) ["align"(i32* %P, i32 %P1)] ; CHECK: to many arguments - call void @llvm.assume(i1 true) ["dereferenceable"(i32* %P, i32 8, i32 8)] + call void @llvm.assume(i1 true) ["align"(i32* %P, i32 8, i32 8)] ; CHECK: this attribute should have 2 arguments - call void @llvm.assume(i1 true) ["dereferenceable"(i32* %P)] + call void @llvm.assume(i1 true) ["align"(i32* %P)] ; CHECK: this attribute has no argument - call void @llvm.assume(i1 true) ["dereferenceable"(i32* %P, i32 4), "cold"(i32* %P)] + call void @llvm.assume(i1 true) ["align"(i32* %P, i32 4), "cold"(i32* %P)] ; CHECK: this attribute should have one argument call void @llvm.assume(i1 true) ["noalias"()] - call void @llvm.assume(i1 true) ["align"(i32* %P, i32 %P1, i32 4)] -; CHECK: alignment assumptions should have 2 or 3 arguments - call void @llvm.assume(i1 true) ["align"(i32* %P, i32 %P1, i32 4, i32 4)] -; CHECK: second argument should be an integer - call void @llvm.assume(i1 true) ["align"(i32* %P, i32* %P2)] -; CHECK: third argument should be an integer if present - call void @llvm.assume(i1 true) ["align"(i32* %P, i32 %P1, i32* %P2)] ret void } diff --git a/unittests/Analysis/AssumeBundleQueriesTest.cpp b/unittests/Analysis/AssumeBundleQueriesTest.cpp index 946368e1cb9..d35a77fa379 100644 --- a/unittests/Analysis/AssumeBundleQueriesTest.cpp +++ b/unittests/Analysis/AssumeBundleQueriesTest.cpp @@ -546,41 +546,3 @@ TEST(AssumeQueryAPI, AssumptionCache) { ASSERT_EQ(AR[0].Index, 1u); ASSERT_EQ(AR[0].Assume, &*First); } - -TEST(AssumeQueryAPI, Alignment) { - LLVMContext C; - SMDiagnostic Err; - std::unique_ptr Mod = parseAssemblyString( - "declare void @llvm.assume(i1)\n" - "define void @test(i32* %P, i32* %P1, i32* %P2, i32 %I3, i1 %B) {\n" - "call void @llvm.assume(i1 true) [\"align\"(i32* %P, i32 8, i32 %I3)]\n" - "call void @llvm.assume(i1 true) [\"align\"(i32* %P1, i32 %I3, i32 " - "%I3)]\n" - "call void @llvm.assume(i1 true) [\"align\"(i32* %P2, i32 16, i32 8)]\n" - "ret void\n}\n", - Err, C); - if (!Mod) - Err.print("AssumeQueryAPI", errs()); - - Function *F = Mod->getFunction("test"); - BasicBlock::iterator Start = F->begin()->begin(); - IntrinsicInst *II; - RetainedKnowledge RK; - II = cast(&*Start); - RK = getKnowledgeFromBundle(*II, II->bundle_op_info_begin()[0]); - ASSERT_EQ(RK.AttrKind, Attribute::Alignment); - ASSERT_EQ(RK.WasOn, F->getArg(0)); - ASSERT_EQ(RK.ArgValue, 1u); - Start++; - II = cast(&*Start); - RK = getKnowledgeFromBundle(*II, II->bundle_op_info_begin()[0]); - ASSERT_EQ(RK.AttrKind, Attribute::Alignment); - ASSERT_EQ(RK.WasOn, F->getArg(1)); - ASSERT_EQ(RK.ArgValue, 1u); - Start++; - II = cast(&*Start); - RK = getKnowledgeFromBundle(*II, II->bundle_op_info_begin()[0]); - ASSERT_EQ(RK.AttrKind, Attribute::Alignment); - ASSERT_EQ(RK.WasOn, F->getArg(2)); - ASSERT_EQ(RK.ArgValue, 8u); -}