[llvm] 498887a - [Attributor] Introduce the closed world flag

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 29 22:35:35 PDT 2023


Author: Johannes Doerfert
Date: 2023-08-29T22:35:17-07:00
New Revision: 498887ae8a354461bcff9c37b50dd407f2f1ed64

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

LOG: [Attributor] Introduce the closed world flag

The Attributor user can now set the closed world flag
(`AttributorConfig.IsClosedWorldModule` or
`-attributor-assume-closed-world`) in order to specialize call edges
based only on available callees. That means, we assume all functions are
known and hence all potential callees must be declared/defined in the
module. We will use this for GPUs and LTO cases, but for now the user
has to set it via a flag.

Added: 
    

Modified: 
    llvm/include/llvm/Transforms/IPO/Attributor.h
    llvm/lib/Transforms/IPO/Attributor.cpp
    llvm/lib/Transforms/IPO/AttributorAttributes.cpp
    llvm/test/Transforms/Attributor/callgraph.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index fd6f2e20cd952f..abcdc9318a7a21 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -1316,6 +1316,11 @@ struct InformationCache {
     return TargetTriple.isAMDGPU() || TargetTriple.isNVPTX();
   }
 
+  /// Return all functions that might be called indirectly, only valid for
+  /// closed world modules (see isClosedWorldModule).
+  const ArrayRef<Function *>
+  getIndirectlyCallableFunctions(Attributor &A) const;
+
 private:
   struct FunctionInfo {
     ~FunctionInfo();
@@ -1348,6 +1353,10 @@ struct InformationCache {
     return *FI;
   }
 
+  /// Vector of functions that might be callable indirectly, i.a., via a
+  /// function pointer.
+  SmallVector<Function *> IndirectlyCallableFunctions;
+
   /// Initialize the function information cache \p FI for the function \p F.
   ///
   /// This method needs to be called for all function that might be looked at
@@ -1413,6 +1422,10 @@ struct AttributorConfig {
   /// Flag to determine if we should skip all liveness checks early on.
   bool UseLiveness = true;
 
+  /// Flag to indicate if the entire world is contained in this module, that
+  /// is, no outside functions exist.
+  bool IsClosedWorldModule = false;
+
   /// Callback function to be invoked on internal functions marked live.
   std::function<void(Attributor &A, const Function &F)> InitializationCallback =
       nullptr;
@@ -1483,9 +1496,7 @@ struct Attributor {
   /// \param Configuration The Attributor configuration which determines what
   ///                      generic features to use.
   Attributor(SetVector<Function *> &Functions, InformationCache &InfoCache,
-             AttributorConfig Configuration)
-      : Allocator(InfoCache.Allocator), Functions(Functions),
-        InfoCache(InfoCache), Configuration(Configuration) {}
+             AttributorConfig Configuration);
 
   ~Attributor();
 
@@ -1704,6 +1715,10 @@ struct Attributor {
                : true;
   }
 
+  /// Return true if the module contains the whole world, thus, no outside
+  /// functions exist.
+  bool isClosedWorldModule() const;
+
   /// Return true if we derive attributes for \p Fn
   bool isRunOn(Function &Fn) const { return isRunOn(&Fn); }
   bool isRunOn(Function *Fn) const {

diff  --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index 69f8952e3aaca0..5c05080c3a67b2 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -175,6 +175,10 @@ static cl::opt<bool> SimplifyAllLoads("attributor-simplify-all-loads",
                                       cl::desc("Try to simplify all loads."),
                                       cl::init(true));
 
+static cl::opt<bool> CloseWorldAssumption(
+    "attributor-assume-closed-world", cl::Hidden,
+    cl::desc("Should a closed world be assumed, or not. Default if not set."));
+
 /// Logic operators for the change status enum class.
 ///
 ///{
@@ -1057,6 +1061,21 @@ ChangeStatus AbstractAttribute::update(Attributor &A) {
   return HasChanged;
 }
 
+Attributor::Attributor(SetVector<Function *> &Functions,
+                       InformationCache &InfoCache,
+                       AttributorConfig Configuration)
+    : Allocator(InfoCache.Allocator), Functions(Functions),
+      InfoCache(InfoCache), Configuration(Configuration) {
+  if (!isClosedWorldModule())
+    return;
+  for (Function *Fn : Functions)
+    if (Fn->hasAddressTaken(/*PutOffender=*/nullptr,
+                            /*IgnoreCallbackUses=*/false,
+                            /*IgnoreAssumeLikeCalls=*/true,
+                            /*IgnoreLLVMUsed=*/true))
+      InfoCache.IndirectlyCallableFunctions.push_back(Fn);
+}
+
 bool Attributor::getAttrsFromAssumes(const IRPosition &IRP,
                                      Attribute::AttrKind AK,
                                      SmallVectorImpl<Attribute> &Attrs) {
@@ -3251,6 +3270,12 @@ InformationCache::FunctionInfo::~FunctionInfo() {
     It.getSecond()->~InstructionVectorTy();
 }
 
+const ArrayRef<Function *>
+InformationCache::getIndirectlyCallableFunctions(Attributor &A) const {
+  assert(A.isClosedWorldModule() && "Cannot see all indirect callees!");
+  return IndirectlyCallableFunctions;
+}
+
 void Attributor::recordDependence(const AbstractAttribute &FromAA,
                                   const AbstractAttribute &ToAA,
                                   DepClassTy DepClass) {
@@ -3586,6 +3611,12 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
   assert(Success && "Expected the check call to be successful!");
 }
 
+bool Attributor::isClosedWorldModule() const {
+  if (CloseWorldAssumption.getNumOccurrences())
+    return CloseWorldAssumption;
+  return isModulePass() && Configuration.IsClosedWorldModule;
+}
+
 /// Helpers to ease debugging through output streams and print calls.
 ///
 ///{

diff  --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 8bb8c60e2c4b30..ada4def7cfdb15 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -12065,11 +12065,22 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
   /// See AbstractAttribute::initialize(...).
   void initialize(Attributor &A) override {
     auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
-    if (!MD)
+    if (!MD && !A.isClosedWorldModule())
       return;
-    for (const auto &Op : MD->operands())
-      if (Function *Callee = mdconst::dyn_extract_or_null<Function>(Op))
-        PotentialCallees.insert(Callee);
+
+    if (MD) {
+      for (const auto &Op : MD->operands())
+        if (Function *Callee = mdconst::dyn_extract_or_null<Function>(Op))
+          PotentialCallees.insert(Callee);
+    } else if (A.isClosedWorldModule()) {
+      ArrayRef<Function *> IndirectlyCallableFunctions =
+          A.getInfoCache().getIndirectlyCallableFunctions(A);
+      PotentialCallees.insert(IndirectlyCallableFunctions.begin(),
+                              IndirectlyCallableFunctions.end());
+    }
+
+    if (PotentialCallees.empty())
+      indicateOptimisticFixpoint();
   }
 
   ChangeStatus updateImpl(Attributor &A) override {

diff  --git a/llvm/test/Transforms/Attributor/callgraph.ll b/llvm/test/Transforms/Attributor/callgraph.ll
index bc14ac342aeabb..272cf53ae9d8e0 100644
--- a/llvm/test/Transforms/Attributor/callgraph.ll
+++ b/llvm/test/Transforms/Attributor/callgraph.ll
@@ -1,8 +1,9 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
-; RUN: opt -passes=attributor -S < %s | FileCheck %s --check-prefixes=CHECK,UPTO2,UNLIM
+; RUN: opt -passes=attributor -S < %s | FileCheck %s --check-prefixes=CHECK,OWRDL,UPTO2,UNLIM,OUNLM
 ; RUN: opt -passes=attributor -attributor-print-call-graph -S -disable-output < %s | FileCheck %s --check-prefixes=DOT
-; RUN: opt -passes=attributor --attributor-max-specializations-per-call-base=2 -S < %s | FileCheck %s --check-prefixes=CHECK,UPTO2,LIMI2
-; RUN: opt -passes=attributor --attributor-max-specializations-per-call-base=0 -S < %s | FileCheck %s --check-prefixes=CHECK,LIMI0
+; RUN: opt -passes=attributor --attributor-max-specializations-per-call-base=2 -S < %s | FileCheck %s --check-prefixes=CHECK,OWRDL,UPTO2,LIMI2
+; RUN: opt -passes=attributor --attributor-max-specializations-per-call-base=0 -S < %s | FileCheck %s --check-prefixes=CHECK,OWRDL,LIMI0
+; RUN: opt -passes=attributor --attributor-assume-closed-world -S < %s | FileCheck %s --check-prefixes=CHECK,UPTO2,UNLIM,CWRLD
 
 define dso_local void @func1() {
 ; CHECK-LABEL: @func1(
@@ -224,32 +225,32 @@ define i32 @non_matching_fp1_noundef(i1 %c1, i1 %c2, i1 %c) {
 }
 
 define void @non_matching_fp2(i1 %c1, i1 %c2, i1 %c, ptr %unknown) {
-; UNLIM-LABEL: @non_matching_fp2(
-; UNLIM-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
-; UNLIM-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]]
-; UNLIM-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
-; UNLIM-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
-; UNLIM-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
-; UNLIM:       2:
-; UNLIM-NEXT:    call void @takeI32()
-; UNLIM-NEXT:    br label [[TMP10:%.*]]
-; UNLIM:       3:
-; UNLIM-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
-; UNLIM-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
-; UNLIM:       5:
-; UNLIM-NEXT:    call void @retI32()
-; UNLIM-NEXT:    br label [[TMP10]]
-; UNLIM:       6:
-; UNLIM-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloat
-; UNLIM-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
-; UNLIM:       8:
-; UNLIM-NEXT:    call void @retFloatTakeFloat()
-; UNLIM-NEXT:    br label [[TMP10]]
-; UNLIM:       9:
-; UNLIM-NEXT:    call void [[FP]]()
-; UNLIM-NEXT:    br label [[TMP10]]
-; UNLIM:       10:
-; UNLIM-NEXT:    ret void
+; OUNLM-LABEL: @non_matching_fp2(
+; OUNLM-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
+; OUNLM-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]]
+; OUNLM-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
+; OUNLM-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
+; OUNLM-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
+; OUNLM:       2:
+; OUNLM-NEXT:    call void @takeI32()
+; OUNLM-NEXT:    br label [[TMP10:%.*]]
+; OUNLM:       3:
+; OUNLM-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
+; OUNLM-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
+; OUNLM:       5:
+; OUNLM-NEXT:    call void @retI32()
+; OUNLM-NEXT:    br label [[TMP10]]
+; OUNLM:       6:
+; OUNLM-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloat
+; OUNLM-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
+; OUNLM:       8:
+; OUNLM-NEXT:    call void @retFloatTakeFloat()
+; OUNLM-NEXT:    br label [[TMP10]]
+; OUNLM:       9:
+; OUNLM-NEXT:    call void [[FP]]()
+; OUNLM-NEXT:    br label [[TMP10]]
+; OUNLM:       10:
+; OUNLM-NEXT:    ret void
 ;
 ; LIMI2-LABEL: @non_matching_fp2(
 ; LIMI2-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
@@ -278,6 +279,55 @@ define void @non_matching_fp2(i1 %c1, i1 %c2, i1 %c, ptr %unknown) {
 ; LIMI0-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
 ; LIMI0-NEXT:    call void [[FP]]()
 ; LIMI0-NEXT:    ret void
+;
+; CWRLD-LABEL: @non_matching_fp2(
+; CWRLD-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
+; CWRLD-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]]
+; CWRLD-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
+; CWRLD-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
+; CWRLD-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
+; CWRLD:       2:
+; CWRLD-NEXT:    call void @takeI32()
+; CWRLD-NEXT:    br label [[TMP21:%.*]]
+; CWRLD:       3:
+; CWRLD-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
+; CWRLD-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
+; CWRLD:       5:
+; CWRLD-NEXT:    call void @retI32()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       6:
+; CWRLD-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP]], @func3
+; CWRLD-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
+; CWRLD:       8:
+; CWRLD-NEXT:    call void @func3()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       9:
+; CWRLD-NEXT:    [[TMP10:%.*]] = icmp eq ptr [[FP]], @func4
+; CWRLD-NEXT:    br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP12:%.*]]
+; CWRLD:       11:
+; CWRLD-NEXT:    call void @func4()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       12:
+; CWRLD-NEXT:    [[TMP13:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloat
+; CWRLD-NEXT:    br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP15:%.*]]
+; CWRLD:       14:
+; CWRLD-NEXT:    call void @retFloatTakeFloat()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       15:
+; CWRLD-NEXT:    [[TMP16:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloatFloatNoundef
+; CWRLD-NEXT:    br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP18:%.*]]
+; CWRLD:       17:
+; CWRLD-NEXT:    call void @retFloatTakeFloatFloatNoundef()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       18:
+; CWRLD-NEXT:    br i1 true, label [[TMP19:%.*]], label [[TMP20:%.*]]
+; CWRLD:       19:
+; CWRLD-NEXT:    call void @void()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       20:
+; CWRLD-NEXT:    unreachable
+; CWRLD:       21:
+; CWRLD-NEXT:    ret void
 ;
   %fp1 = select i1 %c1, ptr @retI32, ptr @takeI32
   %fp2 = select i1 %c2, ptr @retFloatTakeFloat, ptr %unknown
@@ -287,24 +337,88 @@ define void @non_matching_fp2(i1 %c1, i1 %c2, i1 %c, ptr %unknown) {
 }
 
 define i32 @non_matching_unknown(i1 %c, ptr %fn) {
-; UPTO2-LABEL: @non_matching_unknown(
-; UPTO2-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]]
-; UPTO2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @retI32
-; UPTO2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
-; UPTO2:       2:
-; UPTO2-NEXT:    [[CALL1:%.*]] = call i32 @retI32(i32 42)
-; UPTO2-NEXT:    br label [[TMP4:%.*]]
-; UPTO2:       3:
-; UPTO2-NEXT:    [[CALL2:%.*]] = call i32 [[FP]](i32 42)
-; UPTO2-NEXT:    br label [[TMP4]]
-; UPTO2:       4:
-; UPTO2-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP3]] ]
-; UPTO2-NEXT:    ret i32 [[CALL_PHI]]
+; OUNLM-LABEL: @non_matching_unknown(
+; OUNLM-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]]
+; OUNLM-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @retI32
+; OUNLM-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
+; OUNLM:       2:
+; OUNLM-NEXT:    [[CALL1:%.*]] = call i32 @retI32(i32 42)
+; OUNLM-NEXT:    br label [[TMP4:%.*]]
+; OUNLM:       3:
+; OUNLM-NEXT:    [[CALL2:%.*]] = call i32 [[FP]](i32 42)
+; OUNLM-NEXT:    br label [[TMP4]]
+; OUNLM:       4:
+; OUNLM-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP3]] ]
+; OUNLM-NEXT:    ret i32 [[CALL_PHI]]
+;
+; LIMI2-LABEL: @non_matching_unknown(
+; LIMI2-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]]
+; LIMI2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @retI32
+; LIMI2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
+; LIMI2:       2:
+; LIMI2-NEXT:    [[CALL1:%.*]] = call i32 @retI32(i32 42)
+; LIMI2-NEXT:    br label [[TMP4:%.*]]
+; LIMI2:       3:
+; LIMI2-NEXT:    [[CALL2:%.*]] = call i32 [[FP]](i32 42)
+; LIMI2-NEXT:    br label [[TMP4]]
+; LIMI2:       4:
+; LIMI2-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP3]] ]
+; LIMI2-NEXT:    ret i32 [[CALL_PHI]]
 ;
 ; LIMI0-LABEL: @non_matching_unknown(
 ; LIMI0-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]]
 ; LIMI0-NEXT:    [[CALL:%.*]] = call i32 [[FP]](i32 42)
 ; LIMI0-NEXT:    ret i32 [[CALL]]
