llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-llvm-transforms Author: None (llvmbot) <details> <summary>Changes</summary> Backport 01a103b0b9c449e8dec17950835991757d1c4f88 Requested by: @<!-- -->hvdijk --- Patch is 30.47 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/114786.diff 4 Files Affected: - (modified) llvm/include/llvm/Analysis/MemoryBuiltins.h (+47-24) - (modified) llvm/lib/Analysis/MemoryBuiltins.cpp (+80-65) - (modified) llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll (+254) - (modified) llvm/test/Transforms/LowerConstantIntrinsics/objectsize_basic.ll (+24) ``````````diff diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h index bb282a1b73d320..a21f116db7e70d 100644 --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -222,21 +222,43 @@ struct SizeOffsetAPInt : public SizeOffsetType<APInt, SizeOffsetAPInt> { static bool known(const APInt &V) { return V.getBitWidth() > 1; } }; +/// OffsetSpan - Used internally by \p ObjectSizeOffsetVisitor. Represents a +/// point in memory as a pair of allocated bytes before and after it. +struct OffsetSpan { + APInt Before; /// Number of allocated bytes before this point. + APInt After; /// Number of allocated bytes after this point. + + OffsetSpan() = default; + OffsetSpan(APInt Before, APInt After) : Before(Before), After(After) {} + + bool knownBefore() const { return known(Before); } + bool knownAfter() const { return known(After); } + bool anyKnown() const { return knownBefore() || knownAfter(); } + bool bothKnown() const { return knownBefore() && knownAfter(); } + + bool operator==(const OffsetSpan &RHS) const { + return Before == RHS.Before && After == RHS.After; + } + bool operator!=(const OffsetSpan &RHS) const { return !(*this == RHS); } + + static bool known(const APInt &V) { return V.getBitWidth() > 1; } +}; + /// Evaluate the size and offset of an object pointed to by a Value* /// statically. Fails if size or offset are not known at compile time. class ObjectSizeOffsetVisitor - : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetAPInt> { + : public InstVisitor<ObjectSizeOffsetVisitor, OffsetSpan> { const DataLayout &DL; const TargetLibraryInfo *TLI; ObjectSizeOpts Options; unsigned IntTyBits; APInt Zero; - SmallDenseMap<Instruction *, SizeOffsetAPInt, 8> SeenInsts; + SmallDenseMap<Instruction *, OffsetSpan, 8> SeenInsts; unsigned InstructionsVisited; APInt align(APInt Size, MaybeAlign Align); - static SizeOffsetAPInt unknown() { return SizeOffsetAPInt(); } + static OffsetSpan unknown() { return OffsetSpan(); } public: ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, @@ -246,29 +268,30 @@ class ObjectSizeOffsetVisitor // These are "private", except they can't actually be made private. Only // compute() should be used by external users. - SizeOffsetAPInt visitAllocaInst(AllocaInst &I); - SizeOffsetAPInt visitArgument(Argument &A); - SizeOffsetAPInt visitCallBase(CallBase &CB); - SizeOffsetAPInt visitConstantPointerNull(ConstantPointerNull &); - SizeOffsetAPInt visitExtractElementInst(ExtractElementInst &I); - SizeOffsetAPInt visitExtractValueInst(ExtractValueInst &I); - SizeOffsetAPInt visitGlobalAlias(GlobalAlias &GA); - SizeOffsetAPInt visitGlobalVariable(GlobalVariable &GV); - SizeOffsetAPInt visitIntToPtrInst(IntToPtrInst &); - SizeOffsetAPInt visitLoadInst(LoadInst &I); - SizeOffsetAPInt visitPHINode(PHINode &); - SizeOffsetAPInt visitSelectInst(SelectInst &I); - SizeOffsetAPInt visitUndefValue(UndefValue &); - SizeOffsetAPInt visitInstruction(Instruction &I); + OffsetSpan visitAllocaInst(AllocaInst &I); + OffsetSpan visitArgument(Argument &A); + OffsetSpan visitCallBase(CallBase &CB); + OffsetSpan visitConstantPointerNull(ConstantPointerNull &); + OffsetSpan visitExtractElementInst(ExtractElementInst &I); + OffsetSpan visitExtractValueInst(ExtractValueInst &I); + OffsetSpan visitGlobalAlias(GlobalAlias &GA); + OffsetSpan visitGlobalVariable(GlobalVariable &GV); + OffsetSpan visitIntToPtrInst(IntToPtrInst &); + OffsetSpan visitLoadInst(LoadInst &I); + OffsetSpan visitPHINode(PHINode &); + OffsetSpan visitSelectInst(SelectInst &I); + OffsetSpan visitUndefValue(UndefValue &); + OffsetSpan visitInstruction(Instruction &I); private: - SizeOffsetAPInt findLoadSizeOffset( - LoadInst &LoadFrom, BasicBlock &BB, BasicBlock::iterator From, - SmallDenseMap<BasicBlock *, SizeOffsetAPInt, 8> &VisitedBlocks, - unsigned &ScannedInstCount); - SizeOffsetAPInt combineSizeOffset(SizeOffsetAPInt LHS, SizeOffsetAPInt RHS); - SizeOffsetAPInt computeImpl(Value *V); - SizeOffsetAPInt computeValue(Value *V); + OffsetSpan + findLoadOffsetRange(LoadInst &LoadFrom, BasicBlock &BB, + BasicBlock::iterator From, + SmallDenseMap<BasicBlock *, OffsetSpan, 8> &VisitedBlocks, + unsigned &ScannedInstCount); + OffsetSpan combineOffsetRange(OffsetSpan LHS, OffsetSpan RHS); + OffsetSpan computeImpl(Value *V); + OffsetSpan computeValue(Value *V); bool CheckedZextOrTrunc(APInt &I); }; diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index 1edc51e9ce5da3..44cb2d0942f460 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -700,10 +700,21 @@ ObjectSizeOffsetVisitor::ObjectSizeOffsetVisitor(const DataLayout &DL, SizeOffsetAPInt ObjectSizeOffsetVisitor::compute(Value *V) { InstructionsVisited = 0; - return computeImpl(V); + OffsetSpan Span = computeImpl(V); + + // In ExactSizeFromOffset mode, we don't care about the Before Field, so allow + // us to overwrite it if needs be. + if (Span.knownAfter() && !Span.knownBefore() && + Options.EvalMode == ObjectSizeOpts::Mode::ExactSizeFromOffset) + Span.Before = APInt::getZero(Span.After.getBitWidth()); + + if (!Span.bothKnown()) + return {}; + + return {Span.Before + Span.After, Span.Before}; } -SizeOffsetAPInt ObjectSizeOffsetVisitor::computeImpl(Value *V) { +OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) { unsigned InitialIntTyBits = DL.getIndexTypeSizeInBits(V->getType()); // Stripping pointer casts can strip address space casts which can change the @@ -720,28 +731,28 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::computeImpl(Value *V) { IntTyBits = DL.getIndexTypeSizeInBits(V->getType()); Zero = APInt::getZero(IntTyBits); - SizeOffsetAPInt SOT = computeValue(V); + OffsetSpan ORT = computeValue(V); bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits; if (!IndexTypeSizeChanged && Offset.isZero()) - return SOT; + return ORT; // We stripped an address space cast that changed the index type size or we // accumulated some constant offset (or both). Readjust the bit width to match // the argument index type size and apply the offset, as required. if (IndexTypeSizeChanged) { - if (SOT.knownSize() && !::CheckedZextOrTrunc(SOT.Size, InitialIntTyBits)) - SOT.Size = APInt(); - if (SOT.knownOffset() && - !::CheckedZextOrTrunc(SOT.Offset, InitialIntTyBits)) - SOT.Offset = APInt(); + if (ORT.knownBefore() && + !::CheckedZextOrTrunc(ORT.Before, InitialIntTyBits)) + ORT.Before = APInt(); + if (ORT.knownAfter() && !::CheckedZextOrTrunc(ORT.After, InitialIntTyBits)) + ORT.After = APInt(); } - // If the computed offset is "unknown" we cannot add the stripped offset. - return {SOT.Size, - SOT.Offset.getBitWidth() > 1 ? SOT.Offset + Offset : SOT.Offset}; + // If the computed bound is "unknown" we cannot add the stripped offset. + return {(ORT.knownBefore() ? ORT.Before + Offset : ORT.Before), + (ORT.knownAfter() ? ORT.After - Offset : ORT.After)}; } -SizeOffsetAPInt ObjectSizeOffsetVisitor::computeValue(Value *V) { +OffsetSpan ObjectSizeOffsetVisitor::computeValue(Value *V) { if (Instruction *I = dyn_cast<Instruction>(V)) { // If we have already seen this instruction, bail out. Cycles can happen in // unreachable code after constant propagation. @@ -751,7 +762,7 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::computeValue(Value *V) { ++InstructionsVisited; if (InstructionsVisited > ObjectSizeOffsetVisitorMaxVisitInstructions) return ObjectSizeOffsetVisitor::unknown(); - SizeOffsetAPInt Res = visit(*I); + OffsetSpan Res = visit(*I); // Cache the result for later visits. If we happened to visit this during // the above recursion, we would consider it unknown until now. SeenInsts[I] = Res; @@ -777,13 +788,13 @@ bool ObjectSizeOffsetVisitor::CheckedZextOrTrunc(APInt &I) { return ::CheckedZextOrTrunc(I, IntTyBits); } -SizeOffsetAPInt ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) { +OffsetSpan ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) { TypeSize ElemSize = DL.getTypeAllocSize(I.getAllocatedType()); if (ElemSize.isScalable() && Options.EvalMode != ObjectSizeOpts::Mode::Min) return ObjectSizeOffsetVisitor::unknown(); APInt Size(IntTyBits, ElemSize.getKnownMinValue()); if (!I.isArrayAllocation()) - return SizeOffsetAPInt(align(Size, I.getAlign()), Zero); + return OffsetSpan(Zero, align(Size, I.getAlign())); Value *ArraySize = I.getArraySize(); if (const ConstantInt *C = dyn_cast<ConstantInt>(ArraySize)) { @@ -794,12 +805,12 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) { bool Overflow; Size = Size.umul_ov(NumElems, Overflow); return Overflow ? ObjectSizeOffsetVisitor::unknown() - : SizeOffsetAPInt(align(Size, I.getAlign()), Zero); + : OffsetSpan(Zero, align(Size, I.getAlign())); } return ObjectSizeOffsetVisitor::unknown(); } -SizeOffsetAPInt ObjectSizeOffsetVisitor::visitArgument(Argument &A) { +OffsetSpan ObjectSizeOffsetVisitor::visitArgument(Argument &A) { Type *MemoryTy = A.getPointeeInMemoryValueType(); // No interprocedural analysis is done at the moment. if (!MemoryTy|| !MemoryTy->isSized()) { @@ -808,16 +819,16 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::visitArgument(Argument &A) { } APInt Size(IntTyBits, DL.getTypeAllocSize(MemoryTy)); - return SizeOffsetAPInt(align(Size, A.getParamAlign()), Zero); + return OffsetSpan(Zero, align(Size, A.getParamAlign())); } -SizeOffsetAPInt ObjectSizeOffsetVisitor::visitCallBase(CallBase &CB) { +OffsetSpan ObjectSizeOffsetVisitor::visitCallBase(CallBase &CB) { if (std::optional<APInt> Size = getAllocSize(&CB, TLI)) - return SizeOffsetAPInt(*Size, Zero); + return OffsetSpan(Zero, *Size); return ObjectSizeOffsetVisitor::unknown(); } -SizeOffsetAPInt +OffsetSpan ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull &CPN) { // If null is unknown, there's nothing we can do. Additionally, non-zero // address spaces can make use of null, so we don't presume to know anything @@ -828,45 +839,43 @@ ObjectSizeOffsetVisitor::visitConstantPointerNull(ConstantPointerNull &CPN) { // addrspace(1) gets casted to addrspace(0) (or vice-versa). if (Options.NullIsUnknownSize || CPN.getType()->getAddressSpace()) return ObjectSizeOffsetVisitor::unknown(); - return SizeOffsetAPInt(Zero, Zero); + return OffsetSpan(Zero, Zero); } -SizeOffsetAPInt +OffsetSpan ObjectSizeOffsetVisitor::visitExtractElementInst(ExtractElementInst &) { return ObjectSizeOffsetVisitor::unknown(); } -SizeOffsetAPInt -ObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst &) { +OffsetSpan ObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst &) { // Easy cases were already folded by previous passes. return ObjectSizeOffsetVisitor::unknown(); } -SizeOffsetAPInt ObjectSizeOffsetVisitor::visitGlobalAlias(GlobalAlias &GA) { +OffsetSpan ObjectSizeOffsetVisitor::visitGlobalAlias(GlobalAlias &GA) { if (GA.isInterposable()) return ObjectSizeOffsetVisitor::unknown(); return computeImpl(GA.getAliasee()); } -SizeOffsetAPInt -ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV) { +OffsetSpan ObjectSizeOffsetVisitor::visitGlobalVariable(GlobalVariable &GV) { if (!GV.getValueType()->isSized() || GV.hasExternalWeakLinkage() || ((!GV.hasInitializer() || GV.isInterposable()) && Options.EvalMode != ObjectSizeOpts::Mode::Min)) return ObjectSizeOffsetVisitor::unknown(); APInt Size(IntTyBits, DL.getTypeAllocSize(GV.getValueType())); - return SizeOffsetAPInt(align(Size, GV.getAlign()), Zero); + return OffsetSpan(Zero, align(Size, GV.getAlign())); } -SizeOffsetAPInt ObjectSizeOffsetVisitor::visitIntToPtrInst(IntToPtrInst &) { +OffsetSpan ObjectSizeOffsetVisitor::visitIntToPtrInst(IntToPtrInst &) { // clueless return ObjectSizeOffsetVisitor::unknown(); } -SizeOffsetAPInt ObjectSizeOffsetVisitor::findLoadSizeOffset( +OffsetSpan ObjectSizeOffsetVisitor::findLoadOffsetRange( LoadInst &Load, BasicBlock &BB, BasicBlock::iterator From, - SmallDenseMap<BasicBlock *, SizeOffsetAPInt, 8> &VisitedBlocks, + SmallDenseMap<BasicBlock *, OffsetSpan, 8> &VisitedBlocks, unsigned &ScannedInstCount) { constexpr unsigned MaxInstsToScan = 128; @@ -877,7 +886,7 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::findLoadSizeOffset( auto Unknown = [&BB, &VisitedBlocks]() { return VisitedBlocks[&BB] = ObjectSizeOffsetVisitor::unknown(); }; - auto Known = [&BB, &VisitedBlocks](SizeOffsetAPInt SO) { + auto Known = [&BB, &VisitedBlocks](OffsetSpan SO) { return VisitedBlocks[&BB] = SO; }; @@ -948,15 +957,15 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::findLoadSizeOffset( if (!C) return Unknown(); - return Known({C->getValue(), APInt(C->getValue().getBitWidth(), 0)}); + return Known({APInt(C->getValue().getBitWidth(), 0), C->getValue()}); } return Unknown(); } while (From-- != BB.begin()); - SmallVector<SizeOffsetAPInt> PredecessorSizeOffsets; + SmallVector<OffsetSpan> PredecessorSizeOffsets; for (auto *PredBB : predecessors(&BB)) { - PredecessorSizeOffsets.push_back(findLoadSizeOffset( + PredecessorSizeOffsets.push_back(findLoadOffsetRange( Load, *PredBB, BasicBlock::iterator(PredBB->getTerminator()), VisitedBlocks, ScannedInstCount)); if (!PredecessorSizeOffsets.back().bothKnown()) @@ -968,70 +977,70 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::findLoadSizeOffset( return Known(std::accumulate( PredecessorSizeOffsets.begin() + 1, PredecessorSizeOffsets.end(), - PredecessorSizeOffsets.front(), - [this](SizeOffsetAPInt LHS, SizeOffsetAPInt RHS) { - return combineSizeOffset(LHS, RHS); + PredecessorSizeOffsets.front(), [this](OffsetSpan LHS, OffsetSpan RHS) { + return combineOffsetRange(LHS, RHS); })); } -SizeOffsetAPInt ObjectSizeOffsetVisitor::visitLoadInst(LoadInst &LI) { +OffsetSpan ObjectSizeOffsetVisitor::visitLoadInst(LoadInst &LI) { if (!Options.AA) { ++ObjectVisitorLoad; return ObjectSizeOffsetVisitor::unknown(); } - SmallDenseMap<BasicBlock *, SizeOffsetAPInt, 8> VisitedBlocks; + SmallDenseMap<BasicBlock *, OffsetSpan, 8> VisitedBlocks; unsigned ScannedInstCount = 0; - SizeOffsetAPInt SO = - findLoadSizeOffset(LI, *LI.getParent(), BasicBlock::iterator(LI), - VisitedBlocks, ScannedInstCount); + OffsetSpan SO = + findLoadOffsetRange(LI, *LI.getParent(), BasicBlock::iterator(LI), + VisitedBlocks, ScannedInstCount); if (!SO.bothKnown()) ++ObjectVisitorLoad; return SO; } -SizeOffsetAPInt -ObjectSizeOffsetVisitor::combineSizeOffset(SizeOffsetAPInt LHS, - SizeOffsetAPInt RHS) { +OffsetSpan ObjectSizeOffsetVisitor::combineOffsetRange(OffsetSpan LHS, + OffsetSpan RHS) { if (!LHS.bothKnown() || !RHS.bothKnown()) return ObjectSizeOffsetVisitor::unknown(); switch (Options.EvalMode) { case ObjectSizeOpts::Mode::Min: - return (getSizeWithOverflow(LHS).slt(getSizeWithOverflow(RHS))) ? LHS : RHS; - case ObjectSizeOpts::Mode::Max: - return (getSizeWithOverflow(LHS).sgt(getSizeWithOverflow(RHS))) ? LHS : RHS; + return {LHS.Before.slt(RHS.Before) ? LHS.Before : RHS.Before, + LHS.After.slt(RHS.After) ? LHS.After : RHS.After}; + case ObjectSizeOpts::Mode::Max: { + return {LHS.Before.sgt(RHS.Before) ? LHS.Before : RHS.Before, + LHS.After.sgt(RHS.After) ? LHS.After : RHS.After}; + } case ObjectSizeOpts::Mode::ExactSizeFromOffset: - return (getSizeWithOverflow(LHS).eq(getSizeWithOverflow(RHS))) - ? LHS - : ObjectSizeOffsetVisitor::unknown(); + return {LHS.Before.eq(RHS.Before) ? LHS.Before : APInt(), + LHS.After.eq(RHS.After) ? LHS.After : APInt()}; case ObjectSizeOpts::Mode::ExactUnderlyingSizeAndOffset: - return LHS == RHS ? LHS : ObjectSizeOffsetVisitor::unknown(); + return (LHS == RHS) ? LHS : ObjectSizeOffsetVisitor::unknown(); } llvm_unreachable("missing an eval mode"); } -SizeOffsetAPInt ObjectSizeOffsetVisitor::visitPHINode(PHINode &PN) { +OffsetSpan ObjectSizeOffsetVisitor::visitPHINode(PHINode &PN) { if (PN.getNumIncomingValues() == 0) return ObjectSizeOffsetVisitor::unknown(); auto IncomingValues = PN.incoming_values(); return std::accumulate(IncomingValues.begin() + 1, IncomingValues.end(), computeImpl(*IncomingValues.begin()), - [this](SizeOffsetAPInt LHS, Value *VRHS) { - return combineSizeOffset(LHS, computeImpl(VRHS)); + [this](OffsetSpan LHS, Value *VRHS) { + return combineOffsetRange(LHS, computeImpl(VRHS)); }); } -SizeOffsetAPInt ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) { - return combineSizeOffset(computeImpl(I.getTrueValue()), - computeImpl(I.getFalseValue())); +OffsetSpan ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) { + return combineOffsetRange(computeImpl(I.getTrueValue()), + computeImpl(I.getFalseValue())); } -SizeOffsetAPInt ObjectSizeOffsetVisitor::visitUndefValue(UndefValue &) { - return SizeOffsetAPInt(Zero, Zero); +OffsetSpan ObjectSizeOffsetVisitor::visitUndefValue(UndefValue &) { + return OffsetSpan(Zero, Zero); } -SizeOffsetAPInt ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) { +OffsetSpan ObjectSizeOffsetVisitor::visitInstruction(Instruction &I) { LLVM_DEBUG(dbgs() << "ObjectSizeOffsetVisitor unknown instruction:" << I << '\n'); return ObjectSizeOffsetVisitor::unknown(); @@ -1084,7 +1093,13 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::compute(Value *V) { } SizeOffsetValue ObjectSizeOffsetEvaluator::compute_(Value *V) { - ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, EvalOpts); + + // Only trust ObjectSizeOffsetVisitor in exact mode, otherwise fallback on + // dynamic computation. + ObjectSizeOpts VisitorEvalOpts(EvalOpts); + VisitorEvalOpts.EvalMode = ObjectSizeOpts::Mode::ExactUnderlyingSizeAndOffset; + ObjectSizeOffsetVisitor Visitor(DL, TLI, Context, VisitorEvalOpts); + SizeOffsetAPInt Const = Visitor.compute(V); if (Const.bothKnown()) return SizeOffsetValue(ConstantInt::get(Context, Const.Size), diff --git a/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll b/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll index 4f4d6a88e1693b..2974228e6a8303 100644 --- a/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll +++ b/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll @@ -117,3 +117,257 @@ if.end: %size = call i64 @llvm.objectsize.i64.p0(ptr %p, i1 true, i1 true, i1 false) ret i64 %size } + +define i64 @pick_negative_offset(i32 %n) { +; CHECK-LABEL: @pick_negative_offset( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[BUFFER0:%.*]] = alloca i8, i64 20, align 1 +; CHECK-NEXT: [[OFFSETED0:%.*]] = getelementptr i8, ptr [[BUFFER0]], i64 20 +; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[BUFFER1:%.*]] = alloca i8, i64 20, align 1 +; CHECK-NEXT: [[OFFSETED1:%.*]] = getelementptr i8, ptr [[BUFFER1]], i64 20 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[OFFSETED1]], [[IF_ELSE]] ], [ [[OFFSETED0]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[POFFSETED:%.*]] = getelementptr i8, ptr [[P]], i64 -4 +; CHECK-NEXT: ret i64 4 +; +entry: + %buffer0 = alloca i8, i64 20 + %offseted0 = getelementptr i8, ptr %buffer0, i64 20 + %cond = icmp eq i32 %n, 0 + br i1 %cond, label %if.else, label %if.end ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/114786 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits