@@ -1863,12 +1863,14 @@ struct AAIsDeadImpl : public AAIsDead {
1863
1863
1864
1864
void exploreFromEntry (Attributor &A, const Function *F) {
1865
1865
ToBeExploredPaths.insert (&(F->getEntryBlock ().front ()));
1866
- assumeLive (A, F->getEntryBlock ());
1867
1866
1868
1867
for (size_t i = 0 ; i < ToBeExploredPaths.size (); ++i)
1869
1868
if (const Instruction *NextNoReturnI =
1870
1869
findNextNoReturn (A, ToBeExploredPaths[i]))
1871
1870
NoReturnCalls.insert (NextNoReturnI);
1871
+
1872
+ // Mark the block live after we looked for no-return instructions.
1873
+ assumeLive (A, F->getEntryBlock ());
1872
1874
}
1873
1875
1874
1876
// / Find the next assumed noreturn instruction in the block of \p I starting
@@ -3537,6 +3539,26 @@ bool Attributor::checkForAllReturnedValues(
3537
3539
});
3538
3540
}
3539
3541
3542
+ static bool
3543
+ checkForAllInstructionsImpl (InformationCache::OpcodeInstMapTy &OpcodeInstMap,
3544
+ const function_ref<bool (Instruction &)> &Pred,
3545
+ const AAIsDead *LivenessAA, bool &AnyDead,
3546
+ const ArrayRef<unsigned> &Opcodes) {
3547
+ for (unsigned Opcode : Opcodes) {
3548
+ for (Instruction *I : OpcodeInstMap[Opcode]) {
3549
+ // Skip dead instructions.
3550
+ if (LivenessAA && LivenessAA->isAssumedDead (I)) {
3551
+ AnyDead = true ;
3552
+ continue ;
3553
+ }
3554
+
3555
+ if (!Pred (*I))
3556
+ return false ;
3557
+ }
3558
+ }
3559
+ return true ;
3560
+ }
3561
+
3540
3562
bool Attributor::checkForAllInstructions (
3541
3563
const llvm::function_ref<bool (Instruction &)> &Pred,
3542
3564
const AbstractAttribute &QueryingAA, const ArrayRef<unsigned> &Opcodes) {
@@ -3555,18 +3577,8 @@ bool Attributor::checkForAllInstructions(
3555
3577
3556
3578
auto &OpcodeInstMap =
3557
3579
InfoCache.getOpcodeInstMapForFunction (*AssociatedFunction);
3558
- for (unsigned Opcode : Opcodes) {
3559
- for (Instruction *I : OpcodeInstMap[Opcode]) {
3560
- // Skip dead instructions.
3561
- if (LivenessAA.isAssumedDead (I)) {
3562
- AnyDead = true ;
3563
- continue ;
3564
- }
3565
-
3566
- if (!Pred (*I))
3567
- return false ;
3568
- }
3569
- }
3580
+ if (!checkForAllInstructionsImpl (OpcodeInstMap, Pred, &LivenessAA, AnyDead, Opcodes))
3581
+ return false ;
3570
3582
3571
3583
// If we actually used liveness information so we have to record a dependence.
3572
3584
if (AnyDead)
@@ -3852,6 +3864,48 @@ ChangeStatus Attributor::run(Module &M) {
3852
3864
return ManifestChange;
3853
3865
}
3854
3866
3867
+ void Attributor::initializeInformationCache (Function &F) {
3868
+
3869
+ // Walk all instructions to find interesting instructions that might be
3870
+ // queried by abstract attributes during their initialization or update.
3871
+ // This has to happen before we create attributes.
3872
+ auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap [&F];
3873
+ auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap [&F];
3874
+
3875
+ for (Instruction &I : instructions (&F)) {
3876
+ bool IsInterestingOpcode = false ;
3877
+
3878
+ // To allow easy access to all instructions in a function with a given
3879
+ // opcode we store them in the InfoCache. As not all opcodes are interesting
3880
+ // to concrete attributes we only cache the ones that are as identified in
3881
+ // the following switch.
3882
+ // Note: There are no concrete attributes now so this is initially empty.
3883
+ switch (I.getOpcode ()) {
3884
+ default :
3885
+ assert ((!ImmutableCallSite (&I)) && (!isa<CallBase>(&I)) &&
3886
+ " New call site/base instruction type needs to be known int the "
3887
+ " Attributor." );
3888
+ break ;
3889
+ case Instruction::Load:
3890
+ // The alignment of a pointer is interesting for loads.
3891
+ case Instruction::Store:
3892
+ // The alignment of a pointer is interesting for stores.
3893
+ case Instruction::Call:
3894
+ case Instruction::CallBr:
3895
+ case Instruction::Invoke:
3896
+ case Instruction::CleanupRet:
3897
+ case Instruction::CatchSwitch:
3898
+ case Instruction::Resume:
3899
+ case Instruction::Ret:
3900
+ IsInterestingOpcode = true ;
3901
+ }
3902
+ if (IsInterestingOpcode)
3903
+ InstOpcodeMap[I.getOpcode ()].push_back (&I);
3904
+ if (I.mayReadOrWriteMemory ())
3905
+ ReadOrWriteInsts.push_back (&I);
3906
+ }
3907
+ }
3908
+
3855
3909
void Attributor::identifyDefaultAbstractAttributes (Function &F) {
3856
3910
if (!VisitedFunctions.insert (&F).second )
3857
3911
return ;
@@ -3935,52 +3989,9 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
3935
3989
}
3936
3990
}
3937
3991
3938
- // Walk all instructions to find more attribute opportunities and also
3939
- // interesting instructions that might be queried by abstract attributes
3940
- // during their initialization or update.
3941
- auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap [&F];
3942
- auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap [&F];
3943
-
3944
- for (Instruction &I : instructions (&F)) {
3945
- bool IsInterestingOpcode = false ;
3946
-
3947
- // To allow easy access to all instructions in a function with a given
3948
- // opcode we store them in the InfoCache. As not all opcodes are interesting
3949
- // to concrete attributes we only cache the ones that are as identified in
3950
- // the following switch.
3951
- // Note: There are no concrete attributes now so this is initially empty.
3952
- switch (I.getOpcode ()) {
3953
- default :
3954
- assert ((!ImmutableCallSite (&I)) && (!isa<CallBase>(&I)) &&
3955
- " New call site/base instruction type needs to be known int the "
3956
- " attributor." );
3957
- break ;
3958
- case Instruction::Load:
3959
- // The alignment of a pointer is interesting for loads.
3960
- getOrCreateAAFor<AAAlign>(
3961
- IRPosition::value (*cast<LoadInst>(I).getPointerOperand ()));
3962
- break ;
3963
- case Instruction::Store:
3964
- // The alignment of a pointer is interesting for stores.
3965
- getOrCreateAAFor<AAAlign>(
3966
- IRPosition::value (*cast<StoreInst>(I).getPointerOperand ()));
3967
- break ;
3968
- case Instruction::Call:
3969
- case Instruction::CallBr:
3970
- case Instruction::Invoke:
3971
- case Instruction::CleanupRet:
3972
- case Instruction::CatchSwitch:
3973
- case Instruction::Resume:
3974
- case Instruction::Ret:
3975
- IsInterestingOpcode = true ;
3976
- }
3977
- if (IsInterestingOpcode)
3978
- InstOpcodeMap[I.getOpcode ()].push_back (&I);
3979
- if (I.mayReadOrWriteMemory ())
3980
- ReadOrWriteInsts.push_back (&I);
3981
-
3992
+ auto CallSitePred = [&](Instruction &I) -> bool {
3982
3993
CallSite CS (&I);
3983
- if (CS && CS .getCalledFunction ()) {
3994
+ if (CS.getCalledFunction ()) {
3984
3995
for (int i = 0 , e = CS.getCalledFunction ()->arg_size (); i < e; i++) {
3985
3996
3986
3997
IRPosition CSArgPos = IRPosition::callsite_argument (CS, i);
@@ -4004,7 +4015,32 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
4004
4015
getOrCreateAAFor<AAAlign>(CSArgPos);
4005
4016
}
4006
4017
}
4007
- }
4018
+ return true ;
4019
+ };
4020
+
4021
+ auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction (F);
4022
+ bool Success, AnyDead = false ;
4023
+ Success = checkForAllInstructionsImpl (
4024
+ OpcodeInstMap, CallSitePred, nullptr , AnyDead,
4025
+ {(unsigned )Instruction::Invoke, (unsigned )Instruction::CallBr,
4026
+ (unsigned )Instruction::Call});
4027
+ (void )Success;
4028
+ assert (Success && !AnyDead && " Expected the check call to be successful!" );
4029
+
4030
+ auto LoadStorePred = [&](Instruction &I) -> bool {
4031
+ if (isa<LoadInst>(I))
4032
+ getOrCreateAAFor<AAAlign>(
4033
+ IRPosition::value (*cast<LoadInst>(I).getPointerOperand ()));
4034
+ else
4035
+ getOrCreateAAFor<AAAlign>(
4036
+ IRPosition::value (*cast<StoreInst>(I).getPointerOperand ()));
4037
+ return true ;
4038
+ };
4039
+ Success = checkForAllInstructionsImpl (
4040
+ OpcodeInstMap, LoadStorePred, nullptr , AnyDead,
4041
+ {(unsigned )Instruction::Load, (unsigned )Instruction::Store});
4042
+ (void )Success;
4043
+ assert (Success && !AnyDead && " Expected the check call to be successful!" );
4008
4044
}
4009
4045
4010
4046
// / Helpers to ease debugging through output streams and print calls.
@@ -4078,6 +4114,9 @@ static bool runAttributorOnModule(Module &M, AnalysisGetter &AG) {
4078
4114
InformationCache InfoCache (M.getDataLayout (), AG);
4079
4115
Attributor A (InfoCache, DepRecInterval);
4080
4116
4117
+ for (Function &F : M)
4118
+ A.initializeInformationCache (F);
4119
+
4081
4120
for (Function &F : M) {
4082
4121
if (F.hasExactDefinition ())
4083
4122
NumFnWithExactDefinition++;
0 commit comments