+;
+; CWRLD-LABEL: @non_matching_unknown(
+; CWRLD-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]]
+; CWRLD-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @func3
+; CWRLD-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
+; CWRLD:       2:
+; CWRLD-NEXT:    [[CALL1:%.*]] = call i32 @func3(i32 42)
+; CWRLD-NEXT:    br label [[TMP24:%.*]]
+; CWRLD:       3:
+; CWRLD-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @func4
+; CWRLD-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
+; CWRLD:       5:
+; CWRLD-NEXT:    [[CALL2:%.*]] = call i32 @func4(i32 42)
+; CWRLD-NEXT:    br label [[TMP24]]
+; CWRLD:       6:
+; CWRLD-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP]], @retI32
+; CWRLD-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
+; CWRLD:       8:
+; CWRLD-NEXT:    [[CALL3:%.*]] = call i32 @retI32(i32 42)
+; CWRLD-NEXT:    br label [[TMP24]]
+; CWRLD:       9:
+; CWRLD-NEXT:    [[TMP10:%.*]] = icmp eq ptr [[FP]], @takeI32
+; CWRLD-NEXT:    br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP12:%.*]]
+; CWRLD:       11:
+; CWRLD-NEXT:    [[CALL4:%.*]] = call i32 @takeI32(i32 42)
+; CWRLD-NEXT:    br label [[TMP24]]
+; CWRLD:       12:
+; CWRLD-NEXT:    [[TMP13:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloat
+; CWRLD-NEXT:    br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP18:%.*]]
+; CWRLD:       14:
+; CWRLD-NEXT:    [[TMP15:%.*]] = bitcast i32 42 to float
+; CWRLD-NEXT:    [[TMP16:%.*]] = call float @retFloatTakeFloat(float [[TMP15]])
+; CWRLD-NEXT:    [[TMP17:%.*]] = bitcast float [[TMP16]] to i32
+; CWRLD-NEXT:    br label [[TMP24]]
+; CWRLD:       18:
+; CWRLD-NEXT:    [[TMP19:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloatFloatNoundef
+; CWRLD-NEXT:    br i1 [[TMP19]], label [[TMP20:%.*]], label [[TMP21:%.*]]
+; CWRLD:       20:
+; CWRLD-NEXT:    [[CALL5:%.*]] = call i32 @retFloatTakeFloatFloatNoundef(i32 42)
+; CWRLD-NEXT:    br label [[TMP24]]
+; CWRLD:       21:
+; CWRLD-NEXT:    br i1 true, label [[TMP22:%.*]], label [[TMP23:%.*]]
+; CWRLD:       22:
+; CWRLD-NEXT:    [[CALL6:%.*]] = call i32 @void(i32 42)
+; CWRLD-NEXT:    br label [[TMP24]]
+; CWRLD:       23:
+; CWRLD-NEXT:    unreachable
+; CWRLD:       24:
+; CWRLD-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP8]] ], [ [[CALL4]], [[TMP11]] ], [ [[TMP17]], [[TMP14]] ], [ [[CALL5]], [[TMP20]] ], [ [[CALL6]], [[TMP22]] ]
+; CWRLD-NEXT:    ret i32 [[CALL_PHI]]
 ;
   %fp = select i1 %c, ptr @retI32, ptr %fn
   %call = call i32 %fp(i32 42)
