r301377 - [ubsan] Skip alignment checks on allocas with known alignment

Vedant Kumar via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 25 19:17:21 PDT 2017


Author: vedantk
Date: Tue Apr 25 21:17:21 2017
New Revision: 301377

URL: http://llvm.org/viewvc/llvm-project?rev=301377&view=rev
Log:
[ubsan] Skip alignment checks on allocas with known alignment

It's possible to determine the alignment of an alloca at compile-time.
Use this information to skip emitting some runtime alignment checks.

Testing: check-clang, check-ubsan.

This significantly reduces the amount of alignment checks we emit when
compiling X86ISelLowering.cpp. Here are the numbers from patched/unpatched
clangs based on r301361.

  ------------------------------------------
  | Setup          | # of alignment checks |
  ------------------------------------------
  | unpatched, -O0 |                 47195 |
  | patched, -O0   |                 30876 | (-34.6%)
  ------------------------------------------

Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/test/CodeGen/catch-undef-behavior.c
    cfe/trunk/test/CodeGen/sanitize-recover.c
    cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=301377&r1=301376&r2=301377&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Apr 25 21:17:21 2017
@@ -533,15 +533,6 @@ bool CodeGenFunction::sanitizePerformTyp
          SanOpts.has(SanitizerKind::Vptr);
 }
 
-/// Check if a runtime null check for \p Ptr can be omitted.
-static bool canOmitPointerNullCheck(llvm::Value *Ptr) {
-  // Note: do not perform any constant-folding in this function. That is best
-  // left to the IR builder.
-
-  // Pointers to alloca'd memory are non-null.
-  return isa<llvm::AllocaInst>(Ptr->stripPointerCastsNoFollowAliases());
-}
-
 void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
                                     llvm::Value *Ptr, QualType Ty,
                                     CharUnits Alignment,
@@ -560,11 +551,16 @@ void CodeGenFunction::EmitTypeCheck(Type
   SmallVector<std::pair<llvm::Value *, SanitizerMask>, 3> Checks;
   llvm::BasicBlock *Done = nullptr;
 
+  // Quickly determine whether we have a pointer to an alloca. It's possible
+  // to skip null checks, and some alignment checks, for these pointers. This
+  // can reduce compile-time significantly.
+  auto PtrToAlloca =
+      dyn_cast<llvm::AllocaInst>(Ptr->stripPointerCastsNoFollowAliases());
+
   bool AllowNullPointers = TCK == TCK_DowncastPointer || TCK == TCK_Upcast ||
                            TCK == TCK_UpcastToVirtualBase;
   if ((SanOpts.has(SanitizerKind::Null) || AllowNullPointers) &&
-      !SkippedChecks.has(SanitizerKind::Null) &&
-      !canOmitPointerNullCheck(Ptr)) {
+      !SkippedChecks.has(SanitizerKind::Null) && !PtrToAlloca) {
     // The glvalue must not be an empty glvalue.
     llvm::Value *IsNonNull = Builder.CreateIsNotNull(Ptr);
 
@@ -617,7 +613,8 @@ void CodeGenFunction::EmitTypeCheck(Type
       AlignVal = getContext().getTypeAlignInChars(Ty).getQuantity();
 
     // The glvalue must be suitably aligned.
-    if (AlignVal > 1) {
+    if (AlignVal > 1 &&
+        (!PtrToAlloca || PtrToAlloca->getAlignment() < AlignVal)) {
       llvm::Value *Align =
           Builder.CreateAnd(Builder.CreatePtrToInt(Ptr, IntPtrTy),
                             llvm::ConstantInt::get(IntPtrTy, AlignVal - 1));

Modified: cfe/trunk/test/CodeGen/catch-undef-behavior.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/catch-undef-behavior.c?rev=301377&r1=301376&r2=301377&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/catch-undef-behavior.c (original)
+++ cfe/trunk/test/CodeGen/catch-undef-behavior.c Tue Apr 25 21:17:21 2017
@@ -36,13 +36,7 @@ void foo() {
 
   // CHECK-COMMON:      %[[I8PTR:.*]] = bitcast i32* %[[PTR:.*]] to i8*
   // CHECK-COMMON-NEXT: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* %[[I8PTR]], i1 false, i1 false)
-  // CHECK-COMMON-NEXT: %[[CHECK0:.*]] = icmp uge i64 %[[SIZE]], 4
-
-  // CHECK-COMMON:      %[[PTRTOINT:.*]] = ptrtoint {{.*}}* %[[PTR]] to i64
-  // CHECK-COMMON-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRTOINT]], 3
-  // CHECK-COMMON-NEXT: %[[CHECK1:.*]] = icmp eq i64 %[[MISALIGN]], 0
-
-  // CHECK-COMMON:       %[[OK:.*]] = and i1 %[[CHECK0]], %[[CHECK1]]
+  // CHECK-COMMON-NEXT: %[[OK:.*]] = icmp uge i64 %[[SIZE]], 4
 
   // CHECK-UBSAN: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]], !nosanitize
   // CHECK-TRAP:  br i1 %[[OK]], {{.*}}

Modified: cfe/trunk/test/CodeGen/sanitize-recover.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/sanitize-recover.c?rev=301377&r1=301376&r2=301377&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/sanitize-recover.c (original)
+++ cfe/trunk/test/CodeGen/sanitize-recover.c Tue Apr 25 21:17:21 2017
@@ -22,15 +22,7 @@ void foo() {
   // PARTIAL:      %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false, i1 false)
   // PARTIAL-NEXT: %[[CHECK0:.*]] = icmp uge i64 %[[SIZE]], 4
 
-  // PARTIAL:      %[[MISALIGN:.*]] = and i64 {{.*}}, 3
-  // PARTIAL-NEXT: %[[CHECK1:.*]] = icmp eq i64 %[[MISALIGN]], 0
+  // PARTIAL:      br i1 %[[CHECK0]], {{.*}} !nosanitize
 
-  // PARTIAL:      %[[CHECK01:.*]] = and i1 %[[CHECK1]], %[[CHECK0]]
-
-  // PARTIAL:      br i1 %[[CHECK01]], {{.*}} !nosanitize
-  // PARTIAL:      br i1 %[[CHECK1]], {{.*}} !nosanitize
-
-  // PARTIAL:      call void @__ubsan_handle_type_mismatch_v1_abort(
-  // PARTIAL-NEXT: unreachable
   // PARTIAL:      call void @__ubsan_handle_type_mismatch_v1(
 }

Modified: cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp?rev=301377&r1=301376&r2=301377&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp Tue Apr 25 21:17:21 2017
@@ -12,6 +12,7 @@ void load_non_null_pointers() {
 
   char c = "foo"[0];
 
+  // CHECK-NOT: and i64 {{.*}}, !nosanitize
   // CHECK-NOT: icmp ne {{.*}}, null, !nosanitize
   // CHECK: ret void
 }
@@ -43,10 +44,6 @@ struct A {
     };
     f();
 
-    // LAMBDA: %[[LAMBDAINT:[0-9]+]] = ptrtoint %class.anon* %[[FUNCVAR:.*]] to i64, !nosanitize
-    // LAMBDA: and i64 %[[LAMBDAINT]], 7, !nosanitize
-    // LAMBDA: call void @__ubsan_handle_type_mismatch
-
     // LAMBDA-NOT: call void @__ubsan_handle_type_mismatch
     // LAMBDA: ret void
   }




More information about the cfe-commits mailing list