forked from OSchip/llvm-project
[SimplifyCFG][PhaseOrdering] Defer lowering switch into an integer range comparison and branch until after at least the IPSCCP
That transformation is lossy, as discussed in https://github.com/llvm/llvm-project/issues/53853 and https://github.com/rust-lang/rust/issues/85133#issuecomment-904185574 This is an alternative to D119839, which would add a limited IPSCCP into SimplifyCFG. Unlike lowering switch to lookup, we still want this transformation to happen relatively early, but after giving a chance for the things like CVP to do their thing. It seems like deferring it just until the IPSCCP is enough for the tests at hand, but perhaps we need to be more aggressive and disable it until CVP. Fixes https://github.com/llvm/llvm-project/issues/53853 Refs. https://github.com/rust-lang/rust/issues/85133 Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D119854
This commit is contained in:
parent
d4a53f3bfa
commit
371fcb720e
|
@ -23,6 +23,7 @@ class AssumptionCache;
|
|||
struct SimplifyCFGOptions {
|
||||
int BonusInstThreshold = 1;
|
||||
bool ForwardSwitchCondToPhi = false;
|
||||
bool ConvertSwitchRangeToICmp = false;
|
||||
bool ConvertSwitchToLookupTable = false;
|
||||
bool NeedCanonicalLoop = true;
|
||||
bool HoistCommonInsts = false;
|
||||
|
@ -41,6 +42,10 @@ struct SimplifyCFGOptions {
|
|||
ForwardSwitchCondToPhi = B;
|
||||
return *this;
|
||||
}
|
||||
SimplifyCFGOptions &convertSwitchRangeToICmp(bool B) {
|
||||
ConvertSwitchRangeToICmp = B;
|
||||
return *this;
|
||||
}
|
||||
SimplifyCFGOptions &convertSwitchToLookupTable(bool B) {
|
||||
ConvertSwitchToLookupTable = B;
|
||||
return *this;
|
||||
|
|
|
@ -679,6 +679,8 @@ Expected<SimplifyCFGOptions> parseSimplifyCFGOptions(StringRef Params) {
|
|||
bool Enable = !ParamName.consume_front("no-");
|
||||
if (ParamName == "forward-switch-cond") {
|
||||
Result.forwardSwitchCondToPhi(Enable);
|
||||
} else if (ParamName == "switch-range-to-icmp") {
|
||||
Result.convertSwitchRangeToICmp(Enable);
|
||||
} else if (ParamName == "switch-to-lookup") {
|
||||
Result.convertSwitchToLookupTable(Enable);
|
||||
} else if (ParamName == "keep-loops") {
|
||||
|
|
|
@ -259,14 +259,16 @@ PassBuilder::buildO1FunctionSimplificationPipeline(OptimizationLevel Level,
|
|||
FPM.addPass(EarlyCSEPass(true /* Enable mem-ssa. */));
|
||||
|
||||
// Hoisting of scalars and load expressions.
|
||||
FPM.addPass(SimplifyCFGPass());
|
||||
FPM.addPass(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
FPM.addPass(InstCombinePass());
|
||||
|
||||
FPM.addPass(LibCallsShrinkWrapPass());
|
||||
|
||||
invokePeepholeEPCallbacks(FPM, Level);
|
||||
|
||||
FPM.addPass(SimplifyCFGPass());
|
||||
FPM.addPass(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
|
||||
// Form canonically associated expression trees, and simplify the trees using
|
||||
// basic mathematical properties. For example, this will form (nearly)
|
||||
|
@ -335,7 +337,8 @@ PassBuilder::buildO1FunctionSimplificationPipeline(OptimizationLevel Level,
|
|||
FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM1),
|
||||
/*UseMemorySSA=*/true,
|
||||
/*UseBlockFrequencyInfo=*/true));
|
||||
FPM.addPass(SimplifyCFGPass());
|
||||
FPM.addPass(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
FPM.addPass(InstCombinePass());
|
||||
// The loop passes in LPM2 (LoopFullUnrollPass) do not preserve MemorySSA.
|
||||
// *All* loop passes must preserve it, in order to be able to use it.
|
||||
|
@ -373,7 +376,8 @@ PassBuilder::buildO1FunctionSimplificationPipeline(OptimizationLevel Level,
|
|||
// the simplifications and basic cleanup after all the simplifications.
|
||||
// TODO: Investigate if this is too expensive.
|
||||
FPM.addPass(ADCEPass());
|
||||
FPM.addPass(SimplifyCFGPass());
|
||||
FPM.addPass(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
FPM.addPass(InstCombinePass());
|
||||
invokePeepholeEPCallbacks(FPM, Level);
|
||||
|
||||
|
@ -408,7 +412,8 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
|
|||
// Global value numbering based sinking.
|
||||
if (EnableGVNSink) {
|
||||
FPM.addPass(GVNSinkPass());
|
||||
FPM.addPass(SimplifyCFGPass());
|
||||
FPM.addPass(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
}
|
||||
|
||||
if (EnableConstraintElimination)
|
||||
|
@ -421,7 +426,8 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
|
|||
FPM.addPass(JumpThreadingPass());
|
||||
FPM.addPass(CorrelatedValuePropagationPass());
|
||||
|
||||
FPM.addPass(SimplifyCFGPass());
|
||||
FPM.addPass(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
FPM.addPass(InstCombinePass());
|
||||
if (Level == OptimizationLevel::O3)
|
||||
FPM.addPass(AggressiveInstCombinePass());
|
||||
|
@ -438,7 +444,8 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
|
|||
FPM.addPass(PGOMemOPSizeOpt());
|
||||
|
||||
FPM.addPass(TailCallElimPass());
|
||||
FPM.addPass(SimplifyCFGPass());
|
||||
FPM.addPass(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
|
||||
// Form canonically associated expression trees, and simplify the trees using
|
||||
// basic mathematical properties. For example, this will form (nearly)
|
||||
|
@ -510,7 +517,8 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
|
|||
FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM1),
|
||||
/*UseMemorySSA=*/true,
|
||||
/*UseBlockFrequencyInfo=*/true));
|
||||
FPM.addPass(SimplifyCFGPass());
|
||||
FPM.addPass(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
FPM.addPass(InstCombinePass());
|
||||
// The loop passes in LPM2 (LoopIdiomRecognizePass, IndVarSimplifyPass,
|
||||
// LoopDeletionPass and LoopFullUnrollPass) do not preserve MemorySSA.
|
||||
|
@ -575,8 +583,10 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
|
|||
for (auto &C : ScalarOptimizerLateEPCallbacks)
|
||||
C(FPM, Level);
|
||||
|
||||
FPM.addPass(SimplifyCFGPass(
|
||||
SimplifyCFGOptions().hoistCommonInsts(true).sinkCommonInsts(true)));
|
||||
FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions()
|
||||
.convertSwitchRangeToICmp(true)
|
||||
.hoistCommonInsts(true)
|
||||
.sinkCommonInsts(true)));
|
||||
FPM.addPass(InstCombinePass());
|
||||
invokePeepholeEPCallbacks(FPM, Level);
|
||||
|
||||
|
@ -614,7 +624,8 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM,
|
|||
FunctionPassManager FPM;
|
||||
FPM.addPass(SROAPass());
|
||||
FPM.addPass(EarlyCSEPass()); // Catch trivial redundancies.
|
||||
FPM.addPass(SimplifyCFGPass()); // Merge & remove basic blocks.
|
||||
FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(
|
||||
true))); // Merge & remove basic blocks.
|
||||
FPM.addPass(InstCombinePass()); // Combine silly sequences.
|
||||
invokePeepholeEPCallbacks(FPM, Level);
|
||||
|
||||
|
@ -928,7 +939,8 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
|
|||
GlobalCleanupPM.addPass(InstCombinePass());
|
||||
invokePeepholeEPCallbacks(GlobalCleanupPM, Level);
|
||||
|
||||
GlobalCleanupPM.addPass(SimplifyCFGPass());
|
||||
GlobalCleanupPM.addPass(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(GlobalCleanupPM),
|
||||
PTO.EagerlyInvalidateAnalyses));
|
||||
|
||||
|
@ -1015,7 +1027,8 @@ void PassBuilder::addVectorPasses(OptimizationLevel Level,
|
|||
ExtraPasses.addPass(
|
||||
createFunctionToLoopPassAdaptor(std::move(LPM), /*UseMemorySSA=*/true,
|
||||
/*UseBlockFrequencyInfo=*/true));
|
||||
ExtraPasses.addPass(SimplifyCFGPass());
|
||||
ExtraPasses.addPass(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
ExtraPasses.addPass(InstCombinePass());
|
||||
FPM.addPass(std::move(ExtraPasses));
|
||||
}
|
||||
|
@ -1031,6 +1044,7 @@ void PassBuilder::addVectorPasses(OptimizationLevel Level,
|
|||
// before SLP vectorization.
|
||||
FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions()
|
||||
.forwardSwitchCondToPhi(true)
|
||||
.convertSwitchRangeToICmp(true)
|
||||
.convertSwitchToLookupTable(true)
|
||||
.needCanonicalLoops(false)
|
||||
.hoistCommonInsts(true)
|
||||
|
@ -1202,7 +1216,8 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
|
|||
|
||||
// LoopSink (and other loop passes since the last simplifyCFG) might have
|
||||
// resulted in single-entry-single-exit or empty blocks. Clean up the CFG.
|
||||
OptimizePM.addPass(SimplifyCFGPass());
|
||||
OptimizePM.addPass(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
|
||||
OptimizePM.addPass(CoroCleanupPass());
|
||||
|
||||
|
@ -1676,8 +1691,9 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
|
|||
|
||||
// Add late LTO optimization passes.
|
||||
// Delete basic blocks, which optimization passes may have killed.
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(
|
||||
SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(true))));
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(SimplifyCFGPass(
|
||||
SimplifyCFGOptions().convertSwitchRangeToICmp(true).hoistCommonInsts(
|
||||
true))));
|
||||
|
||||
// Drop bodies of available eternally objects to improve GlobalDCE.
|
||||
MPM.addPass(EliminateAvailableExternallyPass());
|
||||
|
|
|
@ -423,6 +423,7 @@ FUNCTION_PASS_WITH_PARAMS("simplifycfg",
|
|||
},
|
||||
parseSimplifyCFGOptions,
|
||||
"no-forward-switch-cond;forward-switch-cond;"
|
||||
"no-switch-range-to-icmp;switch-range-to-icmp;"
|
||||
"no-switch-to-lookup;switch-to-lookup;"
|
||||
"no-keep-loops;keep-loops;"
|
||||
"no-hoist-common-insts;hoist-common-insts;"
|
||||
|
|
|
@ -531,6 +531,7 @@ void AArch64PassConfig::addIRPasses() {
|
|||
if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
|
||||
addPass(createCFGSimplificationPass(SimplifyCFGOptions()
|
||||
.forwardSwitchCondToPhi(true)
|
||||
.convertSwitchRangeToICmp(true)
|
||||
.convertSwitchToLookupTable(true)
|
||||
.needCanonicalLoops(false)
|
||||
.hoistCommonInsts(true)
|
||||
|
|
|
@ -344,6 +344,7 @@ void HexagonPassConfig::addIRPasses() {
|
|||
if (EnableInitialCFGCleanup)
|
||||
addPass(createCFGSimplificationPass(SimplifyCFGOptions()
|
||||
.forwardSwitchCondToPhi(true)
|
||||
.convertSwitchRangeToICmp(true)
|
||||
.convertSwitchToLookupTable(true)
|
||||
.needCanonicalLoops(false)
|
||||
.hoistCommonInsts(true)
|
||||
|
|
|
@ -365,7 +365,9 @@ void PassManagerBuilder::addPGOInstrPasses(legacy::PassManagerBase &MPM,
|
|||
MPM.add(createFunctionInliningPass(IP));
|
||||
MPM.add(createSROAPass());
|
||||
MPM.add(createEarlyCSEPass()); // Catch trivial redundancies
|
||||
MPM.add(createCFGSimplificationPass()); // Merge & remove BBs
|
||||
MPM.add(createCFGSimplificationPass(
|
||||
SimplifyCFGOptions().convertSwitchRangeToICmp(
|
||||
true))); // Merge & remove BBs
|
||||
MPM.add(createInstructionCombiningPass()); // Combine silly seq's
|
||||
addExtensionsToPM(EP_Peephole, MPM);
|
||||
}
|
||||
|
@ -404,7 +406,8 @@ void PassManagerBuilder::addFunctionSimplificationPasses(
|
|||
MPM.add(createGVNHoistPass());
|
||||
if (EnableGVNSink) {
|
||||
MPM.add(createGVNSinkPass());
|
||||
MPM.add(createCFGSimplificationPass());
|
||||
MPM.add(createCFGSimplificationPass(
|
||||
SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,7 +421,9 @@ void PassManagerBuilder::addFunctionSimplificationPasses(
|
|||
MPM.add(createJumpThreadingPass()); // Thread jumps.
|
||||
MPM.add(createCorrelatedValuePropagationPass()); // Propagate conditionals
|
||||
}
|
||||
MPM.add(createCFGSimplificationPass()); // Merge & remove BBs
|
||||
MPM.add(
|
||||
createCFGSimplificationPass(SimplifyCFGOptions().convertSwitchRangeToICmp(
|
||||
true))); // Merge & remove BBs
|
||||
// Combine silly seq's
|
||||
if (OptLevel > 2)
|
||||
MPM.add(createAggressiveInstCombinerPass());
|
||||
|
@ -434,7 +439,9 @@ void PassManagerBuilder::addFunctionSimplificationPasses(
|
|||
// TODO: Investigate the cost/benefit of tail call elimination on debugging.
|
||||
if (OptLevel > 1)
|
||||
MPM.add(createTailCallEliminationPass()); // Eliminate tail calls
|
||||
MPM.add(createCFGSimplificationPass()); // Merge & remove BBs
|
||||
MPM.add(
|
||||
createCFGSimplificationPass(SimplifyCFGOptions().convertSwitchRangeToICmp(
|
||||
true))); // Merge & remove BBs
|
||||
MPM.add(createReassociatePass()); // Reassociate expressions
|
||||
|
||||
// The matrix extension can introduce large vector operations early, which can
|
||||
|
@ -465,7 +472,8 @@ void PassManagerBuilder::addFunctionSimplificationPasses(
|
|||
// FIXME: We break the loop pass pipeline here in order to do full
|
||||
// simplifycfg. Eventually loop-simplifycfg should be enhanced to replace the
|
||||
// need for this.
|
||||
MPM.add(createCFGSimplificationPass());
|
||||
MPM.add(createCFGSimplificationPass(
|
||||
SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
MPM.add(createInstructionCombiningPass());
|
||||
// We resume loop passes creating a second loop pipeline here.
|
||||
if (EnableLoopFlatten) {
|
||||
|
@ -582,7 +590,8 @@ void PassManagerBuilder::addVectorPasses(legacy::PassManagerBase &PM,
|
|||
PM.add(createInstructionCombiningPass());
|
||||
PM.add(createLICMPass(LicmMssaOptCap, LicmMssaNoAccForPromotionCap));
|
||||
PM.add(createLoopUnswitchPass(SizeLevel || OptLevel < 3, DivergentTarget));
|
||||
PM.add(createCFGSimplificationPass());
|
||||
PM.add(createCFGSimplificationPass(
|
||||
SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
PM.add(createInstructionCombiningPass());
|
||||
}
|
||||
|
||||
|
@ -597,6 +606,7 @@ void PassManagerBuilder::addVectorPasses(legacy::PassManagerBase &PM,
|
|||
// before SLP vectorization.
|
||||
PM.add(createCFGSimplificationPass(SimplifyCFGOptions()
|
||||
.forwardSwitchCondToPhi(true)
|
||||
.convertSwitchRangeToICmp(true)
|
||||
.convertSwitchToLookupTable(true)
|
||||
.needCanonicalLoops(false)
|
||||
.hoistCommonInsts(true)
|
||||
|
@ -772,7 +782,9 @@ void PassManagerBuilder::populateModulePassManager(
|
|||
|
||||
MPM.add(createInstructionCombiningPass()); // Clean up after IPCP & DAE
|
||||
addExtensionsToPM(EP_Peephole, MPM);
|
||||
MPM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE
|
||||
MPM.add(
|
||||
createCFGSimplificationPass(SimplifyCFGOptions().convertSwitchRangeToICmp(
|
||||
true))); // Clean up after IPCP & DAE
|
||||
|
||||
// For SamplePGO in ThinLTO compile phase, we do not want to do indirect
|
||||
// call promotion as it will change the CFG too much to make the 2nd
|
||||
|
@ -972,7 +984,8 @@ void PassManagerBuilder::populateModulePassManager(
|
|||
|
||||
// LoopSink (and other loop passes since the last simplifyCFG) might have
|
||||
// resulted in single-entry-single-exit or empty blocks. Clean up the CFG.
|
||||
MPM.add(createCFGSimplificationPass());
|
||||
MPM.add(createCFGSimplificationPass(
|
||||
SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
|
||||
|
||||
addExtensionsToPM(EP_OptimizerLast, MPM);
|
||||
|
||||
|
|
|
@ -59,6 +59,11 @@ static cl::opt<bool> UserKeepLoops(
|
|||
"keep-loops", cl::Hidden, cl::init(true),
|
||||
cl::desc("Preserve canonical loop structure (default = true)"));
|
||||
|
||||
static cl::opt<bool> UserSwitchRangeToICmp(
|
||||
"switch-range-to-icmp", cl::Hidden, cl::init(false),
|
||||
cl::desc(
|
||||
"Convert switches into an integer range comparison (default = false)"));
|
||||
|
||||
static cl::opt<bool> UserSwitchToLookup(
|
||||
"switch-to-lookup", cl::Hidden, cl::init(false),
|
||||
cl::desc("Convert switches to lookup tables (default = false)"));
|
||||
|
@ -311,6 +316,8 @@ static void applyCommandLineOverridesToOptions(SimplifyCFGOptions &Options) {
|
|||
Options.BonusInstThreshold = UserBonusInstThreshold;
|
||||
if (UserForwardSwitchCond.getNumOccurrences())
|
||||
Options.ForwardSwitchCondToPhi = UserForwardSwitchCond;
|
||||
if (UserSwitchRangeToICmp.getNumOccurrences())
|
||||
Options.ConvertSwitchRangeToICmp = UserSwitchRangeToICmp;
|
||||
if (UserSwitchToLookup.getNumOccurrences())
|
||||
Options.ConvertSwitchToLookupTable = UserSwitchToLookup;
|
||||
if (UserKeepLoops.getNumOccurrences())
|
||||
|
@ -337,6 +344,8 @@ void SimplifyCFGPass::printPipeline(
|
|||
OS << "<";
|
||||
OS << "bonus-inst-threshold=" << Options.BonusInstThreshold << ";";
|
||||
OS << (Options.ForwardSwitchCondToPhi ? "" : "no-") << "forward-switch-cond;";
|
||||
OS << (Options.ConvertSwitchRangeToICmp ? "" : "no-")
|
||||
<< "switch-range-to-icmp;";
|
||||
OS << (Options.ConvertSwitchToLookupTable ? "" : "no-")
|
||||
<< "switch-to-lookup;";
|
||||
OS << (Options.NeedCanonicalLoop ? "" : "no-") << "keep-loops;";
|
||||
|
|
|
@ -6559,7 +6559,9 @@ bool SimplifyCFGOpt::simplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
|
|||
}
|
||||
|
||||
// Try to transform the switch into an icmp and a branch.
|
||||
if (TurnSwitchRangeIntoICmp(SI, Builder))
|
||||
// The conversion from switch to comparison may lose information on
|
||||
// impossible switch values, so disable it early in the pipeline.
|
||||
if (Options.ConvertSwitchRangeToICmp && TurnSwitchRangeIntoICmp(SI, Builder))
|
||||
return requestResimplify();
|
||||
|
||||
// Remove unreachable cases.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
;; Test that the -print-pipeline-passes option correctly prints some explicitly specified pipelines.
|
||||
|
||||
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(adce),function(simplifycfg<bonus-inst-threshold=123;no-forward-switch-cond;switch-to-lookup;keep-loops;no-hoist-common-insts;sink-common-insts>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-0
|
||||
; CHECK-0: function(adce),function(simplifycfg<bonus-inst-threshold=123;no-forward-switch-cond;switch-to-lookup;keep-loops;no-hoist-common-insts;sink-common-insts>)
|
||||
; CHECK-0: function(adce),function(simplifycfg<bonus-inst-threshold=123;no-forward-switch-cond;no-switch-range-to-icmp;switch-to-lookup;keep-loops;no-hoist-common-insts;sink-common-insts>)
|
||||
|
||||
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='module(rpo-function-attrs,require<globals-aa>,function(float2int,lower-constant-intrinsics,loop(loop-rotate)),invalidate<globals-aa>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-1
|
||||
; CHECK-1: rpo-function-attrs,require<globals-aa>,function(float2int,lower-constant-intrinsics,loop(loop-rotate)),invalidate<globals-aa>
|
||||
|
@ -56,7 +56,7 @@
|
|||
; CHECK-17: function(print<stack-lifetime><may>,print<stack-lifetime><must>)
|
||||
|
||||
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(simplifycfg<bonus-inst-threshold=5;forward-switch-cond;switch-to-lookup;keep-loops;hoist-common-insts;sink-common-insts>,simplifycfg<bonus-inst-threshold=7;no-forward-switch-cond;no-switch-to-lookup;no-keep-loops;no-hoist-common-insts;no-sink-common-insts>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-18
|
||||
; CHECK-18: function(simplifycfg<bonus-inst-threshold=5;forward-switch-cond;switch-to-lookup;keep-loops;hoist-common-insts;sink-common-insts>,simplifycfg<bonus-inst-threshold=7;no-forward-switch-cond;no-switch-to-lookup;no-keep-loops;no-hoist-common-insts;no-sink-common-insts>)
|
||||
; CHECK-18: function(simplifycfg<bonus-inst-threshold=5;forward-switch-cond;no-switch-range-to-icmp;switch-to-lookup;keep-loops;hoist-common-insts;sink-common-insts>,simplifycfg<bonus-inst-threshold=7;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;no-keep-loops;no-hoist-common-insts;no-sink-common-insts>)
|
||||
|
||||
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only>,loop-vectorize<interleave-forced-only;vectorize-forced-only>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-19
|
||||
; CHECK-19: function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,loop-vectorize<interleave-forced-only;vectorize-forced-only;>)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
; Tests the PHI nodes in cleanuppads for catchswitch instructions are correctly
|
||||
; split up.
|
||||
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
|
||||
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg<switch-range-to-icmp>,early-cse' -S | FileCheck %s
|
||||
|
||||
declare i32 @__CxxFrameHandler3(...)
|
||||
define i8* @f2(i1 %val) "coroutine.presplit"="1" personality i32 (...)* @__CxxFrameHandler3 {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -loop-unroll -simplifycfg -instcombine -simplifycfg -S -mtriple arm-none-eabi -mcpu=cortex-m7 %s | FileCheck %s
|
||||
; RUN: opt -loop-unroll -simplifycfg -switch-range-to-icmp -instcombine -simplifycfg -S -mtriple arm-none-eabi -mcpu=cortex-m7 %s | FileCheck %s
|
||||
|
||||
; This test is meant to check that this loop is unrolled into three iterations.
|
||||
define void @test(i32* %x, i32 %n) {
|
||||
|
|
|
@ -14,11 +14,9 @@
|
|||
define i64 @test1(i64 %x) {
|
||||
; CHECK-LABEL: @test1(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[SWITCH:%.*]] = icmp eq i64 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[X]], 100
|
||||
; CHECK-NEXT: [[DOT:%.*]] = select i1 [[TMP0]], i64 200, i64 10
|
||||
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = select i1 [[SWITCH]], i64 0, i64 [[DOT]]
|
||||
; CHECK-NEXT: ret i64 [[COMMON_RET_OP]]
|
||||
; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i64 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP]], i64 0, i64 10
|
||||
; CHECK-NEXT: ret i64 [[SWITCH_SELECT]]
|
||||
;
|
||||
entry:
|
||||
switch i64 %x, label %bb3 [
|
||||
|
@ -42,11 +40,9 @@ bb5:
|
|||
define i64 @test2(i64 %x) {
|
||||
; CHECK-LABEL: @test2(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i64 [[X:%.*]], 101
|
||||
; CHECK-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP]], i64 200, i64 10
|
||||
; CHECK-NEXT: [[SWITCH_SELECTCMP1:%.*]] = icmp eq i64 [[X]], 1
|
||||
; CHECK-NEXT: [[SWITCH_SELECT2:%.*]] = select i1 [[SWITCH_SELECTCMP1]], i64 0, i64 [[SWITCH_SELECT]]
|
||||
; CHECK-NEXT: ret i64 [[SWITCH_SELECT2]]
|
||||
; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i64 [[X:%.*]], 1
|
||||
; CHECK-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP]], i64 0, i64 10
|
||||
; CHECK-NEXT: ret i64 [[SWITCH_SELECT]]
|
||||
;
|
||||
entry:
|
||||
switch i64 %x, label %bb3 [
|
||||
|
@ -96,10 +92,8 @@ define i64 @test_fail1(i64 %x) {
|
|||
; CHECK-LABEL: @test_fail1(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[SWITCH:%.*]] = icmp eq i64 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[X]], 100
|
||||
; CHECK-NEXT: [[DOT:%.*]] = select i1 [[TMP0]], i64 200, i64 10
|
||||
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = select i1 [[SWITCH]], i64 0, i64 [[DOT]]
|
||||
; CHECK-NEXT: ret i64 [[COMMON_RET_OP]]
|
||||
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[SWITCH]], i64 0, i64 10
|
||||
; CHECK-NEXT: ret i64 [[SPEC_SELECT]]
|
||||
;
|
||||
entry:
|
||||
switch i64 %x, label %bb3 [
|
||||
|
@ -124,9 +118,9 @@ bb5:
|
|||
define i64 @test_fail2(i64 %x) {
|
||||
; CHECK-LABEL: @test_fail2(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[SWITCH:%.*]] = icmp eq i64 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[SWITCH]], i64 2, i64 [[X]]
|
||||
; CHECK-NEXT: ret i64 [[SPEC_SELECT]]
|
||||
; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i64 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP]], i64 2, i64 1
|
||||
; CHECK-NEXT: ret i64 [[SWITCH_SELECT]]
|
||||
;
|
||||
entry:
|
||||
switch i64 %x, label %bb2 [
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp -S | FileCheck %s
|
||||
|
||||
; Check that simplifycfg deletes a dead 'seteq' instruction when it
|
||||
; folds a conditional branch into a switch instruction.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; Test merging of blocks with phi nodes.
|
||||
;
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp -S | FileCheck %s
|
||||
;
|
||||
|
||||
; ModuleID = '<stdin>'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
|
||||
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp < %s | FileCheck %s
|
||||
|
||||
define void @widget(i32 %arg) {
|
||||
; CHECK-LABEL: @widget(
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -forward-switch-cond=false -S | FileCheck %s --check-prefix=NO_FWD
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -forward-switch-cond=true -S | FileCheck %s --check-prefix=FWD
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -forward-switch-cond=false -switch-range-to-icmp -S | FileCheck %s --check-prefix=NO_FWD
|
||||
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -forward-switch-cond=true -switch-range-to-icmp -S | FileCheck %s --check-prefix=FWD
|
||||
|
||||
; RUN: opt < %s -passes='simplifycfg<no-forward-switch-cond>' -S | FileCheck %s --check-prefix=NO_FWD
|
||||
; RUN: opt < %s -passes='simplifycfg<forward-switch-cond>' -S | FileCheck %s --check-prefix=FWD
|
||||
; RUN: opt < %s -passes='simplifycfg<no-forward-switch-cond;switch-range-to-icmp>' -S | FileCheck %s --check-prefix=NO_FWD
|
||||
; RUN: opt < %s -passes='simplifycfg<forward-switch-cond;switch-range-to-icmp>' -S | FileCheck %s --check-prefix=FWD
|
||||
|
||||
; PR10131
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
|
||||
; RUN: opt -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S -o - < %s | FileCheck %s
|
||||
; RUN: opt -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp -S -o - < %s | FileCheck %s
|
||||
|
||||
declare void @helper(i32)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt %s -S -passes='simplifycfg<switch-to-lookup>' -simplifycfg-require-and-preserve-domtree=1 | FileCheck %s
|
||||
; RUN: opt %s -S -passes='simplifycfg<switch-to-lookup>' -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
declare void @foo(i32)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
|
||||
; RUN: opt %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp -S | FileCheck %s
|
||||
|
||||
declare i32 @f(i32)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
|
||||
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp < %s | FileCheck %s
|
||||
|
||||
define zeroext i1 @test1(i32 %x) nounwind readnone ssp noredzone {
|
||||
entry:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
|
||||
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp < %s | FileCheck %s
|
||||
target datalayout="p:40:64:64:32"
|
||||
|
||||
declare void @foo1()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
|
||||
; RUN: opt -S -data-layout="p:32:32-p1:16:16" -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck -check-prefix=CHECK -check-prefix=DL %s
|
||||
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp < %s | FileCheck %s
|
||||
; RUN: opt -S -data-layout="p:32:32-p1:16:16" -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp < %s | FileCheck -check-prefix=CHECK -check-prefix=DL %s
|
||||
|
||||
declare void @foo1()
|
||||
|
||||
|
|
Loading…
Reference in New Issue