[llvm] [Attributor][NFC] Use poison for the placeholder callee in callgraph.ll (PR #217082)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 18 10:01:54 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Larry Meadows (lfmeadow)

<details>
<summary>Changes</summary>

Stacked on #<!-- -->217077 and #<!-- -->217079, which regenerate this file; only the last commit belongs to this PR.

`@<!-- -->undef_in_callees` checks that a `!callees` list naming something that is not a function does not crash the pass. The callee, its arguments and the entry in the metadata are all placeholders standing for "not a function", which `poison` says as well as `undef` does.

`PoisonValue` is a `UndefValue`, so the pass cannot tell the difference: regenerating after the swap gives a file identical token for token, which is also why this is worth doing — it moves a test off `undef` at no cost.

```llvm
-  call void undef(ptr undef, i32 undef, ptr undef), !callees !3
+  call void poison(ptr poison, i32 poison, ptr poison), !callees !3
-!3 = distinct !{ptr undef, ptr null}
+!3 = distinct !{ptr poison, ptr null}
```

cc @<!-- -->jdoerfert @<!-- -->nikic

Made with [Cursor](https://cursor.com)

---

Patch is 43.49 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/217082.diff


5 Files Affected:

- (modified) llvm/lib/Transforms/IPO/AttributorAttributes.cpp (+70-27) 
- (modified) llvm/test/Transforms/Attributor/callgraph.ll (+85-330) 
- (added) llvm/test/Transforms/Attributor/indirect_call_cycle.ll (+134) 
- (added) llvm/test/Transforms/Attributor/indirect_call_signature_mismatch.ll (+57) 
- (modified) llvm/test/Transforms/Attributor/nounwind.ll (+49-48) 


``````````diff
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 050bc32355253..1d43a479599a1 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -12495,11 +12495,51 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
       AllCalleesKnownNow = false;
     }
 
+    // A direct call to a callee that can reach the function holding this call
+    // site closes a call graph cycle that previously existed only through the
+    // function pointer, and nothing downstream undoes that: an alwaysinline
+    // dispatcher stops being inlinable once it is in a cycle, and on a target
+    // without a dynamically sized stack the recursion it leaves behind has no
+    // statically known stack size. Record which callees those are so manifest()
+    // can leave them to the indirect call. The question has to be asked here,
+    // because the solver no longer answers once manifestation starts.
+    //
+    // Only edges the call graph agrees are direct can close such a cycle, so
+    // walk the solver's known edges rather than asking AAInterFnReachability,
+    // which conservatively reaches everything downstream of an unknown callee
+    // and would suppress far more than this.
+    SmallPtrSet<Function *, 4> CalleesReachingCallerNow;
+    if (Function *Caller = CB->getFunction()) {
+      auto KnownEdgesReach = [&](Function *From) {
+        SmallPtrSet<Function *, 16> Visited;
+        SmallVector<Function *, 16> Worklist = {From};
+        while (!Worklist.empty()) {
+          Function *Fn = Worklist.pop_back_val();
+          if (Fn == Caller)
+            return true;
+          if (!Visited.insert(Fn).second)
+            continue;
+          const auto *EdgesAA = A.getAAFor<AACallEdges>(
+              *this, IRPosition::function(*Fn), DepClassTy::REQUIRED);
+          if (!EdgesAA)
+            continue;
+          for (Function *Next : EdgesAA->getOptimisticEdges())
+            Worklist.push_back(Next);
+        }
+        return false;
+      };
+      for (Function *Callee : AssumedCalleesNow)
+        if (Callee == Caller || KnownEdgesReach(Callee))
+          CalleesReachingCallerNow.insert(Callee);
+    }
+
     if (AssumedCalleesNow == AssumedCallees &&
-        AllCalleesKnown == AllCalleesKnownNow)
+        AllCalleesKnown == AllCalleesKnownNow &&
+        CalleesReachingCallerNow == CalleesReachingCaller)
       return ChangeStatus::UNCHANGED;
 
     std::swap(AssumedCallees, AssumedCalleesNow);
+    std::swap(CalleesReachingCaller, CalleesReachingCallerNow);
     AllCalleesKnown = AllCalleesKnownNow;
     return ChangeStatus::CHANGED;
   }
@@ -12524,8 +12564,6 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
 
     bool CBIsVoid = CB->getType()->isVoidTy();
     BasicBlock::iterator IP = CB->getIterator();
-    FunctionType *CSFT = CB->getFunctionType();
-    SmallVector<Value *> CSArgs(CB->args());
 
     // If we know all callees and there are none, the call site is (effectively)
     // dead (or UB).
@@ -12536,20 +12574,18 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
       return ChangeStatus::CHANGED;
     }
 
