Why does Alias Analysis says that all function may alias

I am try to build Call graph as a practice following the assignment at [1]
The objective it to take in IR and give back Call graph featuring which functions calls which Functions.
The problem is dealing with function pointers as they usually are indirect CallSite.
I tried to overcome the problem by using Alias Analysis (with the new pass manager).
I set up the pipeline like this
int main (int argc, char **argv, const char **env) {
// Before this point I would setup the module object, cl and friends
PassBuilder PB;
ModulePassManager MPM(true);
LoopAnalysisManager LAM(false);
FunctionAnalysisManager FAM(true);
CGSCCAnalysisManager CAM(false);
ModuleAnalysisManager MAM(true);
AAManager AA ;//= PB.buildDefaultAAPipeline();
if (auto Err = PB.parseAAPipeline(AA, “basicaa”))
report_fatal_error(“Error parsing basicaa AA pipeline”);
FAM.registerPass([&] {return std::move(AA);});
MAM.registerPass([&] {return callgraphs::WeightedCallGraph();});
PB.crossRegisterProxies(LAM, FAM, CAM, MAM);

MPM.run(*module, MAM);
return 0;
callgraphs hold the Analysis and transformation pass they do the following:-
A- generate the graph
B- Print it.

Deep inside that Namespace this is how I would analyse an CallSite once it is proven to hold an indirect function call

void WeightedCallGraphInfo::AnalyseIndirectCallSite(CallSite &cs, ModuleAnalysisManager &MAM) {
Value *v = cs.getCalledValue();
Function &caller = *cs.getCaller();
Module &M = *caller.getParent();
FunctionAnalysisManager &FAM = MAM.
AliasAnalysis &AA = FAM.getResult(caller);
for (Function &f: M) {
if (f.isIntrinsic())
AliasResult R = AA.alias(v, &f);
if (R == AliasResult::MustAlias){
//What goes here doesn’t matter to my question


The problem is that R is always AliasResult::MayAlias regardlles of the analysis pipeline I have tried basicaa and the BP.buildDefaultAAPipeline() via the pipeline setup shown above and bunch of other ones (through opt).

My concert is that I could be doing something wrong and not being the limitation of the alias analysis.

For example

I tested the analysis on simple .c module that looks like this
void foo(int x);

void bar() {

void baz() {

int main(int argc, char **argv) {
void (*bam)() = 0;
switch (argc%3) {
case 1: bam = bar; break;
case 2: bam = baz; break;
return 0;

I placed the llvm IR on pastebin at [2] because it is too big.

The problem is that bam() and foo() and main() may alias while I was expecting to not alias relation, and bar() and baz() had may alias relation as well however I was expecting a MustAlias. So if anyone had clue about whether I am doing something wrong or this is the expected behavior, it will be great.

I have the source code for the whole pass (just in case anyone would have a doubt in how I did things) at [3].

[1] http://www.cs.sfu.ca/~wsumner/teaching/886/15/project1.html
[2] https://pastebin.com/BGt787tb
[3] https://github.com/oddcoder/LLVM_Playground/tree/master/01_callgrapher