Author: Thurston Dang Date: 2024-12-20T10:07:44-08:00 New Revision: 5bb650345d83669434713146aaa431c1f7ad43d6
URL: https://github.com/llvm/llvm-project/commit/5bb650345d83669434713146aaa431c1f7ad43d6 DIFF: https://github.com/llvm/llvm-project/commit/5bb650345d83669434713146aaa431c1f7ad43d6.diff LOG: Remove -bounds-checking-unique-traps (replace with -fno-sanitize-merge=local-bounds) (#120682) #120613 removed -ubsan-unique-traps and replaced it with -fno-sanitize-merge (introduced in #120511), which allows fine-grained control of which UBSan checks to prevent merging. This analogous patch removes -bound-checking-unique-traps, and allows it to be controlled via -fno-sanitize-merge=local-bounds. Most of this patch is simply plumbing through the compiler flags into the bounds checking pass. 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. Added: Modified: clang/docs/ReleaseNotes.rst clang/docs/UndefinedBehaviorSanitizer.rst clang/lib/CodeGen/BackendUtil.cpp clang/test/CodeGen/bounds-checking.c llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h llvm/lib/Passes/PassBuilder.cpp llvm/lib/Passes/PassRegistry.def llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp llvm/test/Instrumentation/BoundsChecking/many-trap.ll llvm/test/Instrumentation/BoundsChecking/runtimes.ll llvm/test/Instrumentation/BoundsChecking/simple-32.ll llvm/test/Instrumentation/BoundsChecking/simple.ll llvm/test/Instrumentation/BoundsChecking/ubsan-unique-traps.ll Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 38c35aea3cf220..d9d016b30f93d6 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -445,10 +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 control of which UBSan checks are allowed to be merged by the - backend (for example, -fno-sanitize-merge=bool,enum). - Deprecated Compiler Flags ------------------------- @@ -488,8 +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 flag '-ubsan-unique-traps' has been removed. It is - superseded by '-fno-sanitize-merge'. Attribute Changes in Clang -------------------------- @@ -1213,6 +1207,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/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst index 671db7f9f36714..b9ee4484fb9aec 100644 --- a/clang/docs/UndefinedBehaviorSanitizer.rst +++ b/clang/docs/UndefinedBehaviorSanitizer.rst @@ -276,8 +276,8 @@ Stack traces and report symbolization If you want UBSan to print symbolized stack trace for each error report, you will need to: -#. Compile with ``-g`` and ``-fno-omit-frame-pointer`` to get proper debug - information in your binary. +#. Compile with ``-g``, ``-fno-sanitize-merge`` and ``-fno-omit-frame-pointer`` + to get proper debug information in your binary. #. Run your program with environment variable ``UBSAN_OPTIONS=print_stacktrace=1``. #. Make sure ``llvm-symbolizer`` binary is in ``PATH``. diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index e6c9d77d29f6f1..04358cd6d7c232 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1030,6 +1030,9 @@ 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 +1044,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..ee71aa64f85eed 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..a936f5381137c6 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -1281,23 +1281,25 @@ 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, false); 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 == "merge") { + Options.Merge = true; } else { return make_error<StringError>( formatv("invalid BoundsChecking pass parameter '{0}' ", ParamName) @@ -1305,7 +1307,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..41e50385812460 100644 --- a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp +++ b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp @@ -37,15 +37,16 @@ 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 +106,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 +170,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 +195,8 @@ struct ReportingOpts { Name = "__ubsan_handle_local_out_of_bounds_abort"; break; } + + MayMerge = Merge; } }; @@ -253,13 +257,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 +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(Mode))) + if (!addBoundsChecking(F, TLI, SE, + ReportingOpts(Options.Mode, Options.Merge))) return PreservedAnalyses::all(); return PreservedAnalyses::none(); @@ -299,21 +303,24 @@ 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>"; + 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/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/runtimes.ll b/llvm/test/Instrumentation/BoundsChecking/runtimes.ll index 357f92aca85c08..7b95a4092af77e 100644 --- a/llvm/test/Instrumentation/BoundsChecking/runtimes.ll +++ b/llvm/test/Instrumentation/BoundsChecking/runtimes.ll @@ -1,10 +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 +; +; 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" @@ -41,55 +44,96 @@ 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 +; 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-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]] +; 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-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 +; 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-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 } 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 a3f34007e9b09f..5fdb9c78357e73 100644 --- a/llvm/test/Instrumentation/BoundsChecking/ubsan-unique-traps.ll +++ b/llvm/test/Instrumentation/BoundsChecking/ubsan-unique-traps.ll @@ -1,5 +1,7 @@ ; 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 -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" declare noalias ptr @malloc(i64) nounwind allocsize(0) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits