Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions llvm/include/llvm/IR/MDBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ class MDBuilder {
/// Return metadata containing two branch weights.
MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight);

/// Return metadata containing two branch weights, with significant bias
/// towards `true` destination.
MDNode *createLikelyBranchWeights();

/// Return metadata containing two branch weights, with significant bias
/// towards `false` destination.
MDNode *createUnlikelyBranchWeights();

/// Return metadata containing a number of branch weights.
MDNode *createBranchWeights(ArrayRef<uint32_t> Weights);

Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/IR/MDBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ MDNode *MDBuilder::createBranchWeights(uint32_t TrueWeight,
return createBranchWeights({TrueWeight, FalseWeight});
}

MDNode *MDBuilder::createLikelyBranchWeights() {
// Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp
return createBranchWeights((1U << 20) - 1, 1);
}

MDNode *MDBuilder::createUnlikelyBranchWeights() {
// Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp
return createBranchWeights(1, (1U << 20) - 1);
}

MDNode *MDBuilder::createBranchWeights(ArrayRef<uint32_t> Weights) {
assert(Weights.size() >= 1 && "Need at least one branch weights!");

Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Transforms/IPO/CrossDSOCFI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,7 @@ void CrossDSOCFI::buildCFICheck(Module &M) {
}

bool CrossDSOCFI::runOnModule(Module &M) {
VeryLikelyWeights =
MDBuilder(M.getContext()).createBranchWeights((1U << 20) - 1, 1);
VeryLikelyWeights = MDBuilder(M.getContext()).createLikelyBranchWeights();
if (M.getModuleFlag("Cross-DSO CFI") == nullptr)
return false;
buildCFICheck(M);
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1196,8 +1196,7 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
// function pointer to the devirtualized target. In case of a mismatch,
// fall back to indirect call.
if (DevirtCheckMode == WPDCheckMode::Fallback) {
MDNode *Weights =
MDBuilder(M.getContext()).createBranchWeights((1U << 20) - 1, 1);
MDNode *Weights = MDBuilder(M.getContext()).createLikelyBranchWeights();
// Version the indirect call site. If the called value is equal to the
// given callee, 'NewInst' will be executed, otherwise the original call
// site will be executed.
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1817,7 +1817,7 @@ Instruction *AddressSanitizer::genAMDGPUReportBlock(IRBuilder<> &IRB,

auto *Trm =
SplitBlockAndInsertIfThen(ReportCond, &*IRB.GetInsertPoint(), false,
MDBuilder(*C).createBranchWeights(1, 100000));
MDBuilder(*C).createUnlikelyBranchWeights());
Trm->getParent()->setName("asan.report");

if (Recover)
Expand Down Expand Up @@ -1894,7 +1894,7 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
// We use branch weights for the slow path check, to indicate that the slow
// path is rarely taken. This seems to be the case for SPEC benchmarks.
Instruction *CheckTerm = SplitBlockAndInsertIfThen(
Cmp, InsertBefore, false, MDBuilder(*C).createBranchWeights(1, 100000));
Cmp, InsertBefore, false, MDBuilder(*C).createUnlikelyBranchWeights());
assert(cast<BranchInst>(CheckTerm)->isUnconditional());
BasicBlock *NextBB = CheckTerm->getSuccessor(0);
IRB.SetInsertPoint(CheckTerm);
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1229,8 +1229,8 @@ bool DataFlowSanitizer::initializeModule(Module &M) {
FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
/*isVarArg=*/false);

ColdCallWeights = MDBuilder(*Ctx).createBranchWeights(1, 1000);
OriginStoreWeights = MDBuilder(*Ctx).createBranchWeights(1, 1000);
ColdCallWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
OriginStoreWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
return true;
}

Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ HWAddressSanitizer::insertShadowTagCheck(Value *Ptr, Instruction *InsertBefore,

R.TagMismatchTerm = SplitBlockAndInsertIfThen(
TagMismatch, InsertBefore, false,
MDBuilder(*C).createBranchWeights(1, 100000), &DTU, LI);
MDBuilder(*C).createUnlikelyBranchWeights(), &DTU, LI);

return R;
}
Expand Down Expand Up @@ -952,15 +952,15 @@ void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite,
IRB.CreateICmpUGT(TCI.MemTag, ConstantInt::get(Int8Ty, 15));
Instruction *CheckFailTerm = SplitBlockAndInsertIfThen(
OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
MDBuilder(*C).createBranchWeights(1, 100000), &DTU, LI);
MDBuilder(*C).createUnlikelyBranchWeights(), &DTU, LI);

