@@ -193,6 +193,7 @@ PIPE_OPERATOR(AAAssumptionInfo)
193
193
PIPE_OPERATOR (AAUnderlyingObjects)
194
194
PIPE_OPERATOR (AAAddressSpace)
195
195
PIPE_OPERATOR (AAIndirectCallInfo)
196
+ PIPE_OPERATOR (AAGlobalValueInfo)
196
197
197
198
#undef PIPE_OPERATOR
198
199
@@ -12056,6 +12057,134 @@ struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12056
12057
};
12057
12058
} // namespace
12058
12059
12060
+ // / ------------------------ Global Value Info -------------------------------
12061
+ namespace {
12062
+ struct AAGlobalValueInfoFloating : public AAGlobalValueInfo {
12063
+ AAGlobalValueInfoFloating (const IRPosition &IRP, Attributor &A)
12064
+ : AAGlobalValueInfo(IRP, A) {}
12065
+
12066
+ // / See AbstractAttribute::initialize(...).
12067
+ void initialize (Attributor &A) override {}
12068
+
12069
+ bool checkUse (Attributor &A, const Use &U, bool &Follow,
12070
+ SmallVectorImpl<const Value *> &Worklist) {
12071
+ Instruction *UInst = dyn_cast<Instruction>(U.getUser ());
12072
+ if (!UInst) {
12073
+ Follow = true ;
12074
+ return true ;
12075
+ }
12076
+
12077
+ LLVM_DEBUG (dbgs () << " [AAGlobalValueInfo] Check use: " << *U.get () << " in "
12078
+ << *UInst << " \n " );
12079
+
12080
+ if (auto *Cmp = dyn_cast<ICmpInst>(U.getUser ())) {
12081
+ int Idx = &Cmp->getOperandUse (0 ) == &U;
12082
+ if (isa<Constant>(Cmp->getOperand (Idx)))
12083
+ return true ;
12084
+ return U == &getAnchorValue ();
12085
+ }
12086
+
12087
+ // Explicitly catch return instructions.
12088
+ if (isa<ReturnInst>(UInst)) {
12089
+ auto CallSitePred = [&](AbstractCallSite ACS) {
12090
+ Worklist.push_back (ACS.getInstruction ());
12091
+ return true ;
12092
+ };
12093
+ bool UsedAssumedInformation = false ;
12094
+ // TODO: We should traverse the uses or add a "non-call-site" CB.
12095
+ if (!A.checkForAllCallSites (CallSitePred, *UInst->getFunction (),
12096
+ /* RequireAllCallSites=*/ true , this ,
12097
+ UsedAssumedInformation))
12098
+ return false ;
12099
+ return true ;
12100
+ }
12101
+
12102
+ // For now we only use special logic for call sites. However, the tracker
12103
+ // itself knows about a lot of other non-capturing cases already.
12104
+ auto *CB = dyn_cast<CallBase>(UInst);
12105
+ if (!CB)
12106
+ return false ;
12107
+ // Direct calls are OK uses.
12108
+ if (CB->isCallee (&U))
12109
+ return true ;
12110
+ // Non-argument uses are scary.
12111
+ if (!CB->isArgOperand (&U))
12112
+ return false ;
12113
+ // TODO: Iterate callees.
12114
+ auto *Fn = dyn_cast<Function>(CB->getCalledOperand ());
12115
+ if (!Fn || !A.isFunctionIPOAmendable (*Fn))
12116
+ return false ;
12117
+
12118
+ unsigned ArgNo = CB->getArgOperandNo (&U);
12119
+ Worklist.push_back (Fn->getArg (ArgNo));
12120
+ return true ;
12121
+ }
12122
+
12123
+ ChangeStatus updateImpl (Attributor &A) override {
12124
+ unsigned NumUsesBefore = Uses.size ();
12125
+
12126
+ SmallPtrSet<const Value *, 8 > Visited;
12127
+ SmallVector<const Value *> Worklist;
12128
+ Worklist.push_back (&getAnchorValue ());
12129
+
12130
+ auto UsePred = [&](const Use &U, bool &Follow) -> bool {
12131
+ Uses.insert (&U);
12132
+ switch (DetermineUseCaptureKind (U, nullptr )) {
12133
+ case UseCaptureKind::NO_CAPTURE:
12134
+ return checkUse (A, U, Follow, Worklist);
12135
+ case UseCaptureKind::MAY_CAPTURE:
12136
+ return checkUse (A, U, Follow, Worklist);
12137
+ case UseCaptureKind::PASSTHROUGH:
12138
+ Follow = true ;
12139
+ return true ;
12140
+ }
12141
+ return true ;
12142
+ };
12143
+ auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
12144
+ Uses.insert (&OldU);
12145
+ return true ;
12146
+ };
12147
+
12148
+ while (!Worklist.empty ()) {
12149
+ const Value *V = Worklist.pop_back_val ();
12150
+ if (!Visited.insert (V).second )
12151
+ continue ;
12152
+ if (!A.checkForAllUses (UsePred, *this , *V,
12153
+ /* CheckBBLivenessOnly */ true ,
12154
+ DepClassTy::OPTIONAL,
12155
+ /* IgnoreDroppableUses */ true , EquivalentUseCB)) {
12156
+ return indicatePessimisticFixpoint ();
12157
+ }
12158
+ }
12159
+
12160
+ return Uses.size () == NumUsesBefore ? ChangeStatus::UNCHANGED
12161
+ : ChangeStatus::CHANGED;
12162
+ }
12163
+
12164
+ bool isPotentialUse (const Use &U) const override {
12165
+ return !isValidState () || Uses.contains (&U);
12166
+ }
12167
+
12168
+ // / See AbstractAttribute::manifest(...).
12169
+ ChangeStatus manifest (Attributor &A) override {
12170
+ return ChangeStatus::UNCHANGED;
12171
+ }
12172
+
12173
+ // / See AbstractAttribute::getAsStr().
12174
+ const std::string getAsStr (Attributor *A) const override {
12175
+ return " [" + std::to_string (Uses.size ()) + " uses]" ;
12176
+ }
12177
+
12178
+ void trackStatistics () const override {
12179
+ STATS_DECLTRACK_FLOATING_ATTR (GlobalValuesTracked);
12180
+ }
12181
+
12182
+ private:
12183
+ // / Set of (transitive) uses of this GlobalValue.
12184
+ SmallPtrSet<const Use *, 8 > Uses;
12185
+ };
12186
+ } // namespace
12187
+
12059
12188
// / ------------------------ Indirect Call Info -------------------------------
12060
12189
namespace {
12061
12190
struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
@@ -12085,11 +12214,30 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
12085
12214
12086
12215
ChangeStatus updateImpl (Attributor &A) override {
12087
12216
CallBase *CB = cast<CallBase>(getCtxI ());
12217
+ const Use &CalleeUse = CB->getCalledOperandUse ();
12088
12218
Value *FP = CB->getCalledOperand ();
12089
12219
12090
12220
SmallSetVector<Function *, 4 > AssumedCalleesNow;
12091
12221
bool AllCalleesKnownNow = AllCalleesKnown;
12092
12222
12223
+ auto CheckPotentialCalleeUse = [&](Function &PotentialCallee,
12224
+ bool &UsedAssumedInformation) {
12225
+ const auto *GIAA = A.getAAFor <AAGlobalValueInfo>(
12226
+ *this , IRPosition::value (PotentialCallee), DepClassTy::OPTIONAL);
12227
+ if (!GIAA || GIAA->isPotentialUse (CalleeUse))
12228
+ return true ;
12229
+ UsedAssumedInformation = !GIAA->isAtFixpoint ();
12230
+ return false ;
12231
+ };
12232
+
12233
+ auto AddPotentialCallees = [&]() {
12234
+ for (auto *PotentialCallee : PotentialCallees) {
12235
+ bool UsedAssumedInformation = false ;
12236
+ if (CheckPotentialCalleeUse (*PotentialCallee, UsedAssumedInformation))
12237
+ AssumedCalleesNow.insert (PotentialCallee);
12238
+ }
12239
+ };
12240
+
12093
12241
// Use simplification to find potential callees, if !callees was present,
12094
12242
// fallback to that set if necessary.
12095
12243
bool UsedAssumedInformation = false ;
@@ -12099,7 +12247,7 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
12099
12247
UsedAssumedInformation)) {
12100
12248
if (PotentialCallees.empty ())
12101
12249
return indicatePessimisticFixpoint ();
12102
- AssumedCalleesNow. set_union (PotentialCallees );
12250
+ AddPotentialCallees ( );
12103
12251
}
12104
12252
12105
12253
// Try to find a reason for \p Fn not to be a potential callee. If none was
@@ -12112,6 +12260,13 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
12112
12260
if (CachedResult.has_value ())
12113
12261
return CachedResult.value ();
12114
12262
12263
+ bool UsedAssumedInformation = false ;
12264
+ if (!CheckPotentialCalleeUse (Fn, UsedAssumedInformation)) {
12265
+ if (!UsedAssumedInformation)
12266
+ CachedResult = false ;
12267
+ return false ;
12268
+ }
12269
+
12115
12270
int NumFnArgs = Fn.arg_size ();
12116
12271
int NumCBArgs = CB->arg_size ();
12117
12272
@@ -12147,16 +12302,12 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
12147
12302
continue ;
12148
12303
}
12149
12304
if (!PotentialCallees.empty ()) {
12150
- AssumedCalleesNow. set_union (PotentialCallees );
12305
+ AddPotentialCallees ( );
12151
12306
break ;
12152
12307
}
12153
12308
AllCalleesKnownNow = false ;
12154
12309
}
12155
12310
12156
- // If we can't specialize at all, give up now.
12157
- if (!AllCalleesKnownNow && AssumedCalleesNow.empty ())
12158
- return indicatePessimisticFixpoint ();
12159
-
12160
12311
if (AssumedCalleesNow == AssumedCallees &&
12161
12312
AllCalleesKnown == AllCalleesKnownNow)
12162
12313
return ChangeStatus::UNCHANGED;
@@ -12168,6 +12319,9 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
12168
12319
12169
12320
// / See AbstractAttribute::manifest(...).
12170
12321
ChangeStatus manifest (Attributor &A) override {
12322
+ // If we can't specialize at all, give up now.
12323
+ if (!AllCalleesKnown && AssumedCallees.empty ())
12324
+ return ChangeStatus::UNCHANGED;
12171
12325
12172
12326
ChangeStatus Changed = ChangeStatus::UNCHANGED;
12173
12327
CallBase *CB = cast<CallBase>(getCtxI ());
@@ -12550,6 +12704,7 @@ const char AAAssumptionInfo::ID = 0;
12550
12704
const char AAUnderlyingObjects::ID = 0 ;
12551
12705
const char AAAddressSpace::ID = 0 ;
12552
12706
const char AAIndirectCallInfo::ID = 0 ;
12707
+ const char AAGlobalValueInfo::ID = 0 ;
12553
12708
12554
12709
// Macro magic to create the static generator function for attributes that
12555
12710
// follow the naming scheme.
@@ -12688,6 +12843,8 @@ CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUnderlyingObjects)
12688
12843
12689
12844
CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION (IRP_CALL_SITE, CallSite,
12690
12845
AAIndirectCallInfo)
12846
+ CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION (IRP_FLOAT, Floating,
12847
+ AAGlobalValueInfo)
12691
12848
12692
12849
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION (AAHeapToStack)
12693
12850
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION (AAUndefinedBehavior)
0 commit comments