[llvm-branch-commits] [llvm] 6fcb039 - Fold comparison of __builtin_object_size expression with -1 for non-const size

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Dec 22 02:00:45 PST 2020


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*)


        


More information about the llvm-branch-commits mailing list