[clang] [llvm] Remove -bounds-checking-unique-traps (replace with -fno-sanitize-merge=local-bounds) (PR #120682)
Thurston Dang via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 19 22:27:32 PST 2024
https://github.com/thurstond updated https://github.com/llvm/llvm-project/pull/120682
>From ee51ed7bd68df7b2dae3f1426471b34d0388a42f Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Fri, 20 Dec 2024 04:11:36 +0000
Subject: [PATCH 1/4] Remove -bounds-checking-unique-traps (replace with
-fno-sanitize-merge=local-bounds)
-fno-sanitize-merge (introduced in #120511) combines the functionality of -ubsan-unique-traps
and -bounds-checking-unique-traps, while allowing fine-grained control
of which UBSan checks to prevent merging. #120613 removed -ubsan-unique-traps.
This patch removes -bound-checking-unique-traps, which can be controlled
via -fno-sanitize-merge=local-bounds.
Note: this patch subtly changes -fsanitize-merge (the default) to also
include -fsanitize-merge=local-bounds. This is different from the
previous behavior, where -fsanitize-merge (or the old
-ubsan-unique-traps) did not affect local-bounds (requiring the separate
-bounds-checking-unique-traps). However, we argue that the new behavior
is more intuitive.
Removing -bounds-checking-unique-traps and merging its functionality into -fsanitize-merge breaks backwards compatibility; we hope that this is acceptable since '-mllvm -bounds-checking-unique-traps' was an experimental flag.
---
clang/docs/ReleaseNotes.rst | 14 ++-
clang/lib/CodeGen/BackendUtil.cpp | 5 +-
clang/test/CodeGen/bounds-checking.c | 14 ++-
.../Instrumentation/BoundsChecking.h | 15 ++-
llvm/lib/Passes/PassBuilder.cpp | 29 +++--
llvm/lib/Passes/PassRegistry.def | 4 +-
.../Instrumentation/BoundsChecking.cpp | 24 ++--
.../BoundsChecking/runtimes.ll | 107 ++++++++++++++++++
.../BoundsChecking/ubsan-unique-traps.ll | 5 +-
9 files changed, 178 insertions(+), 39 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b8d92a6c881c68..0c6c894e17416a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -445,9 +445,10 @@ New Compiler Flags
- The ``-Warray-compare-cxx26`` warning has been added to warn about array comparison
starting from C++26, this warning is enabled as an error by default.
-- '-fsanitize-merge' (default) and '-fno-sanitize-merge' have been added for
- fine-grained control of which UBSan checks are allowed to be merged by the
- backend (for example, -fno-sanitize-merge=bool,enum).
+- ``-fsanitize-merge`` (default) and ``-fno-sanitize-merge`` have been added for
+ fine-grained, unified control of which UBSan checks can potentially be merged
+ by the compiler (for example,
+ ``-fno-sanitize-merge=bool,enum,array-bounds,local-bounds``).
Deprecated Compiler Flags
-------------------------
@@ -488,8 +489,11 @@ Removed Compiler Flags
derivatives) is now removed, since it's no longer possible to suppress the
diagnostic (see above). Users can expect an `unknown warning` diagnostic if
it's still in use.
-- The experimental flag '-ubsan-unique-traps' has been removed. It is
- superseded by '-fno-sanitize-merge'.
+- The experimental flags '-ubsan-unique-traps' and
+ '-bounds-checking-unique-traps' have been removed. The combination of the
+ two flags is equivalent to '-fno-sanitize-merge' with no parameters.
+ '-bounds-checking-unique-traps' can be selectively controlled via
+ '-f(no-)sanitize-merge=local-bounds'.
Attribute Changes in Clang
--------------------------
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index e6c9d77d29f6f1..bfb73aa51b9b5b 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1030,6 +1030,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
PB.registerScalarOptimizerLateEPCallback(
[this](FunctionPassManager &FPM, OptimizationLevel Level) {
BoundsCheckingPass::ReportingMode Mode;
+ bool Merge = CodeGenOpts.SanitizeMergeHandlers.has(SanitizerKind::LocalBounds);
+
if (CodeGenOpts.SanitizeTrap.has(SanitizerKind::LocalBounds)) {
Mode = BoundsCheckingPass::ReportingMode::Trap;
} else if (CodeGenOpts.SanitizeMinimalRuntime) {
@@ -1041,7 +1043,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
? BoundsCheckingPass::ReportingMode::FullRuntime
: BoundsCheckingPass::ReportingMode::FullRuntimeAbort;
}
- FPM.addPass(BoundsCheckingPass(Mode));
+ BoundsCheckingPass::BoundsCheckingOptions Options(Mode, Merge);
+ FPM.addPass(BoundsCheckingPass(Options));
});
// Don't add sanitizers if we are here from ThinLTO PostLink. That already
diff --git a/clang/test/CodeGen/bounds-checking.c b/clang/test/CodeGen/bounds-checking.c
index f9319ca61670c3..5e6b317a99969e 100644
--- a/clang/test/CodeGen/bounds-checking.c
+++ b/clang/test/CodeGen/bounds-checking.c
@@ -1,12 +1,14 @@
-// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
-// RUN: %clang_cc1 -fsanitize=array-bounds -O -emit-llvm -triple x86_64-apple-darwin10 %s -o - | not FileCheck %s
+// N.B. The clang driver defaults to -fsanitize-merge but clang_cc1 effectively
+// defaults to -fno-sanitize-merge.
// RUN: %clang_cc1 -fsanitize=array-bounds -O -fsanitize-trap=array-bounds -emit-llvm -triple x86_64-apple-darwin10 -DNO_DYNAMIC %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fsanitize=array-bounds -O -emit-llvm -triple x86_64-apple-darwin10 %s -o - | not FileCheck %s
//
-// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -O3 -mllvm -bounds-checking-unique-traps -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefixes=NOOPTLOCAL
-// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | not FileCheck %s --check-prefixes=NOOPTLOCAL
+// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
+//
+// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefixes=NOOPTLOCAL
+// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -fno-sanitize-merge -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefixes=NOOPTLOCAL
+// RUN: %clang_cc1 -fsanitize=local-bounds -fsanitize-trap=local-bounds -fsanitize-merge=local-bounds -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | not FileCheck %s --check-prefixes=NOOPTLOCAL
//
-// N.B. The clang driver defaults to -fsanitize-merge but clang_cc1 effectively
-// defaults to -fno-sanitize-merge.
// RUN: %clang_cc1 -fsanitize=array-bounds -fsanitize-trap=array-bounds -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefixes=NOOPTARRAY
// RUN: %clang_cc1 -fsanitize=array-bounds -fsanitize-trap=array-bounds -fno-sanitize-merge -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | FileCheck %s --check-prefixes=NOOPTARRAY
// RUN: %clang_cc1 -fsanitize=array-bounds -fsanitize-trap=array-bounds -fsanitize-merge=array-bounds -O3 -emit-llvm -triple x86_64-apple-darwin10 %s -o - | not FileCheck %s --check-prefixes=NOOPTARRAY
diff --git a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
index 1876e5b72e8c99..eca93d89838134 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
@@ -17,6 +17,7 @@ class Function;
/// A pass to instrument code and perform run-time bounds checking on loads,
/// stores, and other memory intrinsics.
class BoundsCheckingPass : public PassInfoMixin<BoundsCheckingPass> {
+
public:
enum class ReportingMode {
Trap,
@@ -26,15 +27,21 @@ class BoundsCheckingPass : public PassInfoMixin<BoundsCheckingPass> {
FullRuntimeAbort,
};
-private:
- ReportingMode Mode = ReportingMode::Trap;
+ struct BoundsCheckingOptions {
+ BoundsCheckingOptions(ReportingMode Mode, bool Merge);
-public:
- BoundsCheckingPass(ReportingMode Mode) : Mode(Mode) {}
+ ReportingMode Mode;
+ bool Merge;
+ };
+
+ BoundsCheckingPass(BoundsCheckingOptions Options) : Options(Options) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
static bool isRequired() { return true; }
void printPipeline(raw_ostream &OS,
function_ref<StringRef(StringRef)> MapClassName2PassName);
+
+ private:
+ BoundsCheckingOptions Options;
};
} // end namespace llvm
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index d70ac48f251180..87756acf724261 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -1281,23 +1281,34 @@ parseRegAllocFastPassOptions(PassBuilder &PB, StringRef Params) {
return Opts;
}
-Expected<BoundsCheckingPass::ReportingMode>
+Expected<BoundsCheckingPass::BoundsCheckingOptions>
parseBoundsCheckingOptions(StringRef Params) {
- BoundsCheckingPass::ReportingMode Mode =
- BoundsCheckingPass::ReportingMode::Trap;
+ BoundsCheckingPass::BoundsCheckingOptions Options (BoundsCheckingPass::ReportingMode::Trap, true);
while (!Params.empty()) {
StringRef ParamName;
std::tie(ParamName, Params) = Params.split(';');
if (ParamName == "trap") {
- Mode = BoundsCheckingPass::ReportingMode::Trap;
+ Options.Mode = BoundsCheckingPass::ReportingMode::Trap;
} else if (ParamName == "rt") {
- Mode = BoundsCheckingPass::ReportingMode::FullRuntime;
+ Options.Mode = BoundsCheckingPass::ReportingMode::FullRuntime;
} else if (ParamName == "rt-abort") {
- Mode = BoundsCheckingPass::ReportingMode::FullRuntimeAbort;
+ Options.Mode = BoundsCheckingPass::ReportingMode::FullRuntimeAbort;
} else if (ParamName == "min-rt") {
- Mode = BoundsCheckingPass::ReportingMode::MinRuntime;
+ Options.Mode = BoundsCheckingPass::ReportingMode::MinRuntime;
} else if (ParamName == "min-rt-abort") {
- Mode = BoundsCheckingPass::ReportingMode::MinRuntimeAbort;
+ Options.Mode = BoundsCheckingPass::ReportingMode::MinRuntimeAbort;
+ } else if (ParamName.consume_front("merge=")) {
+ if (ParamName == "true")
+ Options.Merge = true;
+ else if (ParamName == "false")
+ Options.Merge = false;
+ else {
+ return make_error<StringError>(
+ formatv("invalid BoundsChecking pass merge parameter: '{0}' ",
+ ParamName)
+ .str(),
+ inconvertibleErrorCode());
+ }
} else {
return make_error<StringError>(
formatv("invalid BoundsChecking pass parameter '{0}' ", ParamName)
@@ -1305,7 +1316,7 @@ parseBoundsCheckingOptions(StringRef Params) {
inconvertibleErrorCode());
}
}
- return Mode;
+ return Options;
}
} // namespace
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index ba3adcb0e317c0..9f0b09278edcca 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -624,8 +624,8 @@ FUNCTION_PASS_WITH_PARAMS(
parseWinEHPrepareOptions, "demote-catchswitch-only")
FUNCTION_PASS_WITH_PARAMS(
"bounds-checking", "BoundsCheckingPass",
- [](BoundsCheckingPass::ReportingMode Mode) {
- return BoundsCheckingPass(Mode);
+ [](BoundsCheckingPass::BoundsCheckingOptions Options) {
+ return BoundsCheckingPass(Options);
},
parseBoundsCheckingOptions, "trap")
#undef FUNCTION_PASS_WITH_PARAMS
diff --git a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp
index f639d0628d6053..5ce3e0de59c559 100644
--- a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp
+++ b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp
@@ -37,15 +37,15 @@ using namespace llvm;
static cl::opt<bool> SingleTrapBB("bounds-checking-single-trap",
cl::desc("Use one trap block per function"));
-static cl::opt<bool> DebugTrapBB("bounds-checking-unique-traps",
- cl::desc("Always use one trap per check"));
-
STATISTIC(ChecksAdded, "Bounds checks added");
STATISTIC(ChecksSkipped, "Bounds checks skipped");
STATISTIC(ChecksUnable, "Bounds checks unable to add");
using BuilderTy = IRBuilder<TargetFolder>;
+BoundsCheckingPass::BoundsCheckingOptions::BoundsCheckingOptions(ReportingMode Mode, bool Merge)
+ : Mode(Mode), Merge(Merge) {}
+
/// Gets the conditions under which memory accessing instructions will overflow.
///
/// \p Ptr is the pointer that will be read/written, and \p InstVal is either
@@ -105,7 +105,7 @@ static Value *getBoundsCheckCond(Value *Ptr, Value *InstVal,
return Or;
}
-static CallInst *InsertTrap(BuilderTy &IRB) {
+static CallInst *InsertTrap(BuilderTy &IRB, bool DebugTrapBB) {
if (!DebugTrapBB)
return IRB.CreateIntrinsic(Intrinsic::trap, {}, {});
// FIXME: Ideally we would use the SanitizerHandler::OutOfBounds constant.
@@ -169,9 +169,10 @@ struct ReportingOpts {
bool MayReturn = false;
bool UseTrap = false;
bool MinRuntime = false;
+ bool MayMerge = true;
StringRef Name;
- ReportingOpts(BoundsCheckingPass::ReportingMode Mode) {
+ ReportingOpts(BoundsCheckingPass::ReportingMode Mode, bool Merge) {
switch (Mode) {
case BoundsCheckingPass::ReportingMode::Trap:
UseTrap = true;
@@ -193,6 +194,8 @@ struct ReportingOpts {
Name = "__ubsan_handle_local_out_of_bounds_abort";
break;
}
+
+ MayMerge = Merge;
}
};
@@ -253,13 +256,12 @@ static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI,
BasicBlock *TrapBB = BasicBlock::Create(Fn->getContext(), "trap", Fn);
IRB.SetInsertPoint(TrapBB);
+ bool DebugTrapBB = !Opts.MayMerge;
CallInst *TrapCall = Opts.UseTrap
- ? InsertTrap(IRB)
+ ? InsertTrap(IRB, DebugTrapBB)
: InsertCall(IRB, Opts.MayReturn, Opts.Name);
- if (DebugTrapBB) {
- // FIXME: Pass option form clang.
+ if (DebugTrapBB)
TrapCall->addFnAttr(llvm::Attribute::NoMerge);
- }
TrapCall->setDoesNotThrow();
TrapCall->setDebugLoc(DebugLoc);
@@ -289,7 +291,7 @@ PreservedAnalyses BoundsCheckingPass::run(Function &F, FunctionAnalysisManager &
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
auto &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
- if (!addBoundsChecking(F, TLI, SE, ReportingOpts(Mode)))
+ if (!addBoundsChecking(F, TLI, SE, ReportingOpts(Options.Mode, Options.Merge)))
return PreservedAnalyses::all();
return PreservedAnalyses::none();
@@ -299,7 +301,7 @@ void BoundsCheckingPass::printPipeline(
raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
static_cast<PassInfoMixin<BoundsCheckingPass> *>(this)->printPipeline(
OS, MapClassName2PassName);
- switch (Mode) {
+ switch (Options.Mode) {
case ReportingMode::Trap:
OS << "<trap>";
break;
diff --git a/llvm/test/Instrumentation/BoundsChecking/runtimes.ll b/llvm/test/Instrumentation/BoundsChecking/runtimes.ll
index 357f92aca85c08..8726606665d7ca 100644
--- a/llvm/test/Instrumentation/BoundsChecking/runtimes.ll
+++ b/llvm/test/Instrumentation/BoundsChecking/runtimes.ll
@@ -5,6 +5,21 @@
; RUN: opt < %s -passes='bounds-checking<rt-abort>' -S | FileCheck %s --check-prefixes=RTABORT
; RUN: opt < %s -passes='bounds-checking<min-rt>' -S | FileCheck %s --check-prefixes=MINRT
; RUN: opt < %s -passes='bounds-checking<min-rt-abort>' -S | FileCheck %s --check-prefixes=MINRTABORT
+;
+; merge defaults to true
+; RUN: opt < %s -passes='bounds-checking<merge=true>' -S | FileCheck %s --check-prefixes=TR
+; RUN: opt < %s -passes='bounds-checking<trap;merge=true>' -S | FileCheck %s --check-prefixes=TR
+; RUN: opt < %s -passes='bounds-checking<rt;merge=true>' -S | FileCheck %s --check-prefixes=RT
+; RUN: opt < %s -passes='bounds-checking<rt-abort;merge=true>' -S | FileCheck %s --check-prefixes=RTABORT
+; RUN: opt < %s -passes='bounds-checking<min-rt;merge=true>' -S | FileCheck %s --check-prefixes=MINRT
+; RUN: opt < %s -passes='bounds-checking<min-rt-abort;merge=true>' -S | FileCheck %s --check-prefixes=MINRTABORT
+;
+; RUN: opt < %s -passes='bounds-checking<merge=false>' -S | FileCheck %s --check-prefixes=TR-NOMERGE
+; RUN: opt < %s -passes='bounds-checking<trap;merge=false>' -S | FileCheck %s --check-prefixes=TR-NOMERGE
+; RUN: opt < %s -passes='bounds-checking<rt;merge=false>' -S | FileCheck %s --check-prefixes=RT-NOMERGE
+; RUN: opt < %s -passes='bounds-checking<rt-abort;merge=false>' -S | FileCheck %s --check-prefixes=RTABORT-NOMERGE
+; RUN: opt < %s -passes='bounds-checking<min-rt;merge=false>' -S | FileCheck %s --check-prefixes=MINRT-NOMERGE
+; RUN: opt < %s -passes='bounds-checking<min-rt-abort;merge=false>' -S | FileCheck %s --check-prefixes=MINRTABORT-NOMERGE
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
@@ -88,8 +103,100 @@ define void @f1(i64 %x) nounwind {
; MINRTABORT: [[TRAP]]:
; MINRTABORT-NEXT: call void @__ubsan_handle_local_out_of_bounds_minimal_abort() #[[ATTR1:[0-9]+]]
; MINRTABORT-NEXT: unreachable
+;
+; TR-NOMERGE-LABEL: define void @f1(
+; TR-NOMERGE-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+; TR-NOMERGE-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]]
+; TR-NOMERGE-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8
+; TR-NOMERGE-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0
+; TR-NOMERGE-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16
+; TR-NOMERGE-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]]
+; TR-NOMERGE-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]]
+; TR-NOMERGE-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]]
+; TR-NOMERGE: [[BB7]]:
+; TR-NOMERGE-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
+; TR-NOMERGE-NEXT: ret void
+; TR-NOMERGE: [[TRAP]]:
+; TR-NOMERGE-NEXT: call void @llvm.ubsantrap(i8 3) #[[ATTR2:[0-9]+]]
+; TR-NOMERGE-NEXT: unreachable
+;
+; RT-NOMERGE-LABEL: define void @f1(
+; RT-NOMERGE-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+; RT-NOMERGE-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]]
+; RT-NOMERGE-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8
+; RT-NOMERGE-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0
+; RT-NOMERGE-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16
+; RT-NOMERGE-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]]
+; RT-NOMERGE-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]]
+; RT-NOMERGE-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]]
+; RT-NOMERGE: [[BB7]]:
+; RT-NOMERGE-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
+; RT-NOMERGE-NEXT: ret void
+; RT-NOMERGE: [[TRAP]]:
+; RT-NOMERGE-NEXT: call void @__ubsan_handle_local_out_of_bounds() #[[ATTR1:[0-9]+]]
+; RT-NOMERGE-NEXT: br label %[[BB7]]
+;
+; RTABORT-NOMERGE-LABEL: define void @f1(
+; RTABORT-NOMERGE-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+; RTABORT-NOMERGE-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]]
+; RTABORT-NOMERGE-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8
+; RTABORT-NOMERGE-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0
+; RTABORT-NOMERGE-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16
+; RTABORT-NOMERGE-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]]
+; RTABORT-NOMERGE-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]]
+; RTABORT-NOMERGE-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]]
+; RTABORT-NOMERGE: [[BB7]]:
+; RTABORT-NOMERGE-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
+; RTABORT-NOMERGE-NEXT: ret void
+; RTABORT-NOMERGE: [[TRAP]]:
+; RTABORT-NOMERGE-NEXT: call void @__ubsan_handle_local_out_of_bounds_abort() #[[ATTR2:[0-9]+]]
+; RTABORT-NOMERGE-NEXT: unreachable
+;
+; MINRT-NOMERGE-LABEL: define void @f1(
+; MINRT-NOMERGE-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+; MINRT-NOMERGE-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]]
+; MINRT-NOMERGE-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8
+; MINRT-NOMERGE-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0
+; MINRT-NOMERGE-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16
+; MINRT-NOMERGE-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]]
+; MINRT-NOMERGE-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]]
+; MINRT-NOMERGE-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]]
+; MINRT-NOMERGE: [[BB7]]:
+; MINRT-NOMERGE-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
+; MINRT-NOMERGE-NEXT: ret void
+; MINRT-NOMERGE: [[TRAP]]:
+; MINRT-NOMERGE-NEXT: call void @__ubsan_handle_local_out_of_bounds_minimal() #[[ATTR1:[0-9]+]]
+; MINRT-NOMERGE-NEXT: br label %[[BB7]]
+;
+; MINRTABORT-NOMERGE-LABEL: define void @f1(
+; MINRTABORT-NOMERGE-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+; MINRTABORT-NOMERGE-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]]
+; MINRTABORT-NOMERGE-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8
+; MINRTABORT-NOMERGE-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0
+; MINRTABORT-NOMERGE-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16
+; MINRTABORT-NOMERGE-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]]
+; MINRTABORT-NOMERGE-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]]
+; MINRTABORT-NOMERGE-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]]
+; MINRTABORT-NOMERGE: [[BB7]]:
+; MINRTABORT-NOMERGE-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
+; MINRTABORT-NOMERGE-NEXT: ret void
+; MINRTABORT-NOMERGE: [[TRAP]]:
+; MINRTABORT-NOMERGE-NEXT: call void @__ubsan_handle_local_out_of_bounds_minimal_abort() #[[ATTR2:[0-9]+]]
+; MINRTABORT-NOMERGE-NEXT: unreachable
;
%1 = alloca i128, i64 %x
%3 = load i128, ptr %1, align 4
ret void
}
+
+; TR: attributes #[[ATTR2]] = { noreturn nounwind }
+; RT: attributes #[[ATTR0]] = { nounwind }
+; RTABORT: attributes #[[ATTR1]] = { noreturn nounwind }
+; MINRT: attributes #[[ATTR0]] = { nounwind }
+; MINRTABORT: attributes #[[ATTR1]] = { noreturn nounwind }
+
+; TR-NOMERGE: attributes #[[ATTR2]] = { nomerge noreturn nounwind }
+; RT-NOMERGE: attributes #[[ATTR1]] = { nomerge nounwind }
+; RTABORT-NOMERGE: attributes #[[ATTR2]] = { nomerge noreturn nounwind }
+; MINRT-NOMERGE: attributes #[[ATTR1]] = { nomerge nounwind }
+; MINRTABORT-NOMERGE: attributes #[[ATTR2]] = { nomerge noreturn nounwind }
diff --git a/llvm/test/Instrumentation/BoundsChecking/ubsan-unique-traps.ll b/llvm/test/Instrumentation/BoundsChecking/ubsan-unique-traps.ll
index a3f34007e9b09f..a79db52905e824 100644
--- a/llvm/test/Instrumentation/BoundsChecking/ubsan-unique-traps.ll
+++ b/llvm/test/Instrumentation/BoundsChecking/ubsan-unique-traps.ll
@@ -1,5 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes=bounds-checking -bounds-checking-unique-traps -S | FileCheck %s
+; RUN: opt < %s -passes='bounds-checking<merge=false>' -S | FileCheck %s
+; RUN: opt < %s -passes='bounds-checking<merge=true>' -S | not FileCheck %s
+; RUN: opt < %s -passes=bounds-checking -S | not FileCheck %s
+
target datalayout = "e-p:64:64:64-p1:16:16:16-p2:64:64:64:48-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
declare noalias ptr @malloc(i64) nounwind allocsize(0)
>From 77a3e495adaa4ff98c0a8c8b62dddbf1788705f9 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Fri, 20 Dec 2024 04:26:09 +0000
Subject: [PATCH 2/4] clang-format
---
clang/lib/CodeGen/BackendUtil.cpp | 3 ++-
.../llvm/Transforms/Instrumentation/BoundsChecking.h | 4 ++--
llvm/lib/Passes/PassBuilder.cpp | 3 ++-
llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp | 6 ++++--
4 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index bfb73aa51b9b5b..04358cd6d7c232 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1030,7 +1030,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
PB.registerScalarOptimizerLateEPCallback(
[this](FunctionPassManager &FPM, OptimizationLevel Level) {
BoundsCheckingPass::ReportingMode Mode;
- bool Merge = CodeGenOpts.SanitizeMergeHandlers.has(SanitizerKind::LocalBounds);
+ bool Merge = CodeGenOpts.SanitizeMergeHandlers.has(
+ SanitizerKind::LocalBounds);
if (CodeGenOpts.SanitizeTrap.has(SanitizerKind::LocalBounds)) {
Mode = BoundsCheckingPass::ReportingMode::Trap;
diff --git a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
index eca93d89838134..ee71aa64f85eed 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
@@ -40,8 +40,8 @@ class BoundsCheckingPass : public PassInfoMixin<BoundsCheckingPass> {
void printPipeline(raw_ostream &OS,
function_ref<StringRef(StringRef)> MapClassName2PassName);
- private:
- BoundsCheckingOptions Options;
+private:
+ BoundsCheckingOptions Options;
};
} // end namespace llvm
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 87756acf724261..797915236ddbdb 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -1283,7 +1283,8 @@ parseRegAllocFastPassOptions(PassBuilder &PB, StringRef Params) {
Expected<BoundsCheckingPass::BoundsCheckingOptions>
parseBoundsCheckingOptions(StringRef Params) {
- BoundsCheckingPass::BoundsCheckingOptions Options (BoundsCheckingPass::ReportingMode::Trap, true);
+ BoundsCheckingPass::BoundsCheckingOptions Options(
+ BoundsCheckingPass::ReportingMode::Trap, true);
while (!Params.empty()) {
StringRef ParamName;
std::tie(ParamName, Params) = Params.split(';');
diff --git a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp
index 5ce3e0de59c559..4dc8f60d714bc1 100644
--- a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp
+++ b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp
@@ -43,7 +43,8 @@ STATISTIC(ChecksUnable, "Bounds checks unable to add");
using BuilderTy = IRBuilder<TargetFolder>;
-BoundsCheckingPass::BoundsCheckingOptions::BoundsCheckingOptions(ReportingMode Mode, bool Merge)
+BoundsCheckingPass::BoundsCheckingOptions::BoundsCheckingOptions(
+ ReportingMode Mode, bool Merge)
: Mode(Mode), Merge(Merge) {}
/// Gets the conditions under which memory accessing instructions will overflow.
@@ -291,7 +292,8 @@ PreservedAnalyses BoundsCheckingPass::run(Function &F, FunctionAnalysisManager &
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
auto &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
- if (!addBoundsChecking(F, TLI, SE, ReportingOpts(Options.Mode, Options.Merge)))
+ if (!addBoundsChecking(F, TLI, SE,
+ ReportingOpts(Options.Mode, Options.Merge)))
return PreservedAnalyses::all();
return PreservedAnalyses::none();
>From 94c8083d0e040c78fa671527b9e99e19c87735ce Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Fri, 20 Dec 2024 05:29:31 +0000
Subject: [PATCH 3/4] Address Vitaly's feedback
---
clang/docs/ReleaseNotes.rst | 15 ++--
llvm/lib/Passes/PassBuilder.cpp | 16 +---
.../Instrumentation/BoundsChecking.cpp | 13 +--
.../BoundsChecking/runtimes.ll | 85 +++----------------
4 files changed, 27 insertions(+), 102 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0c6c894e17416a..341c7682155fa0 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -445,11 +445,6 @@ New Compiler Flags
- The ``-Warray-compare-cxx26`` warning has been added to warn about array comparison
starting from C++26, this warning is enabled as an error by default.
-- ``-fsanitize-merge`` (default) and ``-fno-sanitize-merge`` have been added for
- fine-grained, unified control of which UBSan checks can potentially be merged
- by the compiler (for example,
- ``-fno-sanitize-merge=bool,enum,array-bounds,local-bounds``).
-
Deprecated Compiler Flags
-------------------------
@@ -489,11 +484,6 @@ Removed Compiler Flags
derivatives) is now removed, since it's no longer possible to suppress the
diagnostic (see above). Users can expect an `unknown warning` diagnostic if
it's still in use.
-- The experimental flags '-ubsan-unique-traps' and
- '-bounds-checking-unique-traps' have been removed. The combination of the
- two flags is equivalent to '-fno-sanitize-merge' with no parameters.
- '-bounds-checking-unique-traps' can be selectively controlled via
- '-f(no-)sanitize-merge=local-bounds'.
Attribute Changes in Clang
--------------------------
@@ -1212,6 +1202,11 @@ Sanitizers
- Implemented ``-f[no-]sanitize-trap=local-bounds``, and ``-f[no-]sanitize-recover=local-bounds``.
+- ``-fsanitize-merge`` (default) and ``-fno-sanitize-merge`` have been added for
+ fine-grained, unified control of which UBSan checks can potentially be merged
+ by the compiler (for example,
+ ``-fno-sanitize-merge=bool,enum,array-bounds,local-bounds``).
+
Python Binding Changes
----------------------
- Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``.
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 797915236ddbdb..a936f5381137c6 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -1284,7 +1284,7 @@ parseRegAllocFastPassOptions(PassBuilder &PB, StringRef Params) {
Expected<BoundsCheckingPass::BoundsCheckingOptions>
parseBoundsCheckingOptions(StringRef Params) {
BoundsCheckingPass::BoundsCheckingOptions Options(
- BoundsCheckingPass::ReportingMode::Trap, true);
+ BoundsCheckingPass::ReportingMode::Trap, false);
while (!Params.empty()) {
StringRef ParamName;
std::tie(ParamName, Params) = Params.split(';');
@@ -1298,18 +1298,8 @@ parseBoundsCheckingOptions(StringRef Params) {
Options.Mode = BoundsCheckingPass::ReportingMode::MinRuntime;
} else if (ParamName == "min-rt-abort") {
Options.Mode = BoundsCheckingPass::ReportingMode::MinRuntimeAbort;
- } else if (ParamName.consume_front("merge=")) {
- if (ParamName == "true")
- Options.Merge = true;
- else if (ParamName == "false")
- Options.Merge = false;
- else {
- return make_error<StringError>(
- formatv("invalid BoundsChecking pass merge parameter: '{0}' ",
- ParamName)
- .str(),
- inconvertibleErrorCode());
- }
+ } else if (ParamName == "merge") {
+ Options.Merge = true;
} else {
return make_error<StringError>(
formatv("invalid BoundsChecking pass parameter '{0}' ", ParamName)
diff --git a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp
index 4dc8f60d714bc1..41e50385812460 100644
--- a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp
+++ b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp
@@ -305,19 +305,22 @@ void BoundsCheckingPass::printPipeline(
OS, MapClassName2PassName);
switch (Options.Mode) {
case ReportingMode::Trap:
- OS << "<trap>";
+ OS << "<trap";
break;
case ReportingMode::MinRuntime:
- OS << "<min-rt>";
+ OS << "<min-rt";
break;
case ReportingMode::MinRuntimeAbort:
- OS << "<min-rt-abort>";
+ OS << "<min-rt-abort";
break;
case ReportingMode::FullRuntime:
- OS << "<rt>";
+ OS << "<rt";
break;
case ReportingMode::FullRuntimeAbort:
- OS << "<rt-abort>";
+ OS << "<rt-abort";
break;
}
+ if (Options.Merge)
+ OS << ";merge";
+ OS << ">";
}
diff --git a/llvm/test/Instrumentation/BoundsChecking/runtimes.ll b/llvm/test/Instrumentation/BoundsChecking/runtimes.ll
index 8726606665d7ca..7b95a4092af77e 100644
--- a/llvm/test/Instrumentation/BoundsChecking/runtimes.ll
+++ b/llvm/test/Instrumentation/BoundsChecking/runtimes.ll
@@ -1,25 +1,13 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt < %s -passes=bounds-checking -S | FileCheck %s --check-prefixes=TR
-; RUN: opt < %s -passes='bounds-checking<trap>' -S | FileCheck %s --check-prefixes=TR
-; RUN: opt < %s -passes='bounds-checking<rt>' -S | FileCheck %s --check-prefixes=RT
-; RUN: opt < %s -passes='bounds-checking<rt-abort>' -S | FileCheck %s --check-prefixes=RTABORT
-; RUN: opt < %s -passes='bounds-checking<min-rt>' -S | FileCheck %s --check-prefixes=MINRT
-; RUN: opt < %s -passes='bounds-checking<min-rt-abort>' -S | FileCheck %s --check-prefixes=MINRTABORT
+; RUN: opt < %s -passes=bounds-checking -S | FileCheck %s --check-prefixes=TR-NOMERGE
+; RUN: opt < %s -passes='bounds-checking<trap>' -S | FileCheck %s --check-prefixes=TR-NOMERGE
+; RUN: opt < %s -passes='bounds-checking<rt>' -S | FileCheck %s --check-prefixes=RT-NOMERGE
+; RUN: opt < %s -passes='bounds-checking<rt-abort>' -S | FileCheck %s --check-prefixes=RTABORT-NOMERGE
+; RUN: opt < %s -passes='bounds-checking<min-rt>' -S | FileCheck %s --check-prefixes=MINRT-NOMERGE
+; RUN: opt < %s -passes='bounds-checking<min-rt-abort>' -S | FileCheck %s --check-prefixes=MINRTABORT-NOMERGE
;
-; merge defaults to true
-; RUN: opt < %s -passes='bounds-checking<merge=true>' -S | FileCheck %s --check-prefixes=TR
-; RUN: opt < %s -passes='bounds-checking<trap;merge=true>' -S | FileCheck %s --check-prefixes=TR
-; RUN: opt < %s -passes='bounds-checking<rt;merge=true>' -S | FileCheck %s --check-prefixes=RT
-; RUN: opt < %s -passes='bounds-checking<rt-abort;merge=true>' -S | FileCheck %s --check-prefixes=RTABORT
-; RUN: opt < %s -passes='bounds-checking<min-rt;merge=true>' -S | FileCheck %s --check-prefixes=MINRT
-; RUN: opt < %s -passes='bounds-checking<min-rt-abort;merge=true>' -S | FileCheck %s --check-prefixes=MINRTABORT
-;
-; RUN: opt < %s -passes='bounds-checking<merge=false>' -S | FileCheck %s --check-prefixes=TR-NOMERGE
-; RUN: opt < %s -passes='bounds-checking<trap;merge=false>' -S | FileCheck %s --check-prefixes=TR-NOMERGE
-; RUN: opt < %s -passes='bounds-checking<rt;merge=false>' -S | FileCheck %s --check-prefixes=RT-NOMERGE
-; RUN: opt < %s -passes='bounds-checking<rt-abort;merge=false>' -S | FileCheck %s --check-prefixes=RTABORT-NOMERGE
-; RUN: opt < %s -passes='bounds-checking<min-rt;merge=false>' -S | FileCheck %s --check-prefixes=MINRT-NOMERGE
-; RUN: opt < %s -passes='bounds-checking<min-rt-abort;merge=false>' -S | FileCheck %s --check-prefixes=MINRTABORT-NOMERGE
+; RUN: opt < %s -passes='bounds-checking<trap;merge>' -S | FileCheck %s --check-prefixes=TR
+; RUN: opt < %s -passes='bounds-checking<rt;merge>' -S | FileCheck %s --check-prefixes=RT
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
@@ -56,54 +44,6 @@ define void @f1(i64 %x) nounwind {
; RT-NEXT: call void @__ubsan_handle_local_out_of_bounds() #[[ATTR0]]
; RT-NEXT: br label %[[BB7]]
;
-; RTABORT-LABEL: define void @f1(
-; RTABORT-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
-; RTABORT-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]]
-; RTABORT-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8
-; RTABORT-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0
-; RTABORT-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16
-; RTABORT-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]]
-; RTABORT-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]]
-; RTABORT-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]]
-; RTABORT: [[BB7]]:
-; RTABORT-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
-; RTABORT-NEXT: ret void
-; RTABORT: [[TRAP]]:
-; RTABORT-NEXT: call void @__ubsan_handle_local_out_of_bounds_abort() #[[ATTR1:[0-9]+]]
-; RTABORT-NEXT: unreachable
-;
-; MINRT-LABEL: define void @f1(
-; MINRT-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
-; MINRT-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]]
-; MINRT-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8
-; MINRT-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0
-; MINRT-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16
-; MINRT-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]]
-; MINRT-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]]
-; MINRT-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]]
-; MINRT: [[BB7]]:
-; MINRT-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
-; MINRT-NEXT: ret void
-; MINRT: [[TRAP]]:
-; MINRT-NEXT: call void @__ubsan_handle_local_out_of_bounds_minimal() #[[ATTR0]]
-; MINRT-NEXT: br label %[[BB7]]
-;
-; MINRTABORT-LABEL: define void @f1(
-; MINRTABORT-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
-; MINRTABORT-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]]
-; MINRTABORT-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8
-; MINRTABORT-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0
-; MINRTABORT-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16
-; MINRTABORT-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]]
-; MINRTABORT-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]]
-; MINRTABORT-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]]
-; MINRTABORT: [[BB7]]:
-; MINRTABORT-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
-; MINRTABORT-NEXT: ret void
-; MINRTABORT: [[TRAP]]:
-; MINRTABORT-NEXT: call void @__ubsan_handle_local_out_of_bounds_minimal_abort() #[[ATTR1:[0-9]+]]
-; MINRTABORT-NEXT: unreachable
-;
; TR-NOMERGE-LABEL: define void @f1(
; TR-NOMERGE-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
; TR-NOMERGE-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]]
@@ -189,14 +129,11 @@ define void @f1(i64 %x) nounwind {
ret void
}
-; TR: attributes #[[ATTR2]] = { noreturn nounwind }
-; RT: attributes #[[ATTR0]] = { nounwind }
-; RTABORT: attributes #[[ATTR1]] = { noreturn nounwind }
-; MINRT: attributes #[[ATTR0]] = { nounwind }
-; MINRTABORT: attributes #[[ATTR1]] = { noreturn nounwind }
-
; TR-NOMERGE: attributes #[[ATTR2]] = { nomerge noreturn nounwind }
; RT-NOMERGE: attributes #[[ATTR1]] = { nomerge nounwind }
; RTABORT-NOMERGE: attributes #[[ATTR2]] = { nomerge noreturn nounwind }
; MINRT-NOMERGE: attributes #[[ATTR1]] = { nomerge nounwind }
; MINRTABORT-NOMERGE: attributes #[[ATTR2]] = { nomerge noreturn nounwind }
+;
+; TR: attributes #[[ATTR2]] = { noreturn nounwind }
+; RT: attributes #[[ATTR0]] = { nounwind }
>From 5af3938dbe6b6df3a64af6dda1b61a7d954d5b99 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Fri, 20 Dec 2024 05:53:10 +0000
Subject: [PATCH 4/4] Update tests to add merge flag
---
llvm/test/Instrumentation/BoundsChecking/many-trap.ll | 4 ++--
llvm/test/Instrumentation/BoundsChecking/simple-32.ll | 2 +-
llvm/test/Instrumentation/BoundsChecking/simple.ll | 2 +-
.../Instrumentation/BoundsChecking/ubsan-unique-traps.ll | 5 ++---
4 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/llvm/test/Instrumentation/BoundsChecking/many-trap.ll b/llvm/test/Instrumentation/BoundsChecking/many-trap.ll
index e9cde95cd09e59..4e157520dbafe3 100644
--- a/llvm/test/Instrumentation/BoundsChecking/many-trap.ll
+++ b/llvm/test/Instrumentation/BoundsChecking/many-trap.ll
@@ -1,5 +1,5 @@
-; RUN: opt < %s -passes=bounds-checking -S | FileCheck %s
-; RUN: opt < %s -passes=bounds-checking -bounds-checking-single-trap -S | FileCheck -check-prefix=SINGLE %s
+; RUN: opt < %s -passes='bounds-checking<merge>' -S | FileCheck %s
+; RUN: opt < %s -passes='bounds-checking<merge>' -bounds-checking-single-trap -S | FileCheck -check-prefix=SINGLE %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
; CHECK: @f1
diff --git a/llvm/test/Instrumentation/BoundsChecking/simple-32.ll b/llvm/test/Instrumentation/BoundsChecking/simple-32.ll
index b707adaca434ca..6f8d373d4c5966 100644
--- a/llvm/test/Instrumentation/BoundsChecking/simple-32.ll
+++ b/llvm/test/Instrumentation/BoundsChecking/simple-32.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -passes=bounds-checking -S | FileCheck %s
+; RUN: opt < %s -passes='bounds-checking<merge>' -S | FileCheck %s
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
diff --git a/llvm/test/Instrumentation/BoundsChecking/simple.ll b/llvm/test/Instrumentation/BoundsChecking/simple.ll
index 914cafdc57f9d3..ce2540cf49cccc 100644
--- a/llvm/test/Instrumentation/BoundsChecking/simple.ll
+++ b/llvm/test/Instrumentation/BoundsChecking/simple.ll
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes=bounds-checking -S | FileCheck %s
+; RUN: opt < %s -passes='bounds-checking<merge>' -S | FileCheck %s
target datalayout = "e-p:64:64:64-p1:16:16:16-p2:64:64:64:48-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
@.str = private constant [8 x i8] c"abcdefg\00"
diff --git a/llvm/test/Instrumentation/BoundsChecking/ubsan-unique-traps.ll b/llvm/test/Instrumentation/BoundsChecking/ubsan-unique-traps.ll
index a79db52905e824..5fdb9c78357e73 100644
--- a/llvm/test/Instrumentation/BoundsChecking/ubsan-unique-traps.ll
+++ b/llvm/test/Instrumentation/BoundsChecking/ubsan-unique-traps.ll
@@ -1,7 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes='bounds-checking<merge=false>' -S | FileCheck %s
-; RUN: opt < %s -passes='bounds-checking<merge=true>' -S | not FileCheck %s
-; RUN: opt < %s -passes=bounds-checking -S | not FileCheck %s
+; RUN: opt < %s -passes=bounds-checking -S | FileCheck %s
+; RUN: opt < %s -passes='bounds-checking<merge>' -S | not FileCheck %s
target datalayout = "e-p:64:64:64-p1:16:16:16-p2:64:64:64:48-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
More information about the llvm-commits
mailing list