IRB.SetInsertPoint(TCI.TagMismatchTerm);
Value *PtrLowBits = IRB.CreateTrunc(IRB.CreateAnd(TCI.PtrLong, 15), Int8Ty);
PtrLowBits = IRB.CreateAdd(
PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
Value *PtrLowBitsOOB = IRB.CreateICmpUGE(PtrLowBits, TCI.MemTag);
SplitBlockAndInsertIfThen(PtrLowBitsOOB, TCI.TagMismatchTerm, false,
MDBuilder(*C).createBranchWeights(1, 100000), &DTU,
MDBuilder(*C).createUnlikelyBranchWeights(), &DTU,
LI, CheckFailTerm->getParent());

IRB.SetInsertPoint(TCI.TagMismatchTerm);
Expand All @@ -969,7 +969,7 @@ void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite,
Value *InlineTag = IRB.CreateLoad(Int8Ty, InlineTagAddr);
Value *InlineTagMismatch = IRB.CreateICmpNE(TCI.PtrTag, InlineTag);
SplitBlockAndInsertIfThen(InlineTagMismatch, TCI.TagMismatchTerm, false,
MDBuilder(*C).createBranchWeights(1, 100000), &DTU,
MDBuilder(*C).createUnlikelyBranchWeights(), &DTU,
LI, CheckFailTerm->getParent());

IRB.SetInsertPoint(CheckFailTerm);
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Transforms/Instrumentation/KCFI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ PreservedAnalyses KCFIPass::run(Function &F, FunctionAnalysisManager &AM) {
"compatible with -fsanitize=kcfi on this target"));

IntegerType *Int32Ty = Type::getInt32Ty(Ctx);
MDNode *VeryUnlikelyWeights =
MDBuilder(Ctx).createBranchWeights(1, (1U << 20) - 1);
MDNode *VeryUnlikelyWeights = MDBuilder(Ctx).createUnlikelyBranchWeights();
Triple T(M.getTargetTriple());

