[llvm] 25a8aec - [AIX] ExternalSymbolSDNode lowering

Xiangling Liao via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 14 06:40:25 PST 2020


Author: Xiangling Liao
Date: 2020-01-14T09:39:02-05:00
New Revision: 25a8aec7f37b970849ccf5f2893431e2ca858709

URL: https://github.com/llvm/llvm-project/commit/25a8aec7f37b970849ccf5f2893431e2ca858709
DIFF: https://github.com/llvm/llvm-project/commit/25a8aec7f37b970849ccf5f2893431e2ca858709.diff

LOG: [AIX] ExternalSymbolSDNode lowering

For memcpy/memset/memmove etc., replace ExternalSymbolSDNode with a
MCSymbolSDNode, which have a prefix dot before function name as entry
point symbol.

Differential Revision: https://reviews.llvm.org/D70718

Added: 
    llvm/test/CodeGen/PowerPC/aix-external-sym-sdnode-lowering.ll
    llvm/test/CodeGen/PowerPC/aix-user-defined-memcpy.ll

Modified: 
    llvm/lib/Target/PowerPC/PPCISelLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 881d6d71a199..60ed72e1018b 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -5117,6 +5117,15 @@ static unsigned getCallOpcode(bool isIndirectCall, bool isPatchPoint,
 
   return PPCISD::CALL;
 }
+
+static bool isValidAIXExternalSymSDNode(StringRef SymName) {
+  return StringSwitch<bool>(SymName)
+      .Cases("__divdi3", "__fixunsdfdi", "__floatundidf", "__floatundisf",
+             "__moddi3", "__udivdi3", "__umoddi3", true)
+      .Cases("ceil", "floor", "memcpy", "memmove", "memset", "round", true)
+      .Default(false);
+}
+
 static SDValue transformCallee(const SDValue &Callee, SelectionDAG &DAG,
                                const SDLoc &dl, const PPCSubtarget &Subtarget) {
   if (!Subtarget.usesFunctionDescriptors() && !Subtarget.isELFv2ABI())
@@ -5141,41 +5150,72 @@ static SDValue transformCallee(const SDValue &Callee, SelectionDAG &DAG,
       Subtarget.is32BitELFABI() && !isLocalCallee() &&
       Subtarget.getTargetMachine().getRelocationModel() == Reloc::PIC_;
 
+  // On AIX, direct function calls reference the symbol for the function's
+  // entry point, which is named by prepending a "." before the function's
+  // C-linkage name.
+  const auto getAIXFuncEntryPointSymbolSDNode =
+      [&](StringRef FuncName, bool IsDeclaration,
+          const XCOFF::StorageClass &SC) {
+        auto &Context = DAG.getMachineFunction().getMMI().getContext();
+
+        MCSymbolXCOFF *S = cast<MCSymbolXCOFF>(
+            Context.getOrCreateSymbol(Twine(".") + Twine(FuncName)));
+
+        if (IsDeclaration && !S->hasContainingCsect()) {
+          // On AIX, an undefined symbol needs to be associated 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, SC,
+              SectionKind::getMetadata());
+          S->setContainingCsect(Sec);
+        }
+
+        MVT PtrVT =
+            DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout());
+        return DAG.getMCSymbol(S, PtrVT);
+      };
+
   if (isFunctionGlobalAddress(Callee)) {
     const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Callee);
+    const GlobalValue *GV = G->getGlobal();
+
     if (!Subtarget.isAIXABI())
-      return DAG.getTargetGlobalAddress(G->getGlobal(), dl,
-                                        Callee.getValueType(), 0,
+      return DAG.getTargetGlobalAddress(GV, dl, Callee.getValueType(), 0,
                                         UsePlt ? PPCII::MO_PLT : 0);
 
-    // On AIX, direct function calls reference the symbol for the function's
-    // entry point, which is named by prepending a "." before the function's
-    // C-linkage name.
-    auto &Context = DAG.getMachineFunction().getMMI().getContext();
+    assert(!isa<GlobalIFunc>(GV) && "IFunc is not supported on AIX.");
+    const GlobalObject *GO = cast<GlobalObject>(GV);
+    const XCOFF::StorageClass SC =
+        TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GO);
+    return getAIXFuncEntryPointSymbolSDNode(GO->getName(), GO->isDeclaration(),
+                                            SC);
+  }
 
