[llvm] d16d820 - [SimplifyCFG] Try 2: sink all-indirect indirect calls

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 28 09:09:13 PDT 2021


Author: Roman Lebedev
Date: 2021-04-28T19:08:54+03:00
New Revision: d16d820c2e6400aa2242efcedbfa824fbfa2fc09

URL: https://github.com/llvm/llvm-project/commit/d16d820c2e6400aa2242efcedbfa824fbfa2fc09
DIFF: https://github.com/llvm/llvm-project/commit/d16d820c2e6400aa2242efcedbfa824fbfa2fc09.diff

LOG: [SimplifyCFG] Try 2: sink all-indirect indirect calls

Note that we don't want to turn a partially-direct call
into an indirect one, that will break ICP amongst other things.

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/SimplifyCFG.cpp
    llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 16e69c0b0d0e..3bf5463efe16 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -1733,6 +1733,32 @@ static bool canSinkInstructions(
       }))
     return false;
 
+  // For calls to be sinkable, they must all be indirect, or have same callee.
+  // I.e. if we have two direct calls to 
diff erent callees, we don't want to
+  // turn that into an indirect call. Likewise, if we have an indirect call,
+  // and a direct call, we don't actually want to have a single indirect call.
+  if (isa<CallBase>(I0)) {
+    auto IsIndirectCall = [](const Instruction *I) {
+      return cast<CallBase>(I)->isIndirectCall();
+    };
+    bool HaveIndirectCalls = any_of(Insts, IsIndirectCall);
+    bool AllCallsAreIndirect = all_of(Insts, IsIndirectCall);
+    if (HaveIndirectCalls) {
+      if (!AllCallsAreIndirect)
+        return false;
+    } else {
+      // All callees must be identical.
+      Value *Callee = nullptr;
+      for (const Instruction *I : Insts) {
+        Value *CurrCallee = cast<CallBase>(I)->getCalledOperand();
+        if (!Callee)
+          Callee = CurrCallee;
+        else if (Callee != CurrCallee)
+          return false;
+      }
+    }
+  }
+
   for (unsigned OI = 0, OE = I0->getNumOperands(); OI != OE; ++OI) {
     Value *Op = I0->getOperand(OI);
     if (Op->getType()->isTokenTy())
@@ -1748,11 +1774,6 @@ static bool canSinkInstructions(
           !canReplaceOperandWithVariable(I0, OI))
         // We can't create a PHI from this GEP.
         return false;
-      // Don't create indirect calls! The called value is the final operand.
-      if (isa<CallBase>(I0) && OI == OE - 1) {
-        // FIXME: if the call was *already* indirect, we should do this.
-        return false;
-      }
       for (auto *I : Insts)
         PHIOperands[I].push_back(I->getOperand(OI));
     }

diff  --git a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
index 84b7f75ab038..5c7f5d07ef0b 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
@@ -1409,14 +1409,9 @@ end:
 
 define void @indirect_caller(i1 %c, i32 %v, void (i32)* %foo, void (i32)* %bar) {
 ; CHECK-LABEL: @indirect_caller(
-; CHECK-NEXT:    br i1 [[C:%.*]], label [[CALL_FOO:%.*]], label [[CALL_BAR:%.*]]
-; CHECK:       call_foo:
-; CHECK-NEXT:    tail call void [[FOO:%.*]](i32 [[V:%.*]])
-; CHECK-NEXT:    br label [[END:%.*]]
-; CHECK:       call_bar:
-; CHECK-NEXT:    tail call void [[BAR:%.*]](i32 [[V]])
-; CHECK-NEXT:    br label [[END]]
-; CHECK:       end:
+; CHECK-NEXT:  end:
+; CHECK-NEXT:    [[BAR_SINK:%.*]] = select i1 [[C:%.*]], void (i32)* [[FOO:%.*]], void (i32)* [[BAR:%.*]]
+; CHECK-NEXT:    tail call void [[BAR_SINK]](i32 [[V:%.*]])
 ; CHECK-NEXT:    ret void
 ;
   br i1 %c, label %call_foo, label %call_bar


        


More information about the llvm-commits mailing list