+    // Callees that can reach the function holding this call site were recorded
+    // during the update; see there for why they are left to the indirect call.
+    auto ReachesCaller = [&](Function *Callee) {
+      return CalleesReachingCaller.contains(Callee);
+    };
+
     // Special handling for the single callee case.
-    if (AllCalleesKnown && AssumedCallees.size() == 1) {
-      auto *NewCallee = AssumedCallees.front();
-      if (isLegalToPromote(*CB, NewCallee)) {
-        promoteCall(*CB, NewCallee, nullptr);
-        NumIndirectCallsPromoted++;
-        return ChangeStatus::CHANGED;
-      }
-      Instruction *NewCall =
-          CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
-                           CB->getName(), CB->getIterator());
-      if (!CBIsVoid)
-        A.changeAfterManifest(IRPosition::callsite_returned(*CB), *NewCall);
-      A.deleteAfterManifest(*CB);
+    if (AllCalleesKnown && AssumedCallees.size() == 1 &&
+        isLegalToPromote(*CB, AssumedCallees.front()) &&
+        !ReachesCaller(AssumedCallees.front())) {
+      promoteCall(*CB, AssumedCallees.front(), nullptr);
+      NumIndirectCallsPromoted++;
       return ChangeStatus::CHANGED;
     }
 
