Index: lib/CodeGen/CodeGenPrepare.cpp =================================================================== --- lib/CodeGen/CodeGenPrepare.cpp +++ lib/CodeGen/CodeGenPrepare.cpp @@ -4468,16 +4468,31 @@ // case currently. CmpInst *Cmp = dyn_cast(SI->getCondition()); + if (!Cmp) + return false; + + Value *CmpOp0 = Cmp->getOperand(0); + Value *CmpOp1 = Cmp->getOperand(1); + + // Emit "cmov on compare with a expensive operand" as a branch to avoid stalls + // on executing expensive instruction likes division. + auto IsExpensiveCostInst = [&](Value *V) -> bool { + auto *I = dyn_cast(V); + if (I && TTI->getUserCost(I) >= TargetTransformInfo::TCC_Expensive) + return true; + + return false; + }; + + if (IsExpensiveCostInst(CmpOp0) || IsExpensiveCostInst(CmpOp1)) + return true; // If a branch is predictable, an out-of-order CPU can avoid blocking on its // comparison condition. If the compare has more than one use, there's // probably another cmov or setcc around, so it's not worth emitting a branch. - if (!Cmp || !Cmp->hasOneUse()) + if (!Cmp->hasOneUse()) return false; - Value *CmpOp0 = Cmp->getOperand(0); - Value *CmpOp1 = Cmp->getOperand(1); - // Emit "cmov on compare with a memory operand" as a branch to avoid stalls // on a load from memory. But if the load is used more than once, do not // change the select to a branch because the load is probably needed Index: test/Transforms/CodeGenPrepare/X86/select.ll =================================================================== --- test/Transforms/CodeGenPrepare/X86/select.ll +++ test/Transforms/CodeGenPrepare/X86/select.ll @@ -139,3 +139,17 @@ ; CHECK: %sel = select i1 %cmp, i32 %div1, i32 %div2 } +; Nothing to sink here, but this gets converted to a branch to +; avoid stalling an out-of-order CPU on a predictable branch. +; Because cmp's operand is expensive instruction likes division. + +define float @fdiv_do_transform(float %a, float %b) { +entry: + %div = fdiv float %a, %b + %cmp = fcmp ogt float %div, %b + %sel = select i1 %cmp, float %div, float 8.0 + ret float %sel + +; CHECK-LABEL: @fdiv_do_transform( +; CHECK: br i1 %cmp, label %select.end, label %select.false +}