Skip to content

[OptBisect][IR] Adding a new OptPassGate for disabling passes via name #145059

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jul 16, 2025
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ab60634
Adding -opt-disable and a test for it
cristianassaiante Jun 20, 2025
aea7b99
Merge branch 'llvm:main' into opt-disable
cristianassaiante Jun 20, 2025
5e79702
Partial solve of review comments
cristianassaiante Jun 23, 2025
8862507
Fix vector usage
cristianassaiante Jun 23, 2025
9f95327
Remove leftovers
cristianassaiante Jun 23, 2025
56405f2
Converted to cl::list, renamed verbose flag, cleanup
cristianassaiante Jun 27, 2025
ed3dd9f
Merge branch 'main' into opt-disable
cristianassaiante Jul 1, 2025
731bcdf
Fixes, new test using opt in llvm/test
cristianassaiante Jul 2, 2025
12bb09c
Added test description
cristianassaiante Jul 2, 2025
6cc429b
Removing leftovers, solving nits
cristianassaiante Jul 3, 2025
825b711
Update llvm/lib/IR/OptBisect.cpp
cristianassaiante Jul 9, 2025
284a13f
Short names with both NPM and Legacy, updated test, solved nits
cristianassaiante Jul 10, 2025
39b85f1
Update failing opt-bisect test
cristianassaiante Jul 10, 2025
3b766f2
Apply suggestions from code review
cristianassaiante Jul 10, 2025
2cb80ea
Removing virtual, cleaning format
cristianassaiante Jul 10, 2025
0f13dab
Format check fail leftover
cristianassaiante Jul 10, 2025
9b696eb
Full case sensitivity, leftover this
cristianassaiante Jul 11, 2025
8282416
Merge branch 'main' into opt-disable
cristianassaiante Jul 11, 2025
098431a
Update llvm/include/llvm/Pass.h
cristianassaiante Jul 16, 2025
3774261
Merge branch 'main' into opt-disable
cristianassaiante Jul 16, 2025
08341fd
Format check fix
cristianassaiante Jul 16, 2025
82ffe52
Update clang bisect test with new output format
cristianassaiante Jul 16, 2025
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
2 changes: 1 addition & 1 deletion clang/test/CodeGen/new-pass-manager-opt-bisect.c
Original file line number Diff line number Diff line change
@@ -7,6 +7,6 @@
// CHECK: BISECT: running pass (1)
// CHECK-NOT: BISECT: running pass (1)
// Make sure that legacy pass manager is running
// CHECK: Instruction Selection
// CHECK: -isel

int func(int a) { return a; }
35 changes: 33 additions & 2 deletions llvm/include/llvm/IR/OptBisect.h
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
#define LLVM_IR_OPTBISECT_H

#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Compiler.h"
#include <limits>

@@ -82,8 +83,38 @@ class LLVM_ABI OptBisect : public OptPassGate {
mutable int LastBisectNum = 0;
};

/// Singleton instance of the OptBisect class, so multiple pass managers don't
/// need to coordinate their uses of OptBisect.
/// This class implements a mechanism to disable passes and individual
/// optimizations at compile time based on a command line option
/// (-opt-disable) in order to study how single transformations, or
/// combinations thereof, affect the IR.
class LLVM_ABI OptDisable : public OptPassGate {
public:
/// Checks the pass name to determine if the specified pass should run.
///
/// It returns true if the pass should run, i.e. if its name is was
/// not provided via command line.
/// If -opt-disable-enable-verbosity is given, the method prints the
/// name of the pass, and whether or not the pass will be executed.
///
/// Most passes should not call this routine directly. Instead, it is called
/// through helper routines provided by the base classes of the pass. For
/// instance, function passes should call FunctionPass::skipFunction().
bool shouldRunPass(StringRef PassName,
StringRef IRDescription) const override;

/// Parses the command line argument to extract the names of the passes
/// to be disabled. Multiple pass names can be provided with comma separation.
void setDisabled(StringRef Pass);

/// isEnabled() should return true before calling shouldRunPass().
bool isEnabled() const override { return !DisabledPasses.empty(); }

private:
StringSet<> DisabledPasses = {};
};