for (CallInst *CI : KCFICalls) {
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1040,8 +1040,8 @@ void MemorySanitizer::initializeModule(Module &M) {
OriginTy = IRB.getInt32Ty();
PtrTy = IRB.getPtrTy();

ColdCallWeights = MDBuilder(*C).createBranchWeights(1, 1000);
OriginStoreWeights = MDBuilder(*C).createBranchWeights(1, 1000);
ColdCallWeights = MDBuilder(*C).createUnlikelyBranchWeights();
OriginStoreWeights = MDBuilder(*C).createUnlikelyBranchWeights();

if (!CompileKernel) {
if (TrackOrigins)
Expand Down
10 changes: 7 additions & 3 deletions llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/CommandLine.h"
Expand Down Expand Up @@ -979,8 +980,9 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
FunctionBoolArray->getValueType(), FunctionBoolArray,
{ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)});
auto Load = IRB.CreateLoad(Int1Ty, FlagPtr);
auto ThenTerm =
SplitBlockAndInsertIfThen(IRB.CreateIsNull(Load), &*IP, false);
auto ThenTerm = SplitBlockAndInsertIfThen(
IRB.CreateIsNull(Load), &*IP, false,
MDBuilder(IRB.getContext()).createUnlikelyBranchWeights());
IRBuilder<> ThenIRB(ThenTerm);
auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr);
Load->setNoSanitizeMetadata();
Expand All @@ -997,7 +999,9 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy);
auto LowestStack = IRB.CreateLoad(IntptrTy, SanCovLowestStack);
auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack);
auto ThenTerm = SplitBlockAndInsertIfThen(IsStackLower, &*IP, false);
auto ThenTerm = SplitBlockAndInsertIfThen(
IsStackLower, &*IP, false,
MDBuilder(IRB.getContext()).createUnlikelyBranchWeights());
IRBuilder<> ThenIRB(ThenTerm);
auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack);
LowestStack->setNoSanitizeMetadata();
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Instrumentation/AddressSanitizer/asan-funclet.ll
Original file line number Diff line number Diff line change
Expand Up @@ -580,5 +580,5 @@ ehcleanup: ; preds = %entry
cleanupret from %0 unwind to caller
}
;.
; CHECK-INLINE: [[PROF0]] = !{!"branch_weights", i32 1, i32 100000}
; CHECK-INLINE: [[PROF0]] = !{!"branch_weights", i32 1, i32 1048575}
;.
2 changes: 1 addition & 1 deletion llvm/test/Instrumentation/AddressSanitizer/basic.ll
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,4 @@ define void @test_swifterror_3() sanitize_address {
; CHECK: attributes #[[#ATTR]] = { nounwind }

; PROF
; CHECK: ![[PROF]] = !{!"branch_weights", i32 1, i32 100000}
; CHECK: ![[PROF]] = !{!"branch_weights", i32 1, i32 1048575}
32 changes: 20 additions & 12 deletions llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 4
; Test -sanitizer-coverage-inline-bool-flag=1
; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-inline-bool-flag=1 -S | FileCheck %s

; CHECK: $foo = comdat nodeduplicate
; CHECK: @__sancov_gen_ = private global [1 x i1] zeroinitializer, section "__sancov_bools", comdat($foo), align 1{{$}}
; CHECK: @__start___sancov_bools = extern_weak hidden global i1
; CHECK-NEXT: @__stop___sancov_bools = extern_weak hidden global i1
; CHECK: @llvm.used = appending global [1 x ptr] [ptr @sancov.module_ctor_bool_flag], section "llvm.metadata"
; CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr @__sancov_gen_], section "llvm.metadata"

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"
target triple = "x86_64-unknown-linux-gnu"
;.
; CHECK: @__sancov_lowest_stack = external thread_local(initialexec) global i64
; CHECK: @__sancov_gen_ = private global [1 x i1] zeroinitializer, section "__sancov_bools", comdat($foo), align 1
; CHECK: @__start___sancov_bools = extern_weak hidden global i1
; CHECK: @__stop___sancov_bools = extern_weak hidden global i1
; CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @sancov.module_ctor_bool_flag, ptr @sancov.module_ctor_bool_flag }]
; CHECK: @llvm.used = appending global [1 x ptr] [ptr @sancov.module_ctor_bool_flag], section "llvm.metadata"
; CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr @__sancov_gen_], section "llvm.metadata"
;.
define void @foo() {
; CHECK-LABEL: @foo(
; CHECK-LABEL: define void @foo() comdat {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i1, ptr @__sancov_gen_, align 1, !nosanitize ![[#EMPTY:]]
; CHECK-NEXT: [[TMP0:%.*]] = load i1, ptr @__sancov_gen_, align 1, !nosanitize [[META0:![0-9]+]]
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i1 [[TMP0]], false
; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]], !prof [[PROF1:![0-9]+]]
; CHECK: 2:
; CHECK-NEXT: store i1 true, ptr @__sancov_gen_, align 1, !nosanitize ![[#EMPTY:]]
; CHECK-NEXT: store i1 true, ptr @__sancov_gen_, align 1, !nosanitize [[META0]]
; CHECK-NEXT: br label [[TMP3]]
; CHECK: 3:
; CHECK-NEXT: ret void
;
entry:
ret void
}
; CHECK: call void @__sanitizer_cov_bool_flag_init(ptr @__start___sancov_bools, ptr @__stop___sancov_bools)

; CHECK: ![[#EMPTY]] = !{}
;.
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind }
;.
; CHECK: [[META0]] = !{}
; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575}
;.
94 changes: 74 additions & 20 deletions llvm/test/Instrumentation/SanitizerCoverage/stack-depth.ll
Original file line number Diff line number Diff line change
@@ -1,43 +1,97 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 4
; This check verifies that stack depth instrumentation works correctly.
; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 \
; RUN: -sanitizer-coverage-stack-depth -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 \
; RUN: -sanitizer-coverage-stack-depth -sanitizer-coverage-trace-pc-guard \
; RUN: -S | FileCheck %s
; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-stack-depth -S | FileCheck %s --check-prefixes=L1
; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=3 -sanitizer-coverage-stack-depth -S -sanitizer-coverage-trace-pc-guard | FileCheck %s --check-prefixes=L3

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; CHECK: @__sancov_lowest_stack = thread_local(initialexec) global i64 -1
@__sancov_lowest_stack = thread_local global i64 0, align 8

;.
; L1: @__sancov_lowest_stack = thread_local(initialexec) global i64 -1, align 8
;.
; L3: @__sancov_lowest_stack = thread_local(initialexec) global i64 -1, align 8
; L3: @__sancov_gen_ = private global [1 x i32] zeroinitializer, section "__sancov_guards", comdat($foo), align 4
; L3: @__sancov_gen_.1 = private global [1 x i32] zeroinitializer, section "__sancov_guards", comdat($bar), align 4
; L3: @__sancov_gen_.2 = private global [1 x i32] zeroinitializer, section "__sancov_guards", comdat($_ZTW21__sancov_lowest_stack), align 4
; L3: @__start___sancov_guards = extern_weak hidden global i32
; L3: @__stop___sancov_guards = extern_weak hidden global i32
; L3: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 2, ptr @sancov.module_ctor_trace_pc_guard, ptr @sancov.module_ctor_trace_pc_guard }]
; L3: @llvm.used = appending global [1 x ptr] [ptr @sancov.module_ctor_trace_pc_guard], section "llvm.metadata"
; L3: @llvm.compiler.used = appending global [3 x ptr] [ptr @__sancov_gen_, ptr @__sancov_gen_.1, ptr @__sancov_gen_.2], section "llvm.metadata"
;.
define i32 @foo() {
; L1-LABEL: define i32 @foo() {
; L1-NEXT: entry:
; L1-NEXT: ret i32 7
;
; L3-LABEL: define i32 @foo() comdat {
; L3-NEXT: entry:
; L3-NEXT: call void @__sanitizer_cov_trace_pc_guard(ptr @__sancov_gen_) #[[ATTR2:[0-9]+]]
; L3-NEXT: ret i32 7
;
entry:
; CHECK-LABEL: define i32 @foo
; CHECK-NOT: call ptr @llvm.frameaddress.p0(i32 0)
; CHECK-NOT: @__sancov_lowest_stack
; CHECK: ret i32 7

ret i32 7
}

define i32 @bar() {
; L1-LABEL: define i32 @bar() {
; L1-NEXT: entry:
; L1-NEXT: [[TMP0:%.*]] = call ptr @llvm.frameaddress.p0(i32 0)
; L1-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
; L1-NEXT: [[TMP2:%.*]] = load i64, ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0:![0-9]+]]
; L1-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]]
; L1-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]], !prof [[PROF1:![0-9]+]]
; L1: 4:
; L1-NEXT: store i64 [[TMP1]], ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0]]
; L1-NEXT: br label [[TMP5]]
; L1: 5:
; L1-NEXT: [[CALL:%.*]] = call i32 @foo()
; L1-NEXT: ret i32 [[CALL]]
;
; L3-LABEL: define i32 @bar() comdat {
; L3-NEXT: entry:
; L3-NEXT: call void @__sanitizer_cov_trace_pc_guard(ptr @__sancov_gen_.1) #[[ATTR2]]
; L3-NEXT: [[TMP0:%.*]] = call ptr @llvm.frameaddress.p0(i32 0)
; L3-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
; L3-NEXT: [[TMP2:%.*]] = load i64, ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0:![0-9]+]]
; L3-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]]
; L3-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]], !prof [[PROF1:![0-9]+]]
; L3: 4:
; L3-NEXT: store i64 [[TMP1]], ptr @__sancov_lowest_stack, align 8, !nosanitize [[META0]]
; L3-NEXT: br label [[TMP5]]
; L3: 5:
; L3-NEXT: [[CALL:%.*]] = call i32 @foo()
; L3-NEXT: ret i32 [[CALL]]
;
entry:
; CHECK-LABEL: define i32 @bar
; CHECK: [[framePtr:%[^ \t]+]] = call ptr @llvm.frameaddress.p0(i32 0)
; CHECK: [[frameInt:%[^ \t]+]] = ptrtoint ptr [[framePtr]] to [[intType:i[0-9]+]]
; CHECK: [[lowest:%[^ \t]+]] = load [[intType]], ptr @__sancov_lowest_stack
; CHECK: [[cmp:%[^ \t]+]] = icmp ult [[intType]] [[frameInt]], [[lowest]]
; CHECK: br i1 [[cmp]], label %[[ifLabel:[^ \t]+]], label
; CHECK: [[ifLabel]]:
; CHECK: store [[intType]] [[frameInt]], ptr @__sancov_lowest_stack
; CHECK: %call = call i32 @foo()
; CHECK: ret i32 %call

%call = call i32 @foo()
ret i32 %call
}

define weak_odr hidden ptr @_ZTW21__sancov_lowest_stack() {
; L1-LABEL: define weak_odr hidden ptr @_ZTW21__sancov_lowest_stack() {
; L1-NEXT: ret ptr @__sancov_lowest_stack
;
; L3-LABEL: define weak_odr hidden ptr @_ZTW21__sancov_lowest_stack() comdat {
; L3-NEXT: call void @__sanitizer_cov_trace_pc_guard(ptr @__sancov_gen_.2) #[[ATTR2]]
; L3-NEXT: ret ptr @__sancov_lowest_stack
;
ret ptr @__sancov_lowest_stack
}
;.
; L1: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) }
;.
; L3: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) }
; L3: attributes #[[ATTR1:[0-9]+]] = { nounwind }
; L3: attributes #[[ATTR2]] = { nomerge }
;.
; L1: [[META0]] = !{}
; L1: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575}
;.
; L3: [[META0]] = !{}
; L3: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575}
;.