summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVedant Kumar <vsk@apple.com>2017-04-26 02:17:21 +0000
committerVedant Kumar <vsk@apple.com>2017-04-26 02:17:21 +0000
commite859ebbd0619c901f2f845c54ce484f5afdd8ab6 (patch)
tree3b553163aacada92afca4d47b3c9666bfc65c26d
parent0827b7ff3ecbe9d826ecc8fadb52717e373200e5 (diff)
downloadbcm5719-llvm-e859ebbd0619c901f2f845c54ce484f5afdd8ab6.tar.gz
bcm5719-llvm-e859ebbd0619c901f2f845c54ce484f5afdd8ab6.zip
[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%) ------------------------------------------ llvm-svn: 301377
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp21
-rw-r--r--clang/test/CodeGen/catch-undef-behavior.c8
-rw-r--r--clang/test/CodeGen/sanitize-recover.c10
-rw-r--r--clang/test/CodeGenCXX/ubsan-suppress-checks.cpp5
4 files changed, 12 insertions, 32 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 719147a58e0..d0aacf65428 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -533,15 +533,6 @@ bool CodeGenFunction::sanitizePerformTypeCheck() const {
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(TypeCheckKind TCK, SourceLocation Loc,
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(TypeCheckKind TCK, SourceLocation Loc,
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));
diff --git a/clang/test/CodeGen/catch-undef-behavior.c b/clang/test/CodeGen/catch-undef-behavior.c
index c5f3a79429a..e67f0a1f8ee 100644
--- a/clang/test/CodeGen/catch-undef-behavior.c
+++ b/clang/test/CodeGen/catch-undef-behavior.c
@@ -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]], {{.*}}
diff --git a/clang/test/CodeGen/sanitize-recover.c b/clang/test/CodeGen/sanitize-recover.c
index 99eff8518ce..d714d58c7f2 100644
--- a/clang/test/CodeGen/sanitize-recover.c
+++ b/clang/test/CodeGen/sanitize-recover.c
@@ -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(
}
diff --git a/clang/test/CodeGenCXX/ubsan-suppress-checks.cpp b/clang/test/CodeGenCXX/ubsan-suppress-checks.cpp
index d0e7b32ef96..ae7c94b34f2 100644
--- a/clang/test/CodeGenCXX/ubsan-suppress-checks.cpp
+++ b/clang/test/CodeGenCXX/ubsan-suppress-checks.cpp
@@ -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
}
OpenPOWER on IntegriCloud