/// Singleton instance of the OptPassGate class, so multiple pass managers don't
/// need to coordinate their uses of OptBisect and OptDisable.
LLVM_ABI OptPassGate &getGlobalPassGate();

} // end namespace llvm
4 changes: 4 additions & 0 deletions llvm/include/llvm/Pass.h
Original file line number Diff line number Diff line change
@@ -114,6 +114,10 @@ class LLVM_ABI Pass {
/// Registration templates, but can be overloaded directly.
virtual StringRef getPassName() const;

/// Return a nice clean name for a pass
/// corresponding to that used to enable the pass in opt.
StringRef getPassArgument() const;

/// getPassID - Return the PassID number that corresponds to this pass.
AnalysisID getPassID() const {
return PassID;
42 changes: 41 additions & 1 deletion llvm/lib/IR/OptBisect.cpp
Original file line number Diff line number Diff line change
@@ -25,6 +25,11 @@ static OptBisect &getOptBisector() {
return OptBisector;
}

static OptDisable &getOptDisabler() {
static OptDisable OptDisabler;
return OptDisabler;
}

static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
cl::init(OptBisect::Disabled), cl::Optional,
cl::cb<void, int>([](int Limit) {
@@ -37,6 +42,18 @@ static cl::opt<bool> OptBisectVerbose(
cl::desc("Show verbose output when opt-bisect-limit is set"), cl::Hidden,
cl::init(true), cl::Optional);

static cl::list<std::string> OptDisablePasses(
"opt-disable", cl::Hidden, cl::CommaSeparated, cl::Optional,
cl::cb<void, std::string>([](const std::string &Pass) {
getOptDisabler().setDisabled(Pass);
}),
cl::desc("Optimization pass(es) to disable (comma-separated list)"));

static cl::opt<bool>
OptDisableVerbose("opt-disable-enable-verbosity",
cl::desc("Show verbose output when opt-disable is set"),
cl::Hidden, cl::init(false), cl::Optional);

static void printPassMessage(StringRef Name, int PassNum, StringRef TargetDesc,
bool Running) {
StringRef Status = Running ? "" : "NOT ";
@@ -55,4 +72,27 @@ bool OptBisect::shouldRunPass(StringRef PassName,
return ShouldRun;
}

OptPassGate &llvm::getGlobalPassGate() { return getOptBisector(); }
static void printDisablePassMessage(const StringRef &Name, StringRef TargetDesc,
bool Running) {
StringRef Status = Running ? "" : "NOT ";
dbgs() << "OptDisable: " << Status << "running pass " << Name << " on "
<< TargetDesc << "\n";
}

void OptDisable::setDisabled(StringRef Pass) { DisabledPasses.insert(Pass); }

bool OptDisable::shouldRunPass(StringRef PassName,
StringRef IRDescription) const {
assert(isEnabled());

const bool ShouldRun = !DisabledPasses.contains(PassName);
if (OptDisableVerbose)
printDisablePassMessage(PassName, IRDescription, ShouldRun);
return ShouldRun;
}

OptPassGate &llvm::getGlobalPassGate() {
if (getOptDisabler().isEnabled())
return getOptDisabler();
return getOptBisector();
}
26 changes: 22 additions & 4 deletions llvm/lib/IR/Pass.cpp
Original file line number Diff line number Diff line change
@@ -62,8 +62,12 @@ static std::string getDescription(const Module &M) {

bool ModulePass::skipModule(const Module &M) const {
const OptPassGate &Gate = M.getContext().getOptPassGate();
return Gate.isEnabled() &&
!Gate.shouldRunPass(this->getPassName(), getDescription(M));

StringRef PassName = getPassArgument();
if (PassName.empty())
PassName = this->getPassName();

return Gate.isEnabled() && !Gate.shouldRunPass(PassName, getDescription(M));
}

bool Pass::mustPreserveAnalysisID(char &AID) const {
@@ -86,6 +90,16 @@ StringRef Pass::getPassName() const {
return "Unnamed pass: implement Pass::getPassName()";
}

/// getPassArgument - Return a nice clean name for a pass
/// corresponding to that used to enable the pass in opt
StringRef Pass::getPassArgument() const {
AnalysisID AID = getPassID();
const PassInfo *PI = Pass::lookupPassInfo(AID);
if (PI)
return PI->getPassArgument();
return "";
}

void Pass::preparePassManager(PMStack &) {
// By default, don't do anything.
}
@@ -173,8 +187,12 @@ static std::string getDescription(const Function &F) {

bool FunctionPass::skipFunction(const Function &F) const {
OptPassGate &Gate = F.getContext().getOptPassGate();
if (Gate.isEnabled() &&
!Gate.shouldRunPass(this->getPassName(), getDescription(F)))

StringRef PassName = getPassArgument();
if (PassName.empty())
PassName = this->getPassName();

if (Gate.isEnabled() && !Gate.shouldRunPass(PassName, getDescription(F)))
return true;

if (F.hasOptNone()) {
10 changes: 7 additions & 3 deletions llvm/lib/Passes/StandardInstrumentations.cpp
Original file line number Diff line number Diff line change
@@ -1078,9 +1078,13 @@ void OptPassGateInstrumentation::registerCallbacks(
if (!PassGate.isEnabled())
return;

PIC.registerShouldRunOptionalPassCallback([this](StringRef PassName, Any IR) {
return this->shouldRun(PassName, IR);
});
PIC.registerShouldRunOptionalPassCallback(
[this, &PIC](StringRef ClassName, Any IR) {
StringRef PassName = PIC.getPassNameForClassName(ClassName);
if (PassName.empty())
return this->shouldRun(ClassName, IR);
return this->shouldRun(PassName, IR);
});
}

raw_ostream &PrintPassInstrumentation::print() {
76 changes: 38 additions & 38 deletions llvm/test/Other/opt-bisect-new-pass-manager.ll
Original file line number Diff line number Diff line change
@@ -11,84 +11,84 @@
; RUN: opt -disable-output -disable-verify \
; RUN: -passes=inferattrs -opt-bisect-limit=-1 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-MODULE-PASS
; CHECK-MODULE-PASS: BISECT: running pass (1) InferFunctionAttrsPass on [module]
; CHECK-MODULE-PASS: BISECT: running pass (1) inferattrs on [module]

; RUN: opt -disable-output -disable-verify \
; RUN: -passes=inferattrs -opt-bisect-limit=0 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-LIMIT-MODULE-PASS
; CHECK-LIMIT-MODULE-PASS: BISECT: NOT running pass (1) InferFunctionAttrsPass on [module]
; CHECK-LIMIT-MODULE-PASS: BISECT: NOT running pass (1) inferattrs on [module]

; RUN: opt -disable-output -debug-pass-manager \
; RUN: -passes=inferattrs -opt-bisect-limit=-1 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-REQUIRED-PASS
; CHECK-REQUIRED-PASS: BISECT: running pass (1) InferFunctionAttrsPass on [module]
; CHECK-REQUIRED-PASS: BISECT: running pass (1) inferattrs on [module]
; CHECK-REQUIRED-PASS-NOT: BISECT: {{.*}}VerifierPass
; CHECK-REQUIRED-PASS: Running pass: VerifierPass

; RUN: opt -disable-output -debug-pass-manager \
; RUN: -passes=inferattrs -opt-bisect-limit=0 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-LIMIT-REQUIRED-PASS
; CHECK-LIMIT-REQUIRED-PASS: BISECT: NOT running pass (1) InferFunctionAttrsPass on [module]
; CHECK-LIMIT-REQUIRED-PASS: BISECT: NOT running pass (1) inferattrs on [module]
; CHECK-LIMIT-REQUIRED-PASS-NOT: BISECT: {{.*}}VerifierPass
; CHECK-LIMIT-REQUIRED-PASS: Running pass: VerifierPass

; RUN: opt -disable-output -disable-verify \
; RUN: -passes=early-cse -opt-bisect-limit=-1 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-PASS
; CHECK-FUNCTION-PASS: BISECT: running pass (1) EarlyCSEPass on f1
; CHECK-FUNCTION-PASS: BISECT: running pass (2) EarlyCSEPass on f2
; CHECK-FUNCTION-PASS: BISECT: running pass (3) EarlyCSEPass on f3
; CHECK-FUNCTION-PASS: BISECT: running pass (4) EarlyCSEPass on f4
; CHECK-FUNCTION-PASS: BISECT: running pass (1) early-cse on f1
; CHECK-FUNCTION-PASS: BISECT: running pass (2) early-cse on f2
; CHECK-FUNCTION-PASS: BISECT: running pass (3) early-cse on f3
; CHECK-FUNCTION-PASS: BISECT: running pass (4) early-cse on f4

; RUN: opt -disable-output -disable-verify \
; RUN: -passes=early-cse -opt-bisect-limit=2 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-LIMIT-FUNCTION-PASS
; CHECK-LIMIT-FUNCTION-PASS: BISECT: running pass (1) EarlyCSEPass on f1
; CHECK-LIMIT-FUNCTION-PASS: BISECT: running pass (2) EarlyCSEPass on f2
; CHECK-LIMIT-FUNCTION-PASS: BISECT: NOT running pass (3) EarlyCSEPass on f3
; CHECK-LIMIT-FUNCTION-PASS: BISECT: NOT running pass (4) EarlyCSEPass on f4
; CHECK-LIMIT-FUNCTION-PASS: BISECT: running pass (1) early-cse on f1
; CHECK-LIMIT-FUNCTION-PASS: BISECT: running pass (2) early-cse on f2
; CHECK-LIMIT-FUNCTION-PASS: BISECT: NOT running pass (3) early-cse on f3
; CHECK-LIMIT-FUNCTION-PASS: BISECT: NOT running pass (4) early-cse on f4

; RUN: opt -disable-output -disable-verify \
; RUN: -passes=function-attrs -opt-bisect-limit=-1 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-CGSCC-PASS
; CHECK-CGSCC-PASS: BISECT: running pass (1) PostOrderFunctionAttrsPass on (f1)
; CHECK-CGSCC-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on (f2)
; CHECK-CGSCC-PASS: BISECT: running pass (3) PostOrderFunctionAttrsPass on (f3)
; CHECK-CGSCC-PASS: BISECT: running pass (4) PostOrderFunctionAttrsPass on (f4)
; CHECK-CGSCC-PASS: BISECT: running pass (1) function-attrs on (f1)
; CHECK-CGSCC-PASS: BISECT: running pass (2) function-attrs on (f2)
; CHECK-CGSCC-PASS: BISECT: running pass (3) function-attrs on (f3)
; CHECK-CGSCC-PASS: BISECT: running pass (4) function-attrs on (f4)

; RUN: opt -disable-output -disable-verify \
; RUN: -passes=function-attrs -opt-bisect-limit=3 %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-LIMIT-CGSCC-PASS
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (1) PostOrderFunctionAttrsPass on (f1)
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on (f2)
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (3) PostOrderFunctionAttrsPass on (f3)
; CHECK-LIMIT-CGSCC-PASS: BISECT: NOT running pass (4) PostOrderFunctionAttrsPass on (f4)
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (1) function-attrs on (f1)
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (2) function-attrs on (f2)
; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (3) function-attrs on (f3)
; CHECK-LIMIT-CGSCC-PASS: BISECT: NOT running pass (4) function-attrs on (f4)

; RUN: opt -disable-output -disable-verify -opt-bisect-limit=-1 \
; RUN: -passes='inferattrs,cgscc(function-attrs,function(early-cse))' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-MULTI-PASS
; CHECK-MULTI-PASS: BISECT: running pass (1) InferFunctionAttrsPass on [module]
; CHECK-MULTI-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on (f1)
; CHECK-MULTI-PASS: BISECT: running pass (3) EarlyCSEPass on f1
; CHECK-MULTI-PASS: BISECT: running pass (4) PostOrderFunctionAttrsPass on (f2)
; CHECK-MULTI-PASS: BISECT: running pass (5) EarlyCSEPass on f2
; CHECK-MULTI-PASS: BISECT: running pass (6) PostOrderFunctionAttrsPass on (f3)
; CHECK-MULTI-PASS: BISECT: running pass (7) EarlyCSEPass on f3
; CHECK-MULTI-PASS: BISECT: running pass (8) PostOrderFunctionAttrsPass on (f4)
; CHECK-MULTI-PASS: BISECT: running pass (9) EarlyCSEPass on f4
; CHECK-MULTI-PASS: BISECT: running pass (1) inferattrs on [module]
; CHECK-MULTI-PASS: BISECT: running pass (2) function-attrs on (f1)
; CHECK-MULTI-PASS: BISECT: running pass (3) early-cse on f1
; CHECK-MULTI-PASS: BISECT: running pass (4) function-attrs on (f2)
; CHECK-MULTI-PASS: BISECT: running pass (5) early-cse on f2
; CHECK-MULTI-PASS: BISECT: running pass (6) function-attrs on (f3)
; CHECK-MULTI-PASS: BISECT: running pass (7) early-cse on f3
; CHECK-MULTI-PASS: BISECT: running pass (8) function-attrs on (f4)
; CHECK-MULTI-PASS: BISECT: running pass (9) early-cse on f4

; RUN: opt -disable-output -disable-verify -opt-bisect-limit=7 \
; RUN: -passes='inferattrs,cgscc(function-attrs,function(early-cse))' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-LIMIT-MULTI-PASS
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (1) InferFunctionAttrsPass on [module]
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on (f1)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (3) EarlyCSEPass on f1
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (4) PostOrderFunctionAttrsPass on (f2)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (5) EarlyCSEPass on f2
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (6) PostOrderFunctionAttrsPass on (f3)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (7) EarlyCSEPass on f3
; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (8) PostOrderFunctionAttrsPass on (f4)
; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (9) EarlyCSEPass on f4
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (1) inferattrs on [module]
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (2) function-attrs on (f1)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (3) early-cse on f1
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (4) function-attrs on (f2)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (5) early-cse on f2
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (6) function-attrs on (f3)
; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (7) early-cse on f3
; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (8) function-attrs on (f4)
; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (9) early-cse on f4

; Make sure we don't skip writing the output to stdout.
; RUN: opt %s -opt-bisect-limit=0 -passes=early-cse | opt -S | FileCheck %s -check-prefix=CHECK-OUTPUT
91 changes: 91 additions & 0 deletions llvm/test/Other/opt-disable.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
; This test uses the same IR functions of the opt-bisect test
; but it checks the correctness of the -opt-disable flag.
; -opt-disable-enable-verbosity is required to have output.

; RUN: opt -disable-output -disable-verify \
; RUN: -opt-disable-enable-verbosity \
; RUN: -passes=inferattrs -opt-disable=inferattrs %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-MODULE-PASS
; CHECK-MODULE-PASS: OptDisable: NOT running pass inferattrs on [module]

; RUN: opt -disable-output -disable-verify \
; RUN: -opt-disable-enable-verbosity \
; RUN: -passes=sroa -opt-disable=sroa %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-PASS
; CHECK-FUNCTION-PASS: OptDisable: NOT running pass sroa on f1
; CHECK-FUNCTION-PASS: OptDisable: NOT running pass sroa on f2
; CHECK-FUNCTION-PASS: OptDisable: NOT running pass sroa on f3
; CHECK-FUNCTION-PASS: OptDisable: NOT running pass sroa on f4

; RUN: opt -disable-output -disable-verify \
; RUN: -opt-disable=inferattrs,function-attrs \
; RUN: -opt-disable-enable-verbosity \
; RUN: -passes='inferattrs,cgscc(function-attrs,function(early-cse))' %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-MULTI-PASS
; CHECK-MULTI-PASS: OptDisable: NOT running pass inferattrs on [module]
; CHECK-MULTI-PASS: OptDisable: NOT running pass function-attrs on (f1)
; CHECK-MULTI-PASS: OptDisable: running pass early-cse on f1
; CHECK-MULTI-PASS: OptDisable: NOT running pass function-attrs on (f2)
; CHECK-MULTI-PASS: OptDisable: running pass early-cse on f2
; CHECK-MULTI-PASS: OptDisable: NOT running pass function-attrs on (f3)
; CHECK-MULTI-PASS: OptDisable: running pass early-cse on f3
; CHECK-MULTI-PASS: OptDisable: NOT running pass function-attrs on (f4)
; CHECK-MULTI-PASS: OptDisable: running pass early-cse on f4

declare i32 @g()

define void @f1(i1 %arg) {
entry:
br label %loop.0
loop.0:
br i1 %arg, label %loop.0.0, label %loop.1
loop.0.0:
br i1 %arg, label %loop.0.0, label %loop.0.1
loop.0.1:
br i1 %arg, label %loop.0.1, label %loop.0
loop.1:
br i1 %arg, label %loop.1, label %loop.1.bb1
loop.1.bb1:
br i1 %arg, label %loop.1, label %loop.1.bb2
loop.1.bb2:
br i1 %arg, label %end, label %loop.1.0
loop.1.0:
br i1 %arg, label %loop.1.0, label %loop.1
end:
ret void
}

define i32 @f2() {
entry:
ret i32 0
}

define i32 @f3() {
entry:
%temp = call i32 @g()
%icmp = icmp ugt i32 %temp, 2
br i1 %icmp, label %bb.true, label %bb.false
bb.true:
%temp2 = call i32 @f2()
ret i32 %temp2
bb.false:
ret i32 0
}

define void @f4(i1 %arg) {
entry:
%i = alloca i32, align 4
call void @llvm.lifetime.start(i64 4, ptr %i)
br label %for.cond

for.cond:
br i1 %arg, label %for.body, label %for.end

for.body:
br label %for.cond

for.end:
ret void
}

declare void @llvm.lifetime.start(i64, ptr nocapture)