@@ -312,9 +426,55 @@ define i32 @non_matching_unknown(i1 %c, ptr %fn) {
 }
 
 define void @broker(ptr %unknown) !callback !0 {
-; CHECK-LABEL: @broker(
-; CHECK-NEXT:    call void [[UNKNOWN:%.*]]()
-; CHECK-NEXT:    ret void
+; OWRDL-LABEL: @broker(
+; OWRDL-NEXT:    call void [[UNKNOWN:%.*]]()
+; OWRDL-NEXT:    ret void
+;
+; CWRLD-LABEL: @broker(
+; CWRLD-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[UNKNOWN:%.*]], @func3
+; CWRLD-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
+; CWRLD:       2:
+; CWRLD-NEXT:    call void @func3()
+; CWRLD-NEXT:    br label [[TMP21:%.*]]
+; CWRLD:       3:
+; CWRLD-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[UNKNOWN]], @func4
+; CWRLD-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
+; CWRLD:       5:
+; CWRLD-NEXT:    call void @func4()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       6:
+; CWRLD-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[UNKNOWN]], @retI32
+; CWRLD-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
+; CWRLD:       8:
+; CWRLD-NEXT:    call void @retI32()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       9:
+; CWRLD-NEXT:    [[TMP10:%.*]] = icmp eq ptr [[UNKNOWN]], @takeI32
+; CWRLD-NEXT:    br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP12:%.*]]
+; CWRLD:       11:
+; CWRLD-NEXT:    call void @takeI32()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       12:
+; CWRLD-NEXT:    [[TMP13:%.*]] = icmp eq ptr [[UNKNOWN]], @retFloatTakeFloat
+; CWRLD-NEXT:    br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP15:%.*]]
+; CWRLD:       14:
+; CWRLD-NEXT:    call void @retFloatTakeFloat()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       15:
+; CWRLD-NEXT:    [[TMP16:%.*]] = icmp eq ptr [[UNKNOWN]], @retFloatTakeFloatFloatNoundef
+; CWRLD-NEXT:    br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP18:%.*]]
+; CWRLD:       17:
+; CWRLD-NEXT:    call void @retFloatTakeFloatFloatNoundef()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       18:
+; CWRLD-NEXT:    br i1 true, label [[TMP19:%.*]], label [[TMP20:%.*]]
+; CWRLD:       19:
+; CWRLD-NEXT:    call void @void()
+; CWRLD-NEXT:    br label [[TMP21]]
+; CWRLD:       20:
+; CWRLD-NEXT:    unreachable
+; CWRLD:       21:
+; CWRLD-NEXT:    ret void
 ;
   call void %unknown()
   ret void


        


More information about the llvm-commits mailing list