[PATCH] D17288: [CodeGenPrepare] Do select to branch transform when cmp's operand is expensive.

Junmo Park via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 16 02:05:50 PST 2016


flyingforyou created this revision.
flyingforyou added a reviewer: spatel.
flyingforyou added subscribers: llvm-commits, JongwonLee, evandro.

Emit "cmov on compare with a expensive operand" as a branch to avoid stalls on executing expensive instruction likes division.

http://reviews.llvm.org/D17288

Files:
  lib/CodeGen/CodeGenPrepare.cpp
  test/Transforms/CodeGenPrepare/X86/select.ll

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
+}
Index: lib/CodeGen/CodeGenPrepare.cpp
===================================================================
--- lib/CodeGen/CodeGenPrepare.cpp
+++ lib/CodeGen/CodeGenPrepare.cpp
@@ -4468,16 +4468,31 @@
   // case currently.
 
   CmpInst *Cmp = dyn_cast<CmpInst>(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<Instruction>(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


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D17288.48055.patch
Type: text/x-patch
Size: 2250 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160216/c06413d5/attachment.bin>


More information about the llvm-commits mailing list