@@ -12566,7 +12602,13 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
     SmallVector<Function *, 8> SkippedAssumedCallees;
     SmallVector<std::pair<CallInst *, Instruction *>> NewCalls;
     for (Function *NewCallee : AssumedCallees) {
-      if (!A.shouldSpecializeCallSiteForCallee(*this, *CB, *NewCallee,
+      // A callee the call site cannot be promoted to is one it can only reach
+      // in ways that are undefined, so a direct call built from the call site's
+      // own operands would not be the call the indirect call performs. Leave it
+      // to the indirect fallback, which the !callees metadata below still
+      // names.
+      if (!isLegalToPromote(*CB, NewCallee) || ReachesCaller(NewCallee) ||
+          !A.shouldSpecializeCallSiteForCallee(*this, *CB, *NewCallee,
                                                AssumedCallees.size())) {
         SkippedAssumedCallees.push_back(NewCallee);
         SpecializedForAllCallees = false;
@@ -12593,16 +12635,11 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
         ThenTI->replaceUsesOfWith(ElseBB, CBBB);
       }
       CastInst *RetBC = nullptr;
-      CallInst *NewCall = nullptr;
-      if (isLegalToPromote(*CB, NewCallee)) {
-        auto *CBClone = cast<CallBase>(CB->clone());
-        CBClone->insertBefore(ThenTI->getIterator());
-        NewCall = &cast<CallInst>(promoteCall(*CBClone, NewCallee, &RetBC));
-        NumIndirectCallsPromoted++;
-      } else {
-        NewCall = CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
-                                   CB->getName(), ThenTI->getIterator());
-      }
+      auto *CBClone = cast<CallBase>(CB->clone());
+      CBClone->insertBefore(ThenTI->getIterator());
+      CallInst *NewCall =
+          &cast<CallInst>(promoteCall(*CBClone, NewCallee, &RetBC));
+      NumIndirectCallsPromoted++;
       NewCalls.push_back({NewCall, RetBC});
     }
 
@@ -12691,6 +12728,12 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
   /// time.
   SmallSetVector<Function *, 4> AssumedCallees;
 
+  /// The subset of the assumed callees that can reach the function holding this
+  /// call site, so that specializing for them would make a call graph cycle
+  /// explicit. Determined during the update, where reachability can still be
+  /// queried, and only read when manifesting.
+  SmallPtrSet<Function *, 4> CalleesReachingCaller;
+
   /// Flag to indicate if all possible callees are in the AssumedCallees set or
   /// if there could be others.
   bool AllCalleesKnown = true;
diff --git a/llvm/test/Transforms/Attributor/callgraph.ll b/llvm/test/Transforms/Attributor/callgraph.ll
index 84e2c54bd832d..ace71ed23e7d8 100644
--- a/llvm/test/Transforms/Attributor/callgraph.ll
+++ b/llvm/test/Transforms/Attributor/callgraph.ll
@@ -128,61 +128,23 @@ declare float @retFloatTakeFloatFloatNoundef(float, float noundef)
 declare void @void()
 
 define i32 @non_matching_fp1(i1 %c1, i1 %c2, i1 %c) {
-; UNLIM-LABEL: @non_matching_fp1(
-; UNLIM-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
-; UNLIM-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr @void
-; 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:    [[CALL1:%.*]] = call i32 @takeI32(i32 42)
-; UNLIM-NEXT:    br label [[TMP15:%.*]]
-; UNLIM:       3:
-; UNLIM-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
-; UNLIM-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
-; UNLIM:       5:
-; UNLIM-NEXT:    [[CALL2:%.*]] = call i32 @retI32(i32 42)
-; UNLIM-NEXT:    br label [[TMP15]]
-; UNLIM:       6:
-; UNLIM-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP]], @void
-; UNLIM-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
-; UNLIM:       8:
-; UNLIM-NEXT:    [[CALL3:%.*]] = call i32 @void(i32 42)
-; UNLIM-NEXT:    br label [[TMP15]]
-; UNLIM:       9:
-; UNLIM-NEXT:    br i1 true, label [[TMP10:%.*]], label [[TMP14:%.*]]
-; UNLIM:       10:
-; UNLIM-NEXT:    [[TMP11:%.*]] = bitcast i32 42 to float
-; UNLIM-NEXT:    [[TMP12:%.*]] = call float @retFloatTakeFloat(float [[TMP11]])
-; UNLIM-NEXT:    [[TMP13:%.*]] = bitcast float [[TMP12]] to i32
-; UNLIM-NEXT:    br label [[TMP15]]
-; UNLIM:       14:
-; UNLIM-NEXT:    unreachable
-; UNLIM:       15:
-; UNLIM-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP8]] ], [ [[TMP13]], [[TMP10]] ]
-; UNLIM-NEXT:    ret i32 [[CALL_PHI]]
-;
-; LIMI2-LABEL: @non_matching_fp1(
-; LIMI2-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
-; LIMI2-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr @void
-; LIMI2-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
-; LIMI2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
-; LIMI2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
-; LIMI2:       2:
-; LIMI2-NEXT:    [[CALL1:%.*]] = call i32 @takeI32(i32 42)
-; LIMI2-NEXT:    br label [[TMP7:%.*]]
-; LIMI2:       3:
-; LIMI2-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
-; LIMI2-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
-; LIMI2:       5:
-; LIMI2-NEXT:    [[CALL2:%.*]] = call i32 @retI32(i32 42)
-; LIMI2-NEXT:    br label [[TMP7]]
-; LIMI2:       6:
-; LIMI2-NEXT:    [[CALL3:%.*]] = call i32 [[FP]](i32 42), !callees [[META0:![0-9]+]]
-; LIMI2-NEXT:    br label [[TMP7]]
-; LIMI2:       7:
-; LIMI2-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP6]] ]
-; LIMI2-NEXT:    ret i32 [[CALL_PHI]]
+; UPTO2-LABEL: @non_matching_fp1(
+; UPTO2-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
+; UPTO2-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr @void
+; UPTO2-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
+; UPTO2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloat
+; UPTO2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP6:%.*]]
+; UPTO2:       2:
+; UPTO2-NEXT:    [[TMP3:%.*]] = bitcast i32 42 to float
+; UPTO2-NEXT:    [[TMP4:%.*]] = call float @retFloatTakeFloat(float [[TMP3]])
+; UPTO2-NEXT:    [[TMP5:%.*]] = bitcast float [[TMP4]] to i32
+; UPTO2-NEXT:    br label [[TMP7:%.*]]
+; UPTO2:       6:
+; UPTO2-NEXT:    [[CALL1:%.*]] = call i32 [[FP]](i32 42), !callees [[META0:![0-9]+]]
+; UPTO2-NEXT:    br label [[TMP7]]
+; UPTO2:       7:
+; UPTO2-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[TMP5]], [[TMP2]] ], [ [[CALL1]], [[TMP6]] ]
+; UPTO2-NEXT:    ret i32 [[CALL_PHI]]
 ;
 ; LIMI0-LABEL: @non_matching_fp1(
 ; LIMI0-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
@@ -199,53 +161,12 @@ define i32 @non_matching_fp1(i1 %c1, i1 %c2, i1 %c) {
 }
 
 define i32 @non_matching_fp1_noundef(i1 %c1, i1 %c2, i1 %c) {
-; UNLIM-LABEL: @non_matching_fp1_noundef(
-; UNLIM-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
-; UNLIM-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloatFloatNoundef, ptr @void
-; 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:    [[CALL1:%.*]] = call i32 @takeI32(i32 42)
-; UNLIM-NEXT:    br label [[TMP9:%.*]]
-; UNLIM:       3:
-; UNLIM-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
-; UNLIM-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
-; UNLIM:       5:
-; UNLIM-NEXT:    [[CALL2:%.*]] = call i32 @retI32(i32 42)
-; UNLIM-NEXT:    br label [[TMP9]]
-; UNLIM:       6:
-; UNLIM-NEXT:    br i1 true, label [[TMP7:%.*]], label [[TMP8:%.*]]
-; UNLIM:       7:
-; UNLIM-NEXT:    [[CALL3:%.*]] = call i32 @void(i32 42)
-; UNLIM-NEXT:    br label [[TMP9]]
-; UNLIM:       8:
-; UNLIM-NEXT:    unreachable
-; UNLIM:       9:
-; UNLIM-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP7]] ]
-; UNLIM-NEXT:    ret i32 [[CALL_PHI]]
-;
-; LIMI2-LABEL: @non_matching_fp1_noundef(
-; LIMI2-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
-; LIMI2-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloatFloatNoundef, ptr @void
-; LIMI2-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
-; LIMI2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
-; LIMI2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
-; LIMI2:       2:
-; LIMI2-NEXT:    [[CALL1:%.*]] = call i32 @takeI32(i32 42)
-; LIMI2-NEXT:    br label [[TMP7:%.*]]
-; LIMI2:       3:
-; LIMI2-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
-; LIMI2-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
-; LIMI2:       5:
-; LIMI2-NEXT:    [[CALL2:%.*]] = call i32 @retI32(i32 42)
-; LIMI2-NEXT:    br label [[TMP7]]
-; LIMI2:       6:
-; LIMI2-NEXT:    [[CALL3:%.*]] = call i32 [[FP]](i32 42), !callees [[META1:![0-9]+]]
-; LIMI2-NEXT:    br label [[TMP7]]
-; LIMI2:       7:
-; LIMI2-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP6]] ]
-; LIMI2-NEXT:    ret i32 [[CALL_PHI]]
+; UPTO2-LABEL: @non_matching_fp1_noundef(
+; UPTO2-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
+; UPTO2-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloatFloatNoundef, ptr @void
+; UPTO2-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
+; UPTO2-NEXT:    [[CALL:%.*]] = call i32 [[FP]](i32 42), !callees [[META0]]
+; UPTO2-NEXT:    ret i32 [[CALL]]
 ;
 ; LIMI0-LABEL: @non_matching_fp1_noundef(
 ; LIMI0-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
@@ -262,108 +183,38 @@ 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) {
-; 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
-; LIMI2-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]]
-; LIMI2-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
-; LIMI2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
-; LIMI2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
-; LIMI2:       2:
-; LIMI2-NEXT:    call void @takeI32()
-; LIMI2-NEXT:    br label [[TMP7:%.*]]
-; LIMI2:       3:
-; LIMI2-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
-; LIMI2-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
-; LIMI2:       5:
-; LIMI2-NEXT:    call void @retI32()
-; LIMI2-NEXT:    br label [[TMP7]]
-; LIMI2:       6:
-; LIMI2-NEXT:    call void [[FP]]()
-; LIMI2-NEXT:    br label [[TMP7]]
-; LIMI2:       7:
-; LIMI2-NEXT:    ret void
-;
-; LIMI0-LABEL: @non_matching_fp2(
-; LIMI0-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
-; LIMI0-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]]
-; LIMI0-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
-; LIMI0-NEXT:    call void [[FP]]()
-; LIMI0-NEXT:    ret void
+; OWRDL-LABEL: @non_matching_fp2(
+; OWRDL-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
+; OWRDL-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]]
+; OWRDL-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
+; OWRDL-NEXT:    call void [[FP]]()
+; OWRDL-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:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @func3
 ; CWRLD-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
 ; CWRLD:       2:
