[llvm] [llvm] Fix __builtin_object_size interaction between Negative Offset … (PR #111827)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 19 14:24:30 PDT 2024
https://github.com/serge-sans-paille updated https://github.com/llvm/llvm-project/pull/111827
>From 294688cc4b8411d30ec3db8ea26a774f0c6d24ea Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton at mozilla.com>
Date: Thu, 10 Oct 2024 13:59:22 +0200
Subject: [PATCH 1/2] [llvm] Fix __builtin_object_size interaction between
Negative Offset and Select/Phi
When picking a SizeOffsetAPInt through combineSizeOffset, the current
constant offset that has been extracted should be taken into account to
perform the right decision, otherwise in the presence of nullptr, we may
perform the wrong decision.
Fix #111709
---
llvm/include/llvm/Analysis/MemoryBuiltins.h | 2 +
llvm/lib/Analysis/MemoryBuiltins.cpp | 45 ++++--
.../builtin-object-size-phi.ll | 130 ++++++++++++++++++
3 files changed, 169 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h
index 7b48844cc9e8e9..01c642d4f48abd 100644
--- a/llvm/include/llvm/Analysis/MemoryBuiltins.h
+++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h
@@ -160,6 +160,7 @@ struct ObjectSizeOpts {
/// though they can't be evaluated. Otherwise, null is always considered to
/// point to a 0 byte region of memory.
bool NullIsUnknownSize = false;
+
/// If set, used for more accurate evaluation
AAResults *AA = nullptr;
};
@@ -230,6 +231,7 @@ class ObjectSizeOffsetVisitor
ObjectSizeOpts Options;
unsigned IntTyBits;
APInt Zero;
+ APInt ConstantOffset;
SmallDenseMap<Instruction *, SizeOffsetAPInt, 8> SeenInsts;
unsigned InstructionsVisited;
diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp
index e1abf5e4d885ec..762b385d77fb6f 100644
--- a/llvm/lib/Analysis/MemoryBuiltins.cpp
+++ b/llvm/lib/Analysis/MemoryBuiltins.cpp
@@ -570,6 +570,14 @@ static APInt getSizeWithOverflow(const SizeOffsetAPInt &Data) {
return Size - Offset;
}
+static SizeOffsetAPInt applyConstantOffset(SizeOffsetAPInt SOT,
+ APInt ConstantOffset) {
+ if (ConstantOffset.isZero())
+ return SOT;
+ return {SOT.Size, SOT.Offset.getBitWidth() > 1 ? SOT.Offset + ConstantOffset
+ : SOT.Offset};
+}
+
/// Compute the size of the object pointed by Ptr. Returns true and the
/// object size in Size if successful, and false otherwise.
/// If RoundToAlign is true, then Size is rounded up to the alignment of
@@ -697,7 +705,8 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::computeImpl(Value *V) {
// the index type size and if we stripped address space casts we have to
// readjust the APInt as we pass it upwards in order for the APInt to match
// the type the caller passed in.
- APInt Offset(InitialIntTyBits, 0);
+
+ APInt Offset = APInt{InitialIntTyBits, 0};
V = V->stripAndAccumulateConstantOffsets(
DL, Offset, /* AllowNonInbounds */ true, /* AllowInvariantGroup */ true);
@@ -706,7 +715,14 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::computeImpl(Value *V) {
IntTyBits = DL.getIndexTypeSizeInBits(V->getType());
Zero = APInt::getZero(IntTyBits);
+ APInt PrevConstantOffset = ConstantOffset;
+
+ if (!::CheckedZextOrTrunc(ConstantOffset, InitialIntTyBits))
+ return ObjectSizeOffsetVisitor::unknown();
+
+ ConstantOffset += Offset;
SizeOffsetAPInt SOT = computeValue(V);
+ ConstantOffset = PrevConstantOffset;
bool IndexTypeSizeChanged = InitialIntTyBits != IntTyBits;
if (!IndexTypeSizeChanged && Offset.isZero())
@@ -722,9 +738,9 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::computeImpl(Value *V) {
!::CheckedZextOrTrunc(SOT.Offset, InitialIntTyBits))
SOT.Offset = 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};
+ return applyConstantOffset(SOT, Offset);
}
SizeOffsetAPInt ObjectSizeOffsetVisitor::computeValue(Value *V) {
@@ -981,18 +997,28 @@ ObjectSizeOffsetVisitor::combineSizeOffset(SizeOffsetAPInt LHS,
SizeOffsetAPInt RHS) {
if (!LHS.bothKnown() || !RHS.bothKnown())
return ObjectSizeOffsetVisitor::unknown();
+ SizeOffsetAPInt AdjustedLHS = applyConstantOffset(LHS, ConstantOffset);
+ SizeOffsetAPInt AdjustedRHS = applyConstantOffset(RHS, ConstantOffset);
switch (Options.EvalMode) {
case ObjectSizeOpts::Mode::Min:
- return (getSizeWithOverflow(LHS).slt(getSizeWithOverflow(RHS))) ? LHS : RHS;
+ return (getSizeWithOverflow(AdjustedLHS)
+ .slt(getSizeWithOverflow(AdjustedRHS)))
+ ? LHS
+ : RHS;
case ObjectSizeOpts::Mode::Max:
- return (getSizeWithOverflow(LHS).sgt(getSizeWithOverflow(RHS))) ? LHS : RHS;
+ return (getSizeWithOverflow(AdjustedLHS)
+ .sgt(getSizeWithOverflow(AdjustedRHS)))
+ ? LHS
+ : RHS;
case ObjectSizeOpts::Mode::ExactSizeFromOffset:
- return (getSizeWithOverflow(LHS).eq(getSizeWithOverflow(RHS)))
+ return (getSizeWithOverflow(AdjustedLHS)
+ .eq(getSizeWithOverflow(AdjustedRHS)))
? LHS
: ObjectSizeOffsetVisitor::unknown();
case ObjectSizeOpts::Mode::ExactUnderlyingSizeAndOffset:
- return LHS == RHS ? LHS : ObjectSizeOffsetVisitor::unknown();
+ return AdjustedLHS == AdjustedRHS ? LHS
+ : ObjectSizeOffsetVisitor::unknown();
}
llvm_unreachable("missing an eval mode");
}
@@ -1000,11 +1026,14 @@ ObjectSizeOffsetVisitor::combineSizeOffset(SizeOffsetAPInt LHS,
SizeOffsetAPInt 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));
+ SizeOffsetAPInt RHS = computeImpl(VRHS);
+ return combineSizeOffset(LHS, RHS);
});
}
diff --git a/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll b/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll
index 4f4d6a88e1693b..d9e7d628ce6cbb 100644
--- a/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll
+++ b/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll
@@ -117,3 +117,133 @@ 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
+
+if.else:
+ %buffer1 = alloca i8, i64 20
+ %offseted1 = getelementptr i8, ptr %buffer1, i64 20
+ br label %if.end
+
+if.end:
+ %p = phi ptr [ %offseted1, %if.else ], [ %offseted0, %entry ]
+ %poffseted = getelementptr i8, ptr %p, i64 -4
+ %size = call i64 @llvm.objectsize.i64.p0(ptr %poffseted, i1 false, i1 false, i1 false)
+ ret i64 %size
+}
+
+define i64 @pick_negative_offset_with_nullptr(i32 %n) {
+; CHECK-LABEL: @pick_negative_offset_with_nullptr(
+; 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: br label [[IF_END]]
+; CHECK: if.end:
+; CHECK-NEXT: [[P0:%.*]] = phi ptr [ [[OFFSETED0]], [[ENTRY:%.*]] ], [ null, [[IF_ELSE]] ]
+; CHECK-NEXT: [[P1:%.*]] = phi ptr [ null, [[IF_ELSE]] ], [ [[OFFSETED0]], [[ENTRY]] ]
+; CHECK-NEXT: [[P0OFFSETED:%.*]] = getelementptr i8, ptr [[P0]], i64 -4
+; CHECK-NEXT: [[P1OFFSETED:%.*]] = getelementptr i8, ptr [[P1]], 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
+
+if.else:
+ br label %if.end
+
+if.end:
+ %p0 = phi ptr [ %offseted0, %entry ], [ null, %if.else ]
+ %p1 = phi ptr [ null, %if.else ], [ %offseted0, %entry ]
+ %p0offseted = getelementptr i8, ptr %p0, i64 -4
+ %p1offseted = getelementptr i8, ptr %p1, i64 -4
+ %size0 = call i64 @llvm.objectsize.i64.p0(ptr %p0offseted, i1 false, i1 false, i1 false)
+ %size1 = call i64 @llvm.objectsize.i64.p0(ptr %p1offseted, i1 false, i1 false, i1 false)
+ %size = select i1 %cond, i64 %size0, i64 %size1
+ ret i64 %size
+}
+
+define i64 @pick_negative_offset_with_unsized_nullptr(i32 %n) {
+; CHECK-LABEL: @pick_negative_offset_with_unsized_nullptr(
+; 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: br label [[IF_END]]
+; CHECK: if.end:
+; CHECK-NEXT: [[P0:%.*]] = phi ptr [ [[OFFSETED0]], [[ENTRY:%.*]] ], [ null, [[IF_ELSE]] ]
+; CHECK-NEXT: [[P1:%.*]] = phi ptr [ null, [[IF_ELSE]] ], [ [[OFFSETED0]], [[ENTRY]] ]
+; CHECK-NEXT: [[P0OFFSETED:%.*]] = getelementptr i8, ptr [[P0]], i64 -4
+; CHECK-NEXT: [[P1OFFSETED:%.*]] = getelementptr i8, ptr [[P1]], i64 -4
+; CHECK-NEXT: ret i64 -1
+;
+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
+
+if.else:
+ br label %if.end
+
+if.end:
+ %p0 = phi ptr [ %offseted0, %entry ], [ null, %if.else ]
+ %p1 = phi ptr [ null, %if.else ], [ %offseted0, %entry ]
+ %p0offseted = getelementptr i8, ptr %p0, i64 -4
+ %p1offseted = getelementptr i8, ptr %p1, i64 -4
+ %size0 = call i64 @llvm.objectsize.i64.p0(ptr %p0offseted, i1 false, i1 true, i1 false)
+ %size1 = call i64 @llvm.objectsize.i64.p0(ptr %p1offseted, i1 false, i1 true, i1 false)
+ %size = select i1 %cond, i64 %size0, i64 %size1
+ ret i64 %size
+}
+
+define i64 @chain_pick_negative_offset_with_nullptr(i32 %x) {
+; CHECK-LABEL: @chain_pick_negative_offset_with_nullptr(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[ARRAY:%.*]] = alloca [4 x i32], align 4
+; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[P:%.*]] = getelementptr i8, ptr [[ARRAY]], i64 8
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], ptr [[P]], ptr null
+; CHECK-NEXT: [[P4:%.*]] = getelementptr i8, ptr [[COND]], i64 8
+; CHECK-NEXT: [[COND6:%.*]] = select i1 [[C]], ptr [[P4]], ptr null
+; CHECK-NEXT: [[P7:%.*]] = getelementptr i8, ptr [[COND6]], i64 -4
+; CHECK-NEXT: ret i64 4
+;
+entry:
+ %array = alloca [4 x i32]
+ %c = icmp eq i32 %x, 0
+ %p = getelementptr i8, ptr %array, i64 8
+ %cond = select i1 %c, ptr %p, ptr null
+ %p4 = getelementptr i8, ptr %cond, i64 8
+ %cond6 = select i1 %c, ptr %p4, ptr null
+ %p7 = getelementptr i8, ptr %cond6, i64 -4
+ %size = call i64 @llvm.objectsize.i64.p0(ptr %p7, i1 false, i1 false, i1 false)
+ ret i64 %size
+}
>From b7e6d77ab098ab0dbe5d915240af3cd0fd6b4a88 Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton at mozilla.com>
Date: Sat, 19 Oct 2024 08:27:49 +0200
Subject: [PATCH 2/2] [llvm] Fix invalid clamping of
__builtin_dynamic_object_size
The offset applied to the pointer passed as first argument of
__builtin_dynamic_object_size maybe negative, so the clamping operation
should be signed.
---
llvm/lib/Analysis/MemoryBuiltins.cpp | 3 +-
.../builtin-dynamic-object-size.ll | 21 ++++-----
.../builtin-object-size-phi.ll | 46 +++++++++++++++++++
.../objectsize_basic.ll | 2 +-
4 files changed, 59 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp
index 762b385d77fb6f..a6383f125b4bc9 100644
--- a/llvm/lib/Analysis/MemoryBuiltins.cpp
+++ b/llvm/lib/Analysis/MemoryBuiltins.cpp
@@ -651,7 +651,7 @@ Value *llvm::lowerObjectSizeCall(
// If we've outside the end of the object, then we can always access
// exactly 0 bytes.
Value *ResultSize = Builder.CreateSub(Size, Offset);
- Value *UseZero = Builder.CreateICmpULT(Size, Offset);
+ Value *UseZero = Builder.CreateICmpSLT(ResultSize, Offset);
ResultSize = Builder.CreateZExtOrTrunc(ResultSize, ResultType);
Value *Ret = Builder.CreateSelect(
UseZero, ConstantInt::get(ResultType, 0), ResultSize);
@@ -717,6 +717,7 @@ SizeOffsetAPInt ObjectSizeOffsetVisitor::computeImpl(Value *V) {
APInt PrevConstantOffset = ConstantOffset;
+ // Accumulate the constant offset if possible, otherwise bail out.
if (!::CheckedZextOrTrunc(ConstantOffset, InitialIntTyBits))
return ObjectSizeOffsetVisitor::unknown();
diff --git a/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll b/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll
index 7a53ca996dc5a1..85258d576f8dd2 100644
--- a/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll
+++ b/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll
@@ -9,9 +9,8 @@ define i64 @weird_identity_but_ok(i64 %sz) {
; CHECK-LABEL: define i64 @weird_identity_but_ok
; CHECK-SAME: (i64 [[SZ:%.*]]) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[SZ]], -1
-; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
-; CHECK-NEXT: ret i64 [[SZ]]
+; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.smax.i64(i64 [[SZ]], i64 0)
+; CHECK-NEXT: ret i64 [[TMP0]]
;
entry:
%call = tail call ptr @malloc(i64 %sz)
@@ -54,8 +53,10 @@ define i64 @internal_pointer(i64 %sz) {
; CHECK-LABEL: define i64 @internal_pointer
; CHECK-SAME: (i64 [[SZ:%.*]]) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[SZ]], i64 2)
-; CHECK-NEXT: ret i64 [[TMP0]]
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[SZ]], -2
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[TMP0]], 2
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP0]]
+; CHECK-NEXT: ret i64 [[TMP2]]
;
entry:
%ptr = call ptr @malloc(i64 %sz)
@@ -140,11 +141,10 @@ define void @bdos_cmpm1(i64 %alloc) {
; CHECK-SAME: (i64 [[ALLOC:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[OBJ:%.*]] = call ptr @malloc(i64 [[ALLOC]])
-; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[ALLOC]], -1
-; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT: br i1 false, label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
; CHECK: if.then:
-; CHECK-NEXT: call void @fortified_chk(ptr [[OBJ]], i64 [[ALLOC]])
+; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.smax.i64(i64 [[ALLOC]], i64 0)
+; CHECK-NEXT: call void @fortified_chk(ptr [[OBJ]], i64 [[TMP0]])
; CHECK-NEXT: br label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: br label [[IF_END]]
@@ -175,11 +175,10 @@ define void @bdos_cmpm1_expr(i64 %alloc, i64 %part) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SZ:%.*]] = udiv i64 [[ALLOC]], [[PART]]
; CHECK-NEXT: [[OBJ:%.*]] = call ptr @malloc(i64 [[SZ]])
-; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[SZ]], -1
-; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT: br i1 false, label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
; CHECK: if.then:
-; CHECK-NEXT: call void @fortified_chk(ptr [[OBJ]], i64 [[SZ]])
+; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.smax.i64(i64 [[SZ]], i64 0)
+; CHECK-NEXT: call void @fortified_chk(ptr [[OBJ]], i64 [[TMP0]])
; CHECK-NEXT: br label [[IF_END:%.*]]
; CHECK: if.else:
; CHECK-NEXT: br label [[IF_END]]
diff --git a/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll b/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll
index d9e7d628ce6cbb..c0e9bf10b417ca 100644
--- a/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll
+++ b/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll
@@ -247,3 +247,49 @@ entry:
%size = call i64 @llvm.objectsize.i64.p0(ptr %p7, i1 false, i1 false, i1 false)
ret i64 %size
}
+
+
+define i64 @negative_offset_dynamic_eval(i32 %x, i64 %i) {
+; CHECK-LABEL: @negative_offset_dynamic_eval(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[ARRAY1:%.*]] = alloca [4 x i32], align 16
+; CHECK-NEXT: [[ARRAY2:%.*]] = alloca [8 x i32], align 16
+; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: br label [[IF_END:%.*]]
+; CHECK: if.else:
+; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[ARRAY2]], i64 16
+; CHECK-NEXT: br label [[IF_END]]
+; CHECK: if.end:
+; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[ARRAY1]], [[IF_THEN]] ], [ [[ADD_PTR]], [[IF_ELSE]] ]
+; CHECK-NEXT: [[ADD_PTR2_IDX:%.*]] = mul i64 [[I:%.*]], 4
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 16, [[ADD_PTR2_IDX]]
+; CHECK-NEXT: [[ADD_PTR2:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[I]]
+; CHECK-NEXT: [[TMP1:%.*]] = sub i64 32, [[TMP0]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i64 [[TMP1]], [[TMP0]]
+; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 0, i64 [[TMP1]]
+; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i64 [[TMP3]], -1
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP4]])
+; CHECK-NEXT: ret i64 [[TMP3]]
+;
+entry:
+ %array1 = alloca [4 x i32], align 16
+ %array2 = alloca [8 x i32], align 16
+ %tobool.not = icmp eq i32 %x, 0
+ br i1 %tobool.not, label %if.else, label %if.then
+
+if.then:
+ br label %if.end
+
+if.else:
+ %add.ptr = getelementptr inbounds i8, ptr %array2, i64 16
+ br label %if.end
+
+if.end:
+ %ptr = phi ptr [ %array1, %if.then ], [ %add.ptr, %if.else ]
+ %add.ptr2 = getelementptr inbounds i32, ptr %ptr, i64 %i
+ %objsize = call i64 @llvm.objectsize.i64.p0(ptr %add.ptr2, i1 false, i1 true, i1 true)
+ ret i64 %objsize
+}
+
diff --git a/llvm/test/Transforms/LowerConstantIntrinsics/objectsize_basic.ll b/llvm/test/Transforms/LowerConstantIntrinsics/objectsize_basic.ll
index c90d5152e1a096..4a1a5098f73a51 100644
--- a/llvm/test/Transforms/LowerConstantIntrinsics/objectsize_basic.ll
+++ b/llvm/test/Transforms/LowerConstantIntrinsics/objectsize_basic.ll
@@ -123,7 +123,7 @@ define i64 @vla_pointer_size_mismatch(i42 %x) {
; CHECK-NEXT: [[A:%.*]] = alloca i8, i42 [[X]], align 1
; CHECK-NEXT: [[G1:%.*]] = getelementptr i8, ptr [[A]], i8 17
; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[TMP2]], 17
-; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], 17
+; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i64 [[TMP3]], 17
; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i64 0, i64 [[TMP3]]
; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i64 [[TMP5]], -1
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP6]])
More information about the llvm-commits
mailing list