-    const GlobalObject *GO = cast<GlobalObject>(G->getGlobal());
-    MCSymbolXCOFF *S = cast<MCSymbolXCOFF>(
-        Context.getOrCreateSymbol(Twine(".") + Twine(GO->getName())));
+  if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
+    const char *SymName = S->getSymbol();
+    if (!Subtarget.isAIXABI())
+      return DAG.getTargetExternalSymbol(SymName, Callee.getValueType(),
+                                         UsePlt ? PPCII::MO_PLT : 0);
 
-    if (GO && GO->isDeclaration() && !S->hasContainingCsect()) {
-      // On AIX, an undefined symbol needs to be associated with a
-      // MCSectionXCOFF to get the correct storage mapping class.
-      // In this case, XCOFF::XMC_PR.
+    // If there exists a user-declared function whose name is the same as the
+    // ExternalSymbol's, then we pick up the user-declared version.
+    const Module *Mod = DAG.getMachineFunction().getFunction().getParent();
+    if (const Function *F =
+            dyn_cast_or_null<Function>(Mod->getNamedValue(SymName))) {
       const XCOFF::StorageClass SC =
-          TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GO);
-      MCSectionXCOFF *Sec =
-          Context.getXCOFFSection(S->getName(), XCOFF::XMC_PR, XCOFF::XTY_ER,
-                                  SC, SectionKind::getMetadata());
-      S->setContainingCsect(Sec);
+          TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(F);
+      return getAIXFuncEntryPointSymbolSDNode(F->getName(), F->isDeclaration(),
+                                              SC);
     }
 
-    EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout());
-    return DAG.getMCSymbol(S, PtrVT);
-  }
+    // TODO: Remove this when the support for ExternalSymbolSDNode is complete.
+    if (isValidAIXExternalSymSDNode(SymName)) {
+      return getAIXFuncEntryPointSymbolSDNode(SymName, true, XCOFF::C_EXT);
+    }
 
-  if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
-    return DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType(),
-                                       UsePlt ? PPCII::MO_PLT : 0);
+    report_fatal_error("Unexpected ExternalSymbolSDNode: " + Twine(SymName));
+  }
 
   // No transformation needed.
   assert(Callee.getNode() && "What no 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
index 000000000000..f5864df4ff95
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-external-sym-sdnode-lowering.ll
@@ -0,0 +1,128 @@
+; RUN: llc -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff \
+; RUN: -stop-after=machine-cp < %s | FileCheck \
+; RUN: --check-prefix=32BIT %s
+
+; RUN: llc -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff \
+; RUN: -stop-after=machine-cp < %s | FileCheck \
+; RUN: --check-prefix=64BIT %s
+
+define i64 @call_divdi3(i64 %p, i64 %num) {
+entry:
+  %div = sdiv i64 %p, %num
+  ret i64 %div
+}
+
+; 32BIT: BL_NOP <mcsymbol .__divdi3>
+
+define i64 @call_fixunsdfdi(double %p) {
+entry:
+  %conv = fptoui double %p to i64
+  ret i64 %conv
+}
+
+; 32BIT: BL_NOP <mcsymbol .__fixunsdfdi>
+
+define double @call_floatundidf(i64 %p) {
+entry:
+  %conv = uitofp i64 %p to double
+  ret double %conv
+}
+
+; 32BIT: BL_NOP <mcsymbol .__floatundidf>
+
+define float @call_floatundisf(i64 %p) {
+entry:
+  %conv = uitofp i64 %p to float
+  ret float %conv
+}
+
+; 32BIT: BL_NOP <mcsymbol .__floatundisf>
+
+define i64 @call_moddi3(i64 %p, i64 %num) {
+entry:
+  %rem = srem i64 %p, %num
+  ret i64 %rem
+}
+
+; 32BIT: BL_NOP <mcsymbol .__moddi3>
+
+define i64 @call_udivdi3(i64 %p, i64 %q) {
+  %1 = udiv i64 %p, %q
+  ret i64 %1
+}
+
+; 32BIT: BL_NOP <mcsymbol .__udivdi3>
+
+define i64 @call_umoddi3(i64 %p, i64 %num) {
+entry:
+  %rem = urem i64 %p, %num
+  ret i64 %rem
+}
+
+; 32BIT: BL_NOP <mcsymbol .__umoddi3>
+
+define double @call_ceil(double %n) {
+entry:
+  %0 = call double @llvm.ceil.f64(double %n)
+  ret double %0
+}
+
+declare double @llvm.ceil.f64(double)
+
+; 32BIT: BL_NOP <mcsymbol .ceil>
+; 64BIT: BL8_NOP <mcsymbol .ceil>
+
+define double @call_floor(double %n) {
+entry:
+  %0 = call double @llvm.floor.f64(double %n)
+  ret double %0
+}
+
+declare double @llvm.floor.f64(double)
+
+; 32BIT: BL_NOP <mcsymbol .floor>
+; 64BIT: BL8_NOP <mcsymbol .floor>
+
+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 <mcsymbol .memcpy>
+; 64BIT: BL8_NOP <mcsymbol .memcpy>
+
+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 <mcsymbol .memmove>
+; 64BIT: BL8_NOP <mcsymbol .memmove>
+
+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 <mcsymbol .memset>
+; 64BIT: BL8_NOP <mcsymbol .memset>
+
+define double @call_round(double %n) {
+entry:
+  %0 = call double @llvm.round.f64(double %n)
+  ret double %0
+}
+
+declare double @llvm.round.f64(double)
+
+; 32BIT: BL_NOP <mcsymbol .round>
+; 64BIT: BL8_NOP <mcsymbol .round>

diff  --git a/llvm/test/CodeGen/PowerPC/aix-user-defined-memcpy.ll b/llvm/test/CodeGen/PowerPC/aix-user-defined-memcpy.ll
new file mode 100644
index 000000000000..0b892a3ded61
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-user-defined-memcpy.ll
@@ -0,0 +1,58 @@
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \
+; RUN: -mattr=-altivec -filetype=obj -o %t.o < %s
+
+; RUN: llvm-readobj --syms %t.o | FileCheck --check-prefix=32-SYM %s
+
+; RUN: llvm-readobj --relocs --expand-relocs %t.o | FileCheck \
+; RUN: --check-prefix=32-REL %s
+
+; RUN: not llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff \
+; RUN: -mcpu=pwr4 -mattr=-altivec -filetype=obj < %s 2>&1 | FileCheck \
+; RUN: --check-prefix=64-CHECK %s
+
+; Test verifies:
+; If there exists a user-defined function whose name is the same as the
+; "memcpy" ExternalSymbol's, we pick up the user-defined version, even if this
+; may lead to some undefined behavior.
+
+define dso_local signext i32 @memcpy(i8* %destination, i32 signext %num) {
+entry:
+  ret i32 3
+}
+
+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)
+
+; TODO: This test should preferably check the symbol table for .o file and
+;       the relocation associated with the call.
+
+; 32-SYM:      Symbol {{[{][[:space:]] *}}Index: [[#Index:]]{{[[:space:]] *}}Name: .memcpy 
+; 32-SYM-NEXT:    Value (RelocatableAddress): 0x0
+; 32-SYM-NEXT:    Section: .text
+; 32-SYM-NEXT:    Type: 0x0
+; 32-SYM-NEXT:    StorageClass: C_EXT (0x2)
+; 32-SYM-NEXT:    NumberOfAuxEntries: 1
+; 32-SYM-NEXT:    CSECT Auxiliary Entry {
+; 32-SYM-NEXT:      Index: 3
+; 32-SYM-NEXT:      ContainingCsectSymbolIndex: 0
+; 32-SYM-NEXT:      ParameterHashIndex: 0x0
+; 32-SYM-NEXT:      TypeChkSectNum: 0x0
+; 32-SYM-NEXT:      SymbolAlignmentLog2: 0
+; 32-SYM-NEXT:      SymbolType: XTY_LD (0x2)
+; 32-SYM-NEXT:      StorageMappingClass: XMC_PR (0x0)
+; 32-SYM-NEXT:      StabInfoIndex: 0x0
+; 32-SYM-NEXT:      StabSectNum: 0x0
+; 32-SYM-NEXT:    }
+; 32-SYM-NEXT:  }
+
+; 32-SYM-NOT: .memcpy
+
+; We are expecting to have the test fail when the support for relocations land.
+; 32-REL-NOT: Relocation{{[[:space:]]}}
+
+; 64-CHECK: LLVM ERROR: 64-bit XCOFF object files are not supported yet.


        


More information about the llvm-commits mailing list