-; CWRLD-NEXT:    call void @takeI32()
+; CWRLD-NEXT:    call void @func3()
 ; CWRLD-NEXT:    br label [[TMP21:%.*]]
 ; CWRLD:       3:
-; CWRLD-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
+; CWRLD-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @func4
 ; CWRLD-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
 ; CWRLD:       5:
-; CWRLD-NEXT:    call void @retI32()
+; CWRLD-NEXT:    call void @func4()
 ; CWRLD-NEXT:    br label [[TMP21]]
 ; CWRLD:       6:
-; CWRLD-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP]], @func3
+; CWRLD-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP]], @void
 ; CWRLD-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
 ; CWRLD:       8:
-; CWRLD-NEXT:    call void @func3()
+; CWRLD-NEXT:    call void @void()
 ; 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:    call void [[FP]](), !callees [[META1:![0-9]+]]
 ; 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:       10:
 ; CWRLD-NEXT:    ret void
 ;
   %fp1 = select i1 %c1, ptr @retI32, ptr @takeI32
@@ -374,87 +225,25 @@ define void @non_matching_fp2(i1 %c1, i1 %c2, i1 %c, ptr %unknown) {
 }
 
 define i32 @non_matching_unknown(i1 %c, ptr %fn) {
-; 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: ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/217082


More information about the llvm-commits mailing list