diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/MC/MCExpr.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 116 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 33 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 12 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrInfo.td | 15 | 
6 files changed, 117 insertions, 63 deletions
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index 83a245602ce..6e648b22df1 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -252,6 +252,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {    case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h";    case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha";    case VK_PPC_TLSLD: return "tlsld"; +  case VK_PPC_LOCAL: return "local";    case VK_Mips_GPREL: return "GPREL";    case VK_Mips_GOT_CALL: return "GOT_CALL";    case VK_Mips_GOT16: return "GOT16"; diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 578f0c723a9..b817394e52c 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -87,6 +87,9 @@ unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,        case MCSymbolRefExpr::VK_PLT:          Type = ELF::R_PPC_PLTREL24;          break; +      case MCSymbolRefExpr::VK_PPC_LOCAL: +        Type = ELF::R_PPC_LOCAL24PC; +        break;        }        break;      case PPC::fixup_ppc_brcond14: diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 471780ac5a2..564887353dd 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -323,12 +323,35 @@ MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(MCSymbol *Sym) {  void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {    MCInst TmpInst;    bool isPPC64 = Subtarget.isPPC64(); +  bool isDarwin = Triple(TM.getTargetTriple()).isOSDarwin(); +  const Module *M = MF->getFunction()->getParent(); +  PICLevel::Level PL = M->getPICLevel();    // Lower multi-instruction pseudo operations.    switch (MI->getOpcode()) {    default: break;    case TargetOpcode::DBG_VALUE:      llvm_unreachable("Should be handled target independently"); +  case PPC::MoveGOTtoLR: { +    // Transform %LR = MoveGOTtoLR +    // Into this: bl _GLOBAL_OFFSET_TABLE_@local-4 +    // _GLOBAL_OFFSET_TABLE_@local-4 (instruction preceding +    // _GLOBAL_OFFSET_TABLE_) has exactly one instruction: +    //      blrl +    // This will return the pointer to _GLOBAL_OFFSET_TABLE_@local +    MCSymbol *GOTSymbol = +      OutContext.GetOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_")); +    const MCExpr *OffsExpr = +      MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(GOTSymbol, +                                                      MCSymbolRefExpr::VK_PPC_LOCAL, +                                                      OutContext), +                              MCConstantExpr::Create(4, OutContext), +                              OutContext); + +    // Emit the 'bl'. +    EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BL).addExpr(OffsExpr)); +    return; +  }    case PPC::MovePCtoLR:    case PPC::MovePCtoLR8: {      // Transform %LR = MovePCtoLR @@ -347,10 +370,14 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {      OutStreamer.EmitLabel(PICBase);      return;    } -  case PPC::GetGBRO: { +  case PPC::UpdateGBR: { +    // Transform %Rd = UpdateGBR(%Rt, %Ri) +    // Into: lwz %Rt, .L0$poff - .L0$pb(%Ri) +    //       add %Rd, %Rt, %Ri      // Get the offset from the GOT Base Register to the GOT -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); -    MCSymbol *PICOffset = MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin); +    MCSymbol *PICOffset = +      MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol();      TmpInst.setOpcode(PPC::LWZ);      const MCExpr *Exp =        MCSymbolRefExpr::Create(PICOffset, MCSymbolRefExpr::VK_None, OutContext); @@ -358,26 +385,26 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {        MCSymbolRefExpr::Create(MF->getPICBaseSymbol(),                                MCSymbolRefExpr::VK_None,                                OutContext); -    const MCOperand MO = TmpInst.getOperand(1); -    TmpInst.getOperand(1) = MCOperand::CreateExpr(MCBinaryExpr::CreateSub(Exp, -                                                                          PB, -                                                                          OutContext)); -    TmpInst.addOperand(MO); +    const MCOperand TR = TmpInst.getOperand(1); +    const MCOperand PICR = TmpInst.getOperand(0); + +    // Step 1: lwz %Rt, .L$poff - .L$pb(%Ri) +    TmpInst.getOperand(1) = +        MCOperand::CreateExpr(MCBinaryExpr::CreateSub(Exp, PB, OutContext)); +    TmpInst.getOperand(0) = TR; +    TmpInst.getOperand(2) = PICR;      EmitToStreamer(OutStreamer, TmpInst); -    return; -  } -  case PPC::UpdateGBR: { -    // Update the GOT Base Register to point to the GOT.  It may be possible to -    // merge this with the PPC::GetGBRO, doing it all in one step. -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); +      TmpInst.setOpcode(PPC::ADD4); -    TmpInst.addOperand(TmpInst.getOperand(0)); +    TmpInst.getOperand(0) = PICR; +    TmpInst.getOperand(1) = TR; +    TmpInst.getOperand(2) = PICR;      EmitToStreamer(OutStreamer, TmpInst);      return;    }    case PPC::LWZtoc: { -    // Transform %X3 = LWZtoc <ga:@min1>, %X2 -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); +    // Transform %R3 = LWZtoc <ga:@min1>, %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. @@ -396,16 +423,23 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {      else if (MO.isBlockAddress())        MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress()); -    MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); - -    const MCExpr *Exp = -      MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_None, -                              OutContext); -    const MCExpr *PB = -      MCSymbolRefExpr::Create(OutContext.GetOrCreateSymbol(Twine(".L.TOC.")), -                                                           OutContext); -    Exp = MCBinaryExpr::CreateSub(Exp, PB, OutContext); -    TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); +    if (PL == PICLevel::Small) { +      const MCExpr *Exp = +        MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_GOT, +                                OutContext); +      TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); +    } else { +      MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); + +      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); +      TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); +    }      EmitToStreamer(OutStreamer, TmpInst);      return;    } @@ -414,7 +448,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {    case PPC::LDtocBA:    case PPC::LDtoc: {      // Transform %X3 = LDtoc <ga:@min1>, %X2 -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);      // Change the opcode to LD, and the global address operand to be a      // reference to the TOC entry we will synthesize later. @@ -445,7 +479,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {    case PPC::ADDIStocHA: {      // Transform %Xd = ADDIStocHA %X2, <ga:@sym> -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);      // Change the opcode to ADDIS8.  If the global address is external, has      // common linkage, is a non-local function address, or is a jump table @@ -491,7 +525,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {    }    case PPC::LDtocL: {      // Transform %Xd = LDtocL <ga:@sym>, %Xs -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);      // Change the opcode to LD.  If the global address is external, has      // common linkage, or is a jump table address, then reference the @@ -533,7 +567,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {    }    case PPC::ADDItocL: {      // Transform %Xd = ADDItocL %Xs, <ga:@sym> -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);      // Change the opcode to ADDI8.  If the global address is external, then      // generate a TOC entry and reference that.  Otherwise reference the @@ -584,7 +618,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {    case PPC::LDgotTprelL:    case PPC::LDgotTprelL32: {      // Transform %Xd = LDgotTprelL <ga:@sym>, %Xs -    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); +    LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);      // Change the opcode to LD.      TmpInst.setOpcode(isPPC64 ? PPC::LD : PPC::LWZ); @@ -808,7 +842,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {    }    } -  LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); +  LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);    EmitToStreamer(OutStreamer, TmpInst);  } @@ -824,16 +858,14 @@ void PPCLinuxAsmPrinter::EmitStartOfAsmFile(Module &M) {    if (Subtarget.isPPC64() || TM.getRelocationModel() != Reloc::PIC_)      return AsmPrinter::EmitStartOfAsmFile(M); -  // FIXME: The use of .got2 assumes large GOT model (-fPIC), which is not -  // optimal for some cases.  We should consider supporting small model (-fpic) -  // as well in the future. -  assert(TM.getCodeModel() != CodeModel::Small && -         "Small code model PIC is currently unsupported."); +  if (M.getPICLevel() == PICLevel::Small) +    return AsmPrinter::EmitStartOfAsmFile(M); +    OutStreamer.SwitchSection(OutContext.getELFSection(".got2",           ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,           SectionKind::getReadOnly())); -  MCSymbol *TOCSym = OutContext.GetOrCreateSymbol(Twine(".L.TOC.")); +  MCSymbol *TOCSym = OutContext.GetOrCreateSymbol(Twine(".LTOC"));    MCSymbol *CurrentPos = OutContext.CreateTempSymbol();    OutStreamer.EmitLabel(CurrentPos); @@ -852,7 +884,9 @@ void PPCLinuxAsmPrinter::EmitStartOfAsmFile(Module &M) {  void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {    // linux/ppc32 - Normal entry label. -  if (!Subtarget.isPPC64() && TM.getRelocationModel() != Reloc::PIC_) +  if (!Subtarget.isPPC64() &&  +      (TM.getRelocationModel() != Reloc::PIC_ ||  +       MF->getFunction()->getParent()->getPICLevel() == PICLevel::Small))      return AsmPrinter::EmitFunctionEntryLabel();    if (!Subtarget.isPPC64()) { @@ -864,7 +898,7 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {        const MCExpr *OffsExpr =          MCBinaryExpr::CreateSub( -          MCSymbolRefExpr::Create(OutContext.GetOrCreateSymbol(Twine(".L.TOC.")), +          MCSymbolRefExpr::Create(OutContext.GetOrCreateSymbol(Twine(".LTOC")),                                                                 OutContext),                                    MCSymbolRefExpr::Create(PICBase, OutContext),            OutContext); diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 0b731cfba6a..49ba58b3e4b 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -27,6 +27,7 @@  #include "llvm/IR/GlobalValue.h"  #include "llvm/IR/GlobalVariable.h"  #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h"  #include "llvm/Support/CommandLine.h"  #include "llvm/Support/Debug.h"  #include "llvm/Support/ErrorHandling.h" @@ -273,23 +274,29 @@ SDNode *PPCDAGToDAGISel::getGlobalBaseReg() {      // Insert the set of GlobalBaseReg into the first MBB of the function      MachineBasicBlock &FirstMBB = MF->front();      MachineBasicBlock::iterator MBBI = FirstMBB.begin(); +    const Module *M = MF->getFunction()->getParent();      DebugLoc dl;      if (PPCLowering->getPointerTy() == MVT::i32) { -      if (PPCSubTarget->isTargetELF()) +      if (PPCSubTarget->isTargetELF()) {          GlobalBaseReg = PPC::R30; -      else +        if (M->getPICLevel() == PICLevel::Small) { +          BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MoveGOTtoLR)); +          BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg); +        } else { +          BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR)); +          BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg); +          unsigned TempReg = RegInfo->createVirtualRegister(&PPC::GPRCRegClass); +          BuildMI(FirstMBB, MBBI, dl, +                  TII.get(PPC::UpdateGBR)).addReg(GlobalBaseReg) +                  .addReg(TempReg, RegState::Define).addReg(GlobalBaseReg); +          MF->getInfo<PPCFunctionInfo>()->setUsesPICBase(true); +        } +      } else {          GlobalBaseReg =            RegInfo->createVirtualRegister(&PPC::GPRC_NOR0RegClass); -      BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR)); -      BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg); -      if (PPCSubTarget->isTargetELF()) { -        unsigned TempReg = RegInfo->createVirtualRegister(&PPC::GPRCRegClass); -        BuildMI(FirstMBB, MBBI, dl, -                TII.get(PPC::GetGBRO), TempReg).addReg(GlobalBaseReg); -        BuildMI(FirstMBB, MBBI, dl, -                TII.get(PPC::UpdateGBR)).addReg(GlobalBaseReg).addReg(TempReg); -        MF->getInfo<PPCFunctionInfo>()->setUsesPICBase(true); +        BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR)); +        BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg);        }      } else {        GlobalBaseReg = RegInfo->createVirtualRegister(&PPC::G8RC_NOX0RegClass); @@ -1442,13 +1449,13 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) {      return CurDAG->SelectNodeTo(N, Reg, MVT::Other, Chain);    }    case PPCISD::TOC_ENTRY: { +    assert ((PPCSubTarget->isPPC64() || PPCSubTarget->isSVR4ABI()) && +            "Only supported for 64-bit ABI and 32-bit SVR4");      if (PPCSubTarget->isSVR4ABI() && !PPCSubTarget->isPPC64()) {        SDValue GA = N->getOperand(0);        return CurDAG->getMachineNode(PPC::LWZtoc, dl, MVT::i32, GA,                                      N->getOperand(1));      } -    assert (PPCSubTarget->isPPC64() && -            "Only supported for 64-bit ABI and 32-bit SVR4");      // For medium and large code model, we generate two instructions as      // described below.  Otherwise we allow SelectCodeCommon to handle this, diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 0c844be3c55..17bf813521a 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1689,6 +1689,8 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,    const GlobalValue *GV = GA->getGlobal();    EVT PtrVT = getPointerTy();    bool is64bit = Subtarget.isPPC64(); +  const Module *M = DAG.getMachineFunction().getFunction()->getParent(); +  PICLevel::Level picLevel = M->getPICLevel();    TLSModel::Model Model = getTargetMachine().getTLSModel(GV); @@ -1728,7 +1730,10 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,        GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSGD_HA, dl, PtrVT,                                     GOTReg, TGA);      } else { -      GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT); +      if (picLevel == PICLevel::Small) +        GOTPtr = DAG.getNode(PPCISD::GlobalBaseReg, dl, PtrVT); +      else +        GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT);      }      SDValue GOTEntry = DAG.getNode(PPCISD::ADDI_TLSGD_L, dl, PtrVT,                                     GOTPtr, TGA); @@ -1745,7 +1750,10 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op,        GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSLD_HA, dl, PtrVT,                             GOTReg, TGA);      } else { -      GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT); +      if (picLevel == PICLevel::Small) +        GOTPtr = DAG.getNode(PPCISD::GlobalBaseReg, dl, PtrVT); +      else +        GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT);      }      SDValue GOTEntry = DAG.getNode(PPCISD::ADDI_TLSLD_L, dl, PtrVT,                                     GOTPtr, TGA); diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index e04425af800..8c76c46980d 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -1031,6 +1031,9 @@ let isTerminator = 1, isBarrier = 1, PPC970_Unit = 7 in {  let Defs = [LR] in    def MovePCtoLR : Pseudo<(outs), (ins), "#MovePCtoLR", []>,                     PPC970_Unit_BRU; +let Defs = [LR] in +  def MoveGOTtoLR : Pseudo<(outs), (ins), "#MoveGOTtoLR", []>, +                    PPC970_Unit_BRU;  let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, PPC970_Unit = 7 in {    let isBarrier = 1 in { @@ -2502,15 +2505,13 @@ def ADDISdtprelHA32 : Pseudo<(outs gprc:$rD), (ins gprc_nor0:$reg, s16imm:$disp)                                                  tglobaltlsaddr:$disp))]>;  // Support for Position-independent code -def LWZtoc: Pseudo<(outs gprc:$rD), (ins tocentry32:$disp, gprc:$reg), -                  "#LWZtoc", -                  [(set i32:$rD, -                     (PPCtoc_entry tglobaladdr:$disp, i32:$reg))]>; +def LWZtoc : Pseudo<(outs gprc:$rD), (ins tocentry32:$disp, gprc:$reg), +                   "#LWZtoc", +                   [(set i32:$rD, +                      (PPCtoc_entry tglobaladdr:$disp, i32:$reg))]>;  // Get Global (GOT) Base Register offset, from the word immediately preceding  // the function label. -def GetGBRO:	Pseudo<(outs gprc:$rT), (ins gprc:$rI), "#GetGBRO", []>; -// Update the Global(GOT) Base Register with the above offset. -def UpdateGBR:	Pseudo<(outs gprc:$rT), (ins gprc:$rI), "#UpdateGBR", []>; +def UpdateGBR : Pseudo<(outs gprc:$rD, gprc:$rT), (ins gprc:$rI), "#UpdateGBR", []>;  // Standard shifts.  These are represented separately from the real shifts above  | 

