/** See llvm::createCFGSimplificationPass function. */
void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM);
-/** See llvm::createLateCFGSimplificationPass function. */
-void LLVMAddLateCFGSimplificationPass(LLVMPassManagerRef PM);
-
/** See llvm::createDeadStoreEliminationPass function. */
void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM);
void initializeJumpThreadingPass(PassRegistry&);
void initializeLCSSAVerificationPassPass(PassRegistry&);
void initializeLCSSAWrapperPassPass(PassRegistry&);
-void initializeLateCFGSimplifyPassPass(PassRegistry&);
void initializeLazyBlockFrequencyInfoPassPass(PassRegistry&);
void initializeLazyBranchProbabilityInfoPassPass(PassRegistry&);
void initializeLazyMachineBlockFrequencyInfoPassPass(PassRegistry&);
(void) llvm::createCallGraphDOTPrinterPass();
(void) llvm::createCallGraphViewerPass();
(void) llvm::createCFGSimplificationPass();
- (void) llvm::createLateCFGSimplificationPass();
(void) llvm::createCFLAndersAAWrapperPass();
(void) llvm::createCFLSteensAAWrapperPass();
(void) llvm::createStructurizeCFGPass();
//===----------------------------------------------------------------------===//
//
// CFGSimplification - Merge basic blocks, eliminate unreachable blocks,
-// simplify terminator instructions, etc...
+// simplify terminator instructions, convert switches to lookup tables, etc.
//
FunctionPass *createCFGSimplificationPass(
- int Threshold = -1, std::function<bool(const Function &)> Ftor = nullptr);
-
-//===----------------------------------------------------------------------===//
-//
-// LateCFGSimplification - Like CFGSimplification, but may also
-// convert switches to lookup tables.
-//
-FunctionPass *createLateCFGSimplificationPass(
- int Threshold = -1, std::function<bool(const Function &)> Ftor = nullptr);
+ unsigned Threshold = 1, bool ForwardSwitchCond = false,
+ bool ConvertSwitch = false, bool KeepLoops = true,
+ std::function<bool(const Function &)> Ftor = nullptr);
//===----------------------------------------------------------------------===//
//
SimplifyCFGOptions Options;
public:
- /// Construct a pass with default options.
- SimplifyCFGPass();
+ /// The default constructor sets the pass options to create optimal IR,
+ /// rather than canonical IR. That is, by default we do transformations that
+ /// are likely to improve performance but make analysis more difficult.
+ /// FIXME: This is inverted from what most instantiations of the pass should
+ /// be.
+ SimplifyCFGPass()
+ : SimplifyCFGPass(SimplifyCFGOptions()
+ .forwardSwitchCondToPhi(true)
+ .convertSwitchToLookupTable(true)
+ .needCanonicalLoops(false)) {}
/// Construct a pass with optional optimizations.
SimplifyCFGPass(const SimplifyCFGOptions &PassOptions);
bool NeedCanonicalLoop;
AssumptionCache *AC;
- SimplifyCFGOptions(int BonusThreshold = 1, bool ForwardSwitchCond = false,
+ SimplifyCFGOptions(unsigned BonusThreshold = 1,
+ bool ForwardSwitchCond = false,
bool SwitchToLookup = false, bool CanonicalLoops = true,
AssumptionCache *AssumpCache = nullptr)
: BonusInstThreshold(BonusThreshold),
ForwardSwitchCondToPhi(ForwardSwitchCond),
ConvertSwitchToLookupTable(SwitchToLookup),
NeedCanonicalLoop(CanonicalLoops), AC(AssumpCache) {}
+
+ // Support 'builder' pattern to set members by name at construction time.
+ SimplifyCFGOptions &bonusInstThreshold(int I) {
+ BonusInstThreshold = I;
+ return *this;
+ }
+ SimplifyCFGOptions &forwardSwitchCondToPhi(bool B) {
+ ForwardSwitchCondToPhi = B;
+ return *this;
+ }
+ SimplifyCFGOptions &convertSwitchToLookupTable(bool B) {
+ ConvertSwitchToLookupTable = B;
+ return *this;
+ }
+ SimplifyCFGOptions &needCanonicalLoops(bool B) {
+ NeedCanonicalLoop = B;
+ return *this;
+ }
+ SimplifyCFGOptions &setAssumptionCache(AssumptionCache *Cache) {
+ AC = Cache;
+ return *this;
+ }
};
//===----------------------------------------------------------------------===//
initializeMemCpyOptLegacyPassPass(R);
initializeDCELegacyPassPass(R);
initializeCFGSimplifyPassPass(R);
- initializeLateCFGSimplifyPassPass(R);
}
void LTOCodeGenerator::setAsmUndefinedRefs(LTOModule *Mod) {
// determine whether it succeeded. We can exploit existing control-flow in
// ldrex/strex loops to simplify this, but it needs tidying up.
if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
- addPass(createLateCFGSimplificationPass());
+ addPass(createCFGSimplificationPass(1, true, true, false));
// Run LoopDataPrefetch
//
// determine whether it succeeded. We can exploit existing control-flow in
// ldrex/strex loops to simplify this, but it needs tidying up.
if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
- addPass(createCFGSimplificationPass(-1, [this](const Function &F) {
- const auto &ST = this->TM->getSubtarget<ARMSubtarget>(F);
- return ST.hasAnyDataBarrier() && !ST.isThumb1Only();
- }));
+ addPass(createCFGSimplificationPass(
+ 1, false, false, true, [this](const Function &F) {
+ const auto &ST = this->TM->getSubtarget<ARMSubtarget>(F);
+ return ST.hasAnyDataBarrier() && !ST.isThumb1Only();
+ }));
TargetPassConfig::addIRPasses();
}
addExtensionsToPM(EP_Peephole, MPM);
- MPM.add(createLateCFGSimplificationPass()); // Switches to lookup tables
+ // Switches to lookup tables and other transforms that may not be considered
+ // canonical by other IR passes.
+ MPM.add(createCFGSimplificationPass(1, true, true, false));
addInstructionCombiningPass(MPM);
if (!DisableUnrollLoops) {
initializeIPSCCPLegacyPassPass(Registry);
initializeSROALegacyPassPass(Registry);
initializeCFGSimplifyPassPass(Registry);
- initializeLateCFGSimplifyPassPass(Registry);
initializeStructurizeCFGPass(Registry);
initializeSimpleLoopUnswitchLegacyPassPass(Registry);
initializeSinkingLegacyPassPass(Registry);
}
void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM) {
- unwrap(PM)->add(createCFGSimplificationPass());
-}
-
-void LLVMAddLateCFGSimplificationPass(LLVMPassManagerRef PM) {
- unwrap(PM)->add(createLateCFGSimplificationPass());
+ unwrap(PM)->add(createCFGSimplificationPass(1, false, false, true));
}
void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM) {
#define DEBUG_TYPE "simplifycfg"
-static cl::opt<unsigned>
-UserBonusInstThreshold("bonus-inst-threshold", cl::Hidden, cl::init(1),
- cl::desc("Control the number of bonus instructions (default = 1)"));
+static cl::opt<unsigned> UserBonusInstThreshold(
+ "bonus-inst-threshold", cl::Hidden, cl::init(1),
+ cl::desc("Control the number of bonus instructions (default = 1)"));
+
+static cl::opt<bool> UserKeepLoops(
+ "keep-loops", cl::Hidden, cl::init(true),
+ cl::desc("Preserve canonical loop structure (default = true)"));
+
+static cl::opt<bool> UserSwitchToLookup(
+ "switch-to-lookup", cl::Hidden, cl::init(false),
+ cl::desc("Convert switches to lookup tables (default = false)"));
+
+static cl::opt<bool> UserForwardSwitchCond(
+ "forward-switch-cond", cl::Hidden, cl::init(false),
+ cl::desc("Forward switch condition to phi ops (default = false)"));
STATISTIC(NumSimpl, "Number of blocks simplified");
return true;
}
-// FIXME: The new pass manager always creates a "late" simplifycfg pass using
-// this default constructor.
-SimplifyCFGPass::SimplifyCFGPass()
- : Options(UserBonusInstThreshold, true, true, false) {}
-
-SimplifyCFGPass::SimplifyCFGPass(const SimplifyCFGOptions &PassOptions)
- : Options(PassOptions) {}
+// Command-line settings override compile-time settings.
+SimplifyCFGPass::SimplifyCFGPass(const SimplifyCFGOptions &Opts) {
+ Options.BonusInstThreshold = UserBonusInstThreshold.getNumOccurrences()
+ ? UserBonusInstThreshold
+ : Opts.BonusInstThreshold;
+ Options.ForwardSwitchCondToPhi = UserForwardSwitchCond.getNumOccurrences()
+ ? UserForwardSwitchCond
+ : Opts.ForwardSwitchCondToPhi;
+ Options.ConvertSwitchToLookupTable = UserSwitchToLookup.getNumOccurrences()
+ ? UserSwitchToLookup
+ : Opts.ConvertSwitchToLookupTable;
+ Options.NeedCanonicalLoop = UserKeepLoops.getNumOccurrences()
+ ? UserKeepLoops
+ : Opts.NeedCanonicalLoop;
+}
PreservedAnalyses SimplifyCFGPass::run(Function &F,
FunctionAnalysisManager &AM) {
}
namespace {
-struct BaseCFGSimplifyPass : public FunctionPass {
+struct CFGSimplifyPass : public FunctionPass {
+ static char ID;
+ SimplifyCFGOptions Options;
std::function<bool(const Function &)> PredicateFtor;
- int BonusInstThreshold;
- bool ForwardSwitchCondToPhi;
- bool ConvertSwitchToLookupTable;
- bool KeepCanonicalLoops;
-
- BaseCFGSimplifyPass(int T, bool ForwardSwitchCond, bool ConvertSwitch,
- bool KeepLoops,
- std::function<bool(const Function &)> Ftor, char &ID)
- : FunctionPass(ID), PredicateFtor(std::move(Ftor)),
- ForwardSwitchCondToPhi(ForwardSwitchCond),
- ConvertSwitchToLookupTable(ConvertSwitch),
- KeepCanonicalLoops(KeepLoops) {
- BonusInstThreshold = (T == -1) ? UserBonusInstThreshold : T;
+
+ CFGSimplifyPass(unsigned Threshold = 1, bool ForwardSwitchCond = false,
+ bool ConvertSwitch = false, bool KeepLoops = true,
+ std::function<bool(const Function &)> Ftor = nullptr)
+ : FunctionPass(ID), PredicateFtor(std::move(Ftor)) {
+
+ initializeCFGSimplifyPassPass(*PassRegistry::getPassRegistry());
+
+ // Check for command-line overrides of options for debug/customization.
+ Options.BonusInstThreshold = UserBonusInstThreshold.getNumOccurrences()
+ ? UserBonusInstThreshold
+ : Threshold;
+
+ Options.ForwardSwitchCondToPhi = UserForwardSwitchCond.getNumOccurrences()
+ ? UserForwardSwitchCond
+ : ForwardSwitchCond;
+
+ Options.ConvertSwitchToLookupTable = UserSwitchToLookup.getNumOccurrences()
+ ? UserSwitchToLookup
+ : ConvertSwitch;
+
+ Options.NeedCanonicalLoop =
+ UserKeepLoops.getNumOccurrences() ? UserKeepLoops : KeepLoops;
}
+
bool runOnFunction(Function &F) override {
if (skipFunction(F) || (PredicateFtor && !PredicateFtor(F)))
return false;
- AssumptionCache *AC =
- &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
- const TargetTransformInfo &TTI =
- getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
- return simplifyFunctionCFG(F, TTI,
- {BonusInstThreshold, ForwardSwitchCondToPhi,
- ConvertSwitchToLookupTable, KeepCanonicalLoops,
- AC});
+ Options.AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
+ auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
+ return simplifyFunctionCFG(F, TTI, Options);
}
-
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<AssumptionCacheTracker>();
AU.addRequired<TargetTransformInfoWrapperPass>();
AU.addPreserved<GlobalsAAWrapperPass>();
}
};
-
-struct CFGSimplifyPass : public BaseCFGSimplifyPass {
- static char ID; // Pass identification, replacement for typeid
-
- CFGSimplifyPass(int T = -1,
- std::function<bool(const Function &)> Ftor = nullptr)
- : BaseCFGSimplifyPass(T, false, false, true, Ftor, ID) {
- initializeCFGSimplifyPassPass(*PassRegistry::getPassRegistry());
- }
-};
-
-struct LateCFGSimplifyPass : public BaseCFGSimplifyPass {
- static char ID; // Pass identification, replacement for typeid
-
- LateCFGSimplifyPass(int T = -1,
- std::function<bool(const Function &)> Ftor = nullptr)
- : BaseCFGSimplifyPass(T, true, true, false, Ftor, ID) {
- initializeLateCFGSimplifyPassPass(*PassRegistry::getPassRegistry());
- }
-};
}
char CFGSimplifyPass::ID = 0;
INITIALIZE_PASS_END(CFGSimplifyPass, "simplifycfg", "Simplify the CFG", false,
false)
-char LateCFGSimplifyPass::ID = 0;
-INITIALIZE_PASS_BEGIN(LateCFGSimplifyPass, "latesimplifycfg",
- "Simplify the CFG more aggressively", false, false)
-INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
-INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
-INITIALIZE_PASS_END(LateCFGSimplifyPass, "latesimplifycfg",
- "Simplify the CFG more aggressively", false, false)
-
// Public interface to the CFGSimplification pass
FunctionPass *
-llvm::createCFGSimplificationPass(int Threshold,
- std::function<bool(const Function &)> Ftor) {
- return new CFGSimplifyPass(Threshold, std::move(Ftor));
-}
-
-// Public interface to the LateCFGSimplification pass
-FunctionPass *
-llvm::createLateCFGSimplificationPass(int Threshold,
+llvm::createCFGSimplificationPass(unsigned Threshold, bool ForwardSwitchCond,
+ bool ConvertSwitch, bool KeepLoops,
std::function<bool(const Function &)> Ftor) {
- return new LateCFGSimplifyPass(Threshold, std::move(Ftor));
+ return new CFGSimplifyPass(Threshold, ForwardSwitchCond, ConvertSwitch,
+ KeepLoops, std::move(Ftor));
}
; CHECK: [[FAILED]]:
; CHECK-NOT: cmp {{w[0-9]+}}, {{w[0-9]+}}
-; verify the preheader is simplified by latesimplifycfg.
+; verify the preheader is simplified by simplifycfg.
; CHECK: [[PH]]:
; CHECK: orr w22, wzr, #0x2
; CHECK-NOT: orr w22, wzr, #0x4
-; RUN: opt < %s -O3 -latesimplifycfg -mcpu=core-avx2 -mtriple=x86_64-unknown-linux-gnu -S | FileCheck --check-prefix AUTO_VEC %s
+; RUN: opt < %s -O3 -simplifycfg -keep-loops=false -mcpu=core-avx2 -mtriple=x86_64-unknown-linux-gnu -S | FileCheck --check-prefix AUTO_VEC %s
; This test checks auto-vectorization with FP induction variable.
; The FP operation is not "fast" and requires "fast-math" function attribute.
; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S | FileCheck --check-prefix VEC4_INTERL1 %s
; RUN: opt < %s -loop-vectorize -force-vector-interleave=2 -force-vector-width=4 -dce -instcombine -S | FileCheck --check-prefix VEC4_INTERL2 %s
; RUN: opt < %s -loop-vectorize -force-vector-interleave=2 -force-vector-width=1 -dce -instcombine -S | FileCheck --check-prefix VEC1_INTERL2 %s
-; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=2 -dce -simplifycfg -instcombine -latesimplifycfg -S | FileCheck --check-prefix VEC2_INTERL1_PRED_STORE %s
+; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=2 -dce -simplifycfg -instcombine -simplifycfg -keep-loops=false -S | FileCheck --check-prefix VEC2_INTERL1_PRED_STORE %s
@fp_inc = common global float 0.000000e+00, align 4
-; RUN: opt -S -latesimplifycfg -mtriple=arm -relocation-model=static < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
-; RUN: opt -S -latesimplifycfg -mtriple=arm -relocation-model=pic < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
-; RUN: opt -S -latesimplifycfg -mtriple=arm -relocation-model=ropi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
-; RUN: opt -S -latesimplifycfg -mtriple=arm -relocation-model=rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
-; RUN: opt -S -latesimplifycfg -mtriple=arm -relocation-model=ropi-rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
+; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=static < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
+; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=pic < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
+; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=ropi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
+; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
+; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=ropi-rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
; CHECK: @{{.*}} = private unnamed_addr constant [3 x i32] [i32 1234, i32 5678, i32 15532]
; ENABLE: @{{.*}} = private unnamed_addr constant [3 x i32*] [i32* @c1, i32* @c2, i32* @c3]
-; RUN: opt -latesimplifycfg -S %s | FileCheck %s
+; RUN: opt -simplifycfg -switch-to-lookup -S %s | FileCheck %s
; rdar://15268442
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -latesimplifycfg -S | FileCheck %s
+; RUN: opt < %s -simplifycfg -forward-switch-cond=false -S | FileCheck %s --check-prefix=NO_FWD
+; RUN: opt < %s -simplifycfg -forward-switch-cond=true -S | FileCheck %s --check-prefix=FWD
; PR10131
target triple = "i386-pc-linux-gnu"
define i32 @t(i32 %m) nounwind readnone {
-; CHECK-LABEL: @t(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[M:%.*]], 4
-; CHECK-NEXT: [[M_:%.*]] = select i1 [[SWITCH]], i32 [[M]], i32 4
-; CHECK-NEXT: ret i32 [[M_]]
+; NO_FWD-LABEL: @t(
+; NO_FWD-NEXT: entry:
+; NO_FWD-NEXT: switch i32 [[M:%.*]], label [[SW_BB4:%.*]] [
+; NO_FWD-NEXT: i32 0, label [[RETURN:%.*]]
+; NO_FWD-NEXT: i32 1, label [[SW_BB1:%.*]]
+; NO_FWD-NEXT: i32 2, label [[SW_BB2:%.*]]
+; NO_FWD-NEXT: i32 3, label [[SW_BB3:%.*]]
+; NO_FWD-NEXT: ]
+; NO_FWD: sw.bb1:
+; NO_FWD-NEXT: br label [[RETURN]]
+; NO_FWD: sw.bb2:
+; NO_FWD-NEXT: br label [[RETURN]]
+; NO_FWD: sw.bb3:
+; NO_FWD-NEXT: br label [[RETURN]]
+; NO_FWD: sw.bb4:
+; NO_FWD-NEXT: br label [[RETURN]]
+; NO_FWD: return:
+; NO_FWD-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 4, [[SW_BB4]] ], [ 3, [[SW_BB3]] ], [ 2, [[SW_BB2]] ], [ 1, [[SW_BB1]] ], [ 0, [[ENTRY:%.*]] ]
+; NO_FWD-NEXT: ret i32 [[RETVAL_0]]
+;
+; FWD-LABEL: @t(
+; FWD-NEXT: entry:
+; FWD-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[M:%.*]], 4
+; FWD-NEXT: [[M_:%.*]] = select i1 [[SWITCH]], i32 [[M]], i32 4
+; FWD-NEXT: ret i32 [[M_]]
;
entry:
switch i32 %m, label %sw.bb4 [
; This then subsequently should allow squashing of the other trivial case blocks.
define i32 @PR34471(i32 %x) {
-; CHECK-LABEL: @PR34471(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: switch i32 [[X:%.*]], label [[ELSE3:%.*]] [
-; CHECK-NEXT: i32 17, label [[RETURN:%.*]]
-; CHECK-NEXT: i32 19, label [[RETURN]]
-; CHECK-NEXT: i32 42, label [[RETURN]]
-; CHECK-NEXT: ]
-; CHECK: else3:
-; CHECK-NEXT: br label [[RETURN]]
-; CHECK: return:
-; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[ELSE3]] ], [ [[X]], [[ENTRY:%.*]] ], [ [[X]], [[ENTRY]] ], [ [[X]], [[ENTRY]] ]
-; CHECK-NEXT: ret i32 [[R]]
+; NO_FWD-LABEL: @PR34471(
+; NO_FWD-NEXT: entry:
+; NO_FWD-NEXT: switch i32 [[X:%.*]], label [[ELSE3:%.*]] [
+; NO_FWD-NEXT: i32 17, label [[RETURN:%.*]]
+; NO_FWD-NEXT: i32 19, label [[IF19:%.*]]
+; NO_FWD-NEXT: i32 42, label [[IF42:%.*]]
+; NO_FWD-NEXT: ]
+; NO_FWD: if19:
+; NO_FWD-NEXT: br label [[RETURN]]
+; NO_FWD: if42:
+; NO_FWD-NEXT: br label [[RETURN]]
+; NO_FWD: else3:
+; NO_FWD-NEXT: br label [[RETURN]]
+; NO_FWD: return:
+; NO_FWD-NEXT: [[R:%.*]] = phi i32 [ [[X]], [[IF19]] ], [ [[X]], [[IF42]] ], [ 0, [[ELSE3]] ], [ 17, [[ENTRY:%.*]] ]
+; NO_FWD-NEXT: ret i32 [[R]]
+;
+; FWD-LABEL: @PR34471(
+; FWD-NEXT: entry:
+; FWD-NEXT: switch i32 [[X:%.*]], label [[ELSE3:%.*]] [
+; FWD-NEXT: i32 17, label [[RETURN:%.*]]
+; FWD-NEXT: i32 19, label [[RETURN]]
+; FWD-NEXT: i32 42, label [[RETURN]]
+; FWD-NEXT: ]
+; FWD: else3:
+; FWD-NEXT: br label [[RETURN]]
+; FWD: return:
+; FWD-NEXT: [[R:%.*]] = phi i32 [ 0, [[ELSE3]] ], [ [[X]], [[ENTRY:%.*]] ], [ [[X]], [[ENTRY]] ], [ [[X]], [[ENTRY]] ]
+; FWD-NEXT: ret i32 [[R]]
;
entry:
switch i32 %x, label %else3 [
-; RUN: opt < %s -latesimplifycfg -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
-; In the presence of "-no-jump-tables"="true", late simplifycfg should not
-; convert any switch cases to lookup tables.
+; RUN: opt < %s -simplifycfg -switch-to-lookup -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+; In the presence of "-no-jump-tables"="true", simplifycfg should not convert switches to lookup tables.
+
; CHECK: @switch.table.bar = private unnamed_addr constant [4 x i32] [i32 55, i32 123, i32 0, i32 -1]
; CHECK-LABEL: foo
; CHECK-NOT: @switch.table.foo = private unnamed_addr constant [4 x i32] [i32 55, i32 123, i32 0, i32 -1]
-; RUN: opt -S -latesimplifycfg < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
+; RUN: opt -S -simplifycfg -switch-to-lookup < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
; rdar://17887153
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin12.0.0"
-; RUN: opt -S -latesimplifycfg < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
+; RUN: opt -S -simplifycfg -switch-to-lookup < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
; rdar://17735071
target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin12.0.0"
-; RUN: opt < %s -latesimplifycfg -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+; RUN: opt < %s -simplifycfg -switch-to-lookup=true -keep-loops=false -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %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"
target triple = "x86_64-unknown-linux-gnu"
-; RUN: opt -latesimplifycfg -S < %s | FileCheck %s
+; RUN: opt -simplifycfg -keep-loops=false -S < %s | FileCheck %s
; It's not worthwhile to if-convert one of the phi nodes and leave
; the other behind, because that still requires a branch. If
-; RUN: opt -latesimplifycfg -S < %s | FileCheck %s
+; RUN: opt -simplifycfg -keep-loops=false -S < %s | FileCheck %s
define void @test1(i32 %n) #0 {
entry:
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -latesimplifycfg -S | FileCheck %s
+; RUN: opt < %s -simplifycfg -switch-to-lookup -S | FileCheck %s
target datalayout = "e-n32"