diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -566,8 +566,16 @@ 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(SizeOffsetPair.first) || + !isa(SizeOffsetPair.second)) + Builder.CreateAssumption( + Builder.CreateICmpNE(Ret, ConstantInt::get(ResultType, -1))); + + return Ret; } } diff --git a/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll b/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll --- a/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll +++ b/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll @@ -14,7 +14,7 @@ ; 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) { @@ -101,6 +101,57 @@ ; 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) @@ -113,3 +164,7 @@ ; 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) diff --git a/llvm/test/Transforms/InstCombine/limit-max-iterations.ll b/llvm/test/Transforms/InstCombine/limit-max-iterations.ll deleted file mode 100644 --- a/llvm/test/Transforms/InstCombine/limit-max-iterations.ll +++ /dev/null @@ -1,39 +0,0 @@ -; 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*)