diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -5319,28 +5319,50 @@ } } - if (Subtarget.isAIXABI() && isFunctionGlobalAddress(Callee)) { + if (Subtarget.isAIXABI()) { // On AIX, direct function calls reference the symbol for the function's // entry point, which is named by inserting a "." before the function's // C-linkage name. - GlobalAddressSDNode *G = cast(Callee); - auto &Context = DAG.getMachineFunction().getMMI().getContext(); + MCSymbolXCOFF *S = nullptr; + if (isFunctionGlobalAddress(Callee)) { + GlobalAddressSDNode *G = cast(Callee); + auto &Context = DAG.getMachineFunction().getMMI().getContext(); - MCSymbolXCOFF *S = cast(Context.getOrCreateSymbol( - Twine(".") + Twine(G->getGlobal()->getName()))); + S = cast(Context.getOrCreateSymbol( + Twine(".") + Twine(G->getGlobal()->getName()))); - const GlobalValue *GV = G->getGlobal(); - if (GV && GV->isDeclaration() && !S->hasContainingCsect()) { + const GlobalValue *GV = G->getGlobal(); + if (GV && GV->isDeclaration() && !S->hasContainingCsect()) { // On AIX, undefined symbol need to associate with a MCSectionXCOFF to // get the correct storage mapping class. In this case, XCOFF::XMC_PR. MCSectionXCOFF *Sec = Context.getXCOFFSection(S->getName(), XCOFF::XMC_PR, XCOFF::XTY_ER, XCOFF::C_EXT, SectionKind::getMetadata()); S->setContainingCsect(Sec); + } + } + + if (ExternalSymbolSDNode *E = dyn_cast(Callee)) { + const char *SymName = E->getSymbol(); + if (strcmp(SymName, "memcpy") == 0 || strcmp(SymName, "memmove") == 0 || + strcmp(SymName, "memset") == 0) { + auto &Context = DAG.getMachineFunction().getMMI().getContext(); + + S = cast( + Context.getOrCreateSymbol(Twine(".") + Twine(SymName))); + if (!S->hasContainingCsect()) { + // On AIX, undefined symbol need to associate with a MCSectionXCOFF to + // get the correct storage mapping class. In this case, XCOFF::XMC_PR. + MCSectionXCOFF *Sec = Context.getXCOFFSection( + S->getName(), XCOFF::XMC_PR, XCOFF::XTY_ER, XCOFF::C_EXT, + SectionKind::getMetadata()); + S->setContainingCsect(Sec); + } + } } + // Replace the callee SDNode with the MCSymbolSDNode. Callee = DAG.getMCSymbol(S, PtrVT); - // Replace the GlobalAddressSDNode Callee with the MCSymbolSDNode. Ops[1] = Callee; } diff --git a/llvm/test/CodeGen/PowerPC/aix-external-sym-sdnode-lowering.ll b/llvm/test/CodeGen/PowerPC/aix-external-sym-sdnode-lowering.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-external-sym-sdnode-lowering.ll @@ -0,0 +1,40 @@ +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr7 \ +; RUN: -mattr=-altivec -stop-after=machine-cp < %s | FileCheck \ +; RUN: --check-prefix=32BIT %s + +; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr7 \ +; RUN: -mattr=-altivec -stop-after=machine-cp < %s | FileCheck \ +; RUN: --check-prefix=64BIT %s + +define void @call_memcpy(i8* %p, i8* %q, i32 %n) { +entry: + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1) + +; 32BIT: BL_NOP +; 64BIT: BL8_NOP + +define void @call_memmove(i8* %p, i8* %q, i32 %n) { +entry: + call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false) + ret void +} + +declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) + +; 32BIT: BL_NOP +; 64BIT: BL8_NOP + +define void @call_memset(i8* %p, i8 %q, i32 %n) #0 { +entry: + call void @llvm.memset.p0i8.i32(i8* %p, i8 %q, i32 %n, i1 false) + ret void +} + +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) + +; 32BIT: BL_NOP +; 64BIT: BL8_NOP