diff --git a/llvm/lib/Target/X86/X86CmovConversion.cpp b/llvm/lib/Target/X86/X86CmovConversion.cpp --- a/llvm/lib/Target/X86/X86CmovConversion.cpp +++ b/llvm/lib/Target/X86/X86CmovConversion.cpp @@ -97,6 +97,11 @@ cl::desc("Convert cmovs to branches whenever they have memory operands."), cl::init(true), cl::Hidden); +static cl::opt ForceAll( + "x86-cmov-converter-force-all", + cl::desc("Convert all cmovs to branches."), + cl::init(false), cl::Hidden); + namespace { /// Converts X86 cmov instructions into branches when profitable. @@ -174,11 +179,11 @@ TSchedModel.init(&STI); // Before we handle the more subtle cases of register-register CMOVs inside - // of potentially hot loops, we want to quickly remove all CMOVs with - // a memory operand. The CMOV will risk a stall waiting for the load to - // complete that speculative execution behind a branch is better suited to - // handle on modern x86 chips. - if (ForceMemOperand) { + // of potentially hot loops, we want to quickly remove all CMOVs (ForceAll) or + // the ones with a memory operand (ForceMemOperand option). The latter CMOV + // will risk a stall waiting for the load to complete that speculative + // execution behind a branch is better suited to handle on modern x86 chips. + if (ForceMemOperand || ForceAll) { CmovGroups AllCmovGroups; SmallVector Blocks; for (auto &MBB : MF) @@ -186,7 +191,8 @@ if (collectCmovCandidates(Blocks, AllCmovGroups, /*IncludeLoads*/ true)) { for (auto &Group : AllCmovGroups) { // Skip any group that doesn't do at least one memory operand cmov. - if (llvm::none_of(Group, [&](MachineInstr *I) { return I->mayLoad(); })) + if (ForceMemOperand && + llvm::none_of(Group, [&](MachineInstr *I) { return I->mayLoad(); })) continue; // For CMOV groups which we can rewrite and which contain a memory load,