From b3a9320c08ef45de8039075cc532bdb89b5d88f9 Mon Sep 17 00:00:00 2001 From: Sean Fertile Date: Tue, 24 Sep 2019 18:04:51 +0000 Subject: [PATCH] Extends the expansion of the LWZtoc pseduo op for AIX. Differential Revision: https://reviews.llvm.org/D67853 llvm-svn: 372772 --- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 53 ++++++++++++++++------ .../CodeGen/PowerPC/lower-globaladdr32-aix-asm.ll | 21 +++++++++ 2 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 llvm/test/CodeGen/PowerPC/lower-globaladdr32-aix-asm.ll diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index c835df3..5ab2701 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -649,16 +649,19 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { } } case PPC::LWZtoc: { - // Transform %r3 = LWZtoc @min1, %r2 + assert(!isDarwin && "TOC is an ELF/XCOFF construct."); + + // Transform %rN = LWZtoc @op1, %r2 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin); - // Change the opcode to LWZ, and the global address operand to be a - // reference to the GOT entry we will synthesize later. + // Change the opcode to LWZ. TmpInst.setOpcode(PPC::LWZ); + const MachineOperand &MO = MI->getOperand(1); + assert(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() && + "Unexpected operand type for LWZtoc pseudo."); - // Map symbol -> label of TOC entry - assert(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()); + // Map the operand to its corresponding MCSymbol. MCSymbol *MOSymbol = nullptr; if (MO.isGlobal()) MOSymbol = getSymbol(MO.getGlobal()); @@ -669,23 +672,43 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { else if (MO.isBlockAddress()) MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress()); - if (PL == PICLevel::SmallPIC) { + const bool IsAIX = TM.getTargetTriple().isOSAIX(); + + // Create a reference to the GOT entry for the symbol. The GOT entry will be + // synthesized later. + if (PL == PICLevel::SmallPIC && !IsAIX) { const MCExpr *Exp = MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_GOT, OutContext); TmpInst.getOperand(1) = MCOperand::createExpr(Exp); - } else { - MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); + EmitToStreamer(*OutStreamer, TmpInst); + return; + } - const MCExpr *Exp = - MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_None, - OutContext); - const MCExpr *PB = - MCSymbolRefExpr::create(OutContext.getOrCreateSymbol(Twine(".LTOC")), - OutContext); - Exp = MCBinaryExpr::createSub(Exp, PB, OutContext); + // Otherwise use the TOC. 'TOCEntry' is a local symbol used to reference + // the storage allocated in the TOC which contains the address of + // 'MOSymbol'. Said TOC entry will be synthesized later. + MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); + const MCExpr *Exp = + MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_None, OutContext); + + // AIX uses the local symbol directly for the operand; that the symbol is + // accessed toc-relative is implicit. + if (IsAIX) { + assert( + TM.getCodeModel() == CodeModel::Small && + "This pseudo should only be selected for 32-bit small code model."); TmpInst.getOperand(1) = MCOperand::createExpr(Exp); + EmitToStreamer(*OutStreamer, TmpInst); + return; } + + // Create an explicit subtract expression between the local symbol and + // '.LTOC' to manifest the toc-relative offset. + const MCExpr *PB = MCSymbolRefExpr::create( + OutContext.getOrCreateSymbol(Twine(".LTOC")), OutContext); + Exp = MCBinaryExpr::createSub(Exp, PB, OutContext); + TmpInst.getOperand(1) = MCOperand::createExpr(Exp); EmitToStreamer(*OutStreamer, TmpInst); return; } diff --git a/llvm/test/CodeGen/PowerPC/lower-globaladdr32-aix-asm.ll b/llvm/test/CodeGen/PowerPC/lower-globaladdr32-aix-asm.ll new file mode 100644 index 0000000..b368cb4 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/lower-globaladdr32-aix-asm.ll @@ -0,0 +1,21 @@ +; RUN: llc -mtriple powerpc-ibm-aix-xcoff \ +; RUN: -code-model=small < %s | FileCheck %s + +@b = common global i32 0 +@a = common global i32 0 + +define void @test() { + %1 = load i32, i32* @b + store i32 %1, i32* @a + ret void +} + +; CHECK-LABEL: test +; CHECK-DAG: lwz [[REG1:[0-9]+]], LC0(2) +; CHECK-DAG: lwz [[REG2:[0-9]+]], LC1(2) +; CHECK-DAG: lwz [[REG3:[0-9]+]], 0([[REG1]]) +; CHECK: stw [[REG3]], 0([[REG2]]) +; CHECK: blr + +; TODO Update test when TOC-entry emission lands. +; CHECK-NOT: .tc -- 2.7.4