[ubsan] Skip null checks if they are constant-folded away
The IR builder can constant-fold null checks if the pointer operand
points to a constant. If the "is-non-null" check is folded away to
"true", don't emit the null check + branch.
Testing: check-clang, check-ubsan.
This slightly reduces the amount of null checks we emit when compiling
X86ISelLowering.cpp. Here are the numbers from patched/unpatched clangs
based on r300371.
-------------------------------------
| Setup | # of null checks |
-------------------------------------
| unpatched, -O0 | 25251 |
| patched, -O0 | 23925 | (-5.3%)
-------------------------------------
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300509 91177308-0d34-0410-b5e6-96231b3b80d8
(cherry picked from commit ebaaf85a35b6e2bd59bc6bfbefb66e7595c751d1)
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 0cf52c8..205b65e 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -567,15 +567,23 @@
// The glvalue must not be an empty glvalue.
llvm::Value *IsNonNull = Builder.CreateIsNotNull(Ptr);
- if (AllowNullPointers) {
- // When performing pointer casts, it's OK if the value is null.
- // Skip the remaining checks in that case.
- Done = createBasicBlock("null");
- llvm::BasicBlock *Rest = createBasicBlock("not.null");
- Builder.CreateCondBr(IsNonNull, Rest, Done);
- EmitBlock(Rest);
- } else {
- Checks.push_back(std::make_pair(IsNonNull, SanitizerKind::Null));
+ // The IR builder can constant-fold the null check if the pointer points to
+ // a constant.
+ bool PtrIsNonNull =
+ IsNonNull == llvm::ConstantInt::getTrue(getLLVMContext());
+
+ // Skip the null check if the pointer is known to be non-null.
+ if (!PtrIsNonNull) {
+ if (AllowNullPointers) {
+ // When performing pointer casts, it's OK if the value is null.
+ // Skip the remaining checks in that case.
+ Done = createBasicBlock("null");
+ llvm::BasicBlock *Rest = createBasicBlock("not.null");
+ Builder.CreateCondBr(IsNonNull, Rest, Done);
+ EmitBlock(Rest);
+ } else {
+ Checks.push_back(std::make_pair(IsNonNull, SanitizerKind::Null));
+ }
}
}
diff --git a/test/CodeGenCXX/ubsan-suppress-checks.cpp b/test/CodeGenCXX/ubsan-suppress-checks.cpp
index a8ca24b..d0e7b32 100644
--- a/test/CodeGenCXX/ubsan-suppress-checks.cpp
+++ b/test/CodeGenCXX/ubsan-suppress-checks.cpp
@@ -10,6 +10,8 @@
int arr[1];
arr[0] = arr[0];
+ char c = "foo"[0];
+
// CHECK-NOT: icmp ne {{.*}}, null, !nosanitize
// CHECK: ret void
}