Why Clang is yielding different LLVM IR return type for the same function

So I have a library function called fooo() in a source file B.c and an external A.c file that is referencing a function fooo() in it.
foo is returning a pointer to a structure

%struct._bar= type { %struct._foo, i32, i32 (%struct.doo*, %struct.doo*, %struct.doo*)* }
declare i8* @fooo() #2


%struct._bar= type { %struct._foo, i32, i32 (%struct.doo*, %struct.doo*, %struct.doo*)* }
define noalias %struct._bar* @fooo() #2{


I am implementing a transform pass that operates on the merged version of A.ll and B.ll , since they have different implementations llvm-link is inserting extra bitcasts and thus various passes failed to operate, for example the Inliner pass.
Is there anything else I could do to achieve what I need? Cheers

I wouldn't expect a bitcast to block inlining. It's hard to say why Clang is generating different code here.


Hi John.
Thanks for the info. Currently I’m marking fooo() by hand by adding the always_inline attribute then run the always inline pass using the following code:

AnalysisManager<Module> AM;
AlwaysInlinerPass* InlinerPass=cast<AlwaysInlinerPass>(createAlwaysInlinerLegacyPass());
delete InlinerPass;

However the CallSites are not inlined.
Reading lib/Transforms/IPO/AlwaysInliner.cpp , it says if (CS.getCalledFunction() == &F) , since after linking the CallSites become indirect calls with Bitcast ConstantExpr as target I think that’s why the inliner has no effect.
Any hints?

Run instcombine first. -Eli