[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