Author: Siddhesh Poyarekar Date: 2020-12-22T10:56:31+01:00 New Revision: 6fcb039956483988fa4b82a9a3944084353d00a5
URL: https://github.com/llvm/llvm-project/commit/6fcb039956483988fa4b82a9a3944084353d00a5 DIFF: https://github.com/llvm/llvm-project/commit/6fcb039956483988fa4b82a9a3944084353d00a5.diff LOG: Fold comparison of __builtin_object_size expression with -1 for non-const size When __builtin_dynamic_object_size returns a non-constant expression, it cannot be -1 since that is an invalid return value for object size. However since passes running after the substitution don't know this, they are unable to optimize away the comparison and hence the comparison and branch stays in there. This change generates an appropriate call to llvm.assume to help the optimizer folding the test. glibc is considering adopting __builtin_dynamic_object_size for additional protection[1] and this change will help reduce branching overhead in fortified implementations of all of the functions that don't have the __builtin___*_chk type builtins, e.g. __ppoll_chk. Also remove the test limit-max-iterations.ll because it was deemed unnecessary during review. [1] https://sourceware.org/pipermail/libc-alpha/2020-November/120191.html Differential Revision: https://reviews.llvm.org/D93015 Added: Modified: llvm/lib/Analysis/MemoryBuiltins.cpp llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll Removed: llvm/test/Transforms/InstCombine/limit-max-iterations.ll ################################################################################ diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index cbb54e8efdc0..5d82d9dd6ea0 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -566,8 +566,16 @@ Value *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize, 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; } } diff --git a/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll b/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll index 4093a121060c..91c9d3c2827f 100644 --- a/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll +++ b/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll @@ -14,7 +14,7 @@ entry: ; 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 @@ for.end: ; preds = %for.body, %entry ; 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 @@ declare void @free(i8* nocapture) ; 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 index a29166c04256..000000000000 --- 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*) _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits