Value *UseZero =
Builder.CreateICmpULT(SizeOffsetPair.first, SizeOffsetPair.second);
ResultSize = Builder.CreateZExtOrTrunc(ResultSize, ResultType);
- return Builder.CreateSelect(UseZero, ConstantInt::get(ResultType, 0),
- ResultSize);
+ Value *Ret = Builder.CreateSelect(
+ UseZero, ConstantInt::get(ResultType, 0), ResultSize);
+
+ // The non-constant size expression cannot evaluate to -1.
+ if (!isa<Constant>(SizeOffsetPair.first) ||
+ !isa<Constant>(SizeOffsetPair.second))
+ Builder.CreateAssumption(
+ Builder.CreateICmpNE(Ret, ConstantInt::get(ResultType, -1)));
+
+ return Ret;
}
}
; CHECK: define i64 @weird_identity_but_ok(i64 %sz)
; CHECK-NEXT: entry:
-; CHECK-NEXT: ret i64 %sz
+; CHECK: ret i64 %sz
; CHECK-NEXT: }
define i64 @phis_are_neat(i1 %which) {
; CHECK: define void @f()
; CHECK: call i64 @llvm.objectsize.i64.p0i8(
+define void @bdos_cmpm1(i64 %alloc) {
+entry:
+ %obj = call i8* @malloc(i64 %alloc)
+ %objsize = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 0, i1 0, i1 1)
+ %cmp.not = icmp eq i64 %objsize, -1
+ br i1 %cmp.not, label %if.else, label %if.then
+
+if.then:
+ call void @fortified_chk(i8* %obj, i64 %objsize)
+ br label %if.end
+
+if.else:
+ call void @unfortified(i8* %obj, i64 %objsize)
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ ret void
+}
+
+; CHECK: define void @bdos_cmpm1(
+; CHECK: [[TMP:%.*]] = icmp ne i64 %alloc, -1
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP]])
+; CHECK-NEXT: br i1 false, label %if.else, label %if.then
+; CHECK: call void @fortified_chk(i8* %obj, i64 %alloc)
+
+define void @bdos_cmpm1_expr(i64 %alloc, i64 %part) {
+entry:
+ %sz = udiv i64 %alloc, %part
+ %obj = call i8* @malloc(i64 %sz)
+ %objsize = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 0, i1 0, i1 1)
+ %cmp.not = icmp eq i64 %objsize, -1
+ br i1 %cmp.not, label %if.else, label %if.then
+
+if.then:
+ call void @fortified_chk(i8* %obj, i64 %objsize)
+ br label %if.end
+
+if.else:
+ call void @unfortified(i8* %obj, i64 %objsize)
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ ret void
+}
+
+; CHECK: define void @bdos_cmpm1_expr(
+; CHECK: [[TMP:%.*]] = icmp ne i64 [[SZ:%.*]], -1
+; CHECK-NEXT: call void @llvm.assume(i1 [[TMP]])
+; CHECK-NEXT: br i1 false, label %if.else, label %if.then
+; CHECK: call void @fortified_chk(i8* %obj, i64 [[SZ]])
+
declare void @bury(i32) local_unnamed_addr #2
; Function Attrs: nounwind allocsize(0)
; Function Attrs: nounwind readnone speculatable
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1)
+
+declare void @fortified_chk(i8*, i64)
+
+declare void @unfortified(i8*, i64)
+++ /dev/null
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -instcombine --instcombine-max-iterations=0 -S | FileCheck %s --check-prefix=ZERO
-; RUN: opt < %s -instcombine --instcombine-max-iterations=1 -S | FileCheck %s --check-prefix=ONE
-; RUN: opt < %s -instcombine -S | FileCheck %s --check-prefix=FIXPOINT
-; RUN: not --crash opt < %s -instcombine -S --instcombine-infinite-loop-threshold=2 2>&1 | FileCheck %s --check-prefix=LOOP
-
-; Based on builtin-dynamic-object-size.ll. This requires multiple iterations of
-; InstCombine to reach a fixpoint.
-
-define i64 @weird_identity_but_ok(i64 %sz) {
-; ZERO-LABEL: @weird_identity_but_ok(
-; ZERO-NEXT: entry:
-; ZERO-NEXT: [[CALL:%.*]] = tail call i8* @malloc(i64 [[SZ:%.*]])
-; ZERO-NEXT: [[CALC_SIZE:%.*]] = tail call i64 @llvm.objectsize.i64.p0i8(i8* [[CALL]], i1 false, i1 true, i1 true)
-; ZERO-NEXT: tail call void @free(i8* [[CALL]])
-; ZERO-NEXT: ret i64 [[CALC_SIZE]]
-;
-; ONE-LABEL: @weird_identity_but_ok(
-; ONE-NEXT: entry:
-; ONE-NEXT: [[TMP0:%.*]] = sub i64 [[SZ:%.*]], 0
-; ONE-NEXT: [[TMP1:%.*]] = icmp ult i64 [[SZ]], 0
-; ONE-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP0]]
-; ONE-NEXT: ret i64 [[TMP2]]
-;
-; FIXPOINT-LABEL: @weird_identity_but_ok(
-; FIXPOINT-NEXT: entry:
-; FIXPOINT-NEXT: ret i64 [[SZ:%.*]]
-;
-; LOOP: LLVM ERROR: Instruction Combining seems stuck in an infinite loop after 2 iterations.
-entry:
- %call = tail call i8* @malloc(i64 %sz)
- %calc_size = tail call i64 @llvm.objectsize.i64.p0i8(i8* %call, i1 false, i1 true, i1 true)
- tail call void @free(i8* %call)
- ret i64 %calc_size
-}
-
-declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1)
-declare i8* @malloc(i64)
-declare void @free(i8*)