Skip to content

Commit

Permalink
[arm-fast-isel] Add support for ELF PIC.
Browse files Browse the repository at this point in the history
This is a preliminary step towards ELF support; currently ARMFastISel hasn't
been used for ELF object files yet.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@164759 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
jush31666 committed Sep 27, 2012
1 parent 5e92990 commit 8f50647
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 2 deletions.
1 change: 1 addition & 0 deletions lib/Target/ARM/ARM.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM,

FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false);
FunctionPass *createARMExpandPseudoPass();
FunctionPass *createARMGlobalBaseRegPass();
FunctionPass *createARMGlobalMergePass(const TargetLowering* tli);
FunctionPass *createARMConstantIslandPass();
FunctionPass *createMLxExpansionPass();
Expand Down
45 changes: 45 additions & 0 deletions lib/Target/ARM/ARMFastISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ class ARMFastISel : public FastISel {
unsigned ARMMoveToFPReg(EVT VT, unsigned SrcReg);
unsigned ARMMoveToIntReg(EVT VT, unsigned SrcReg);
unsigned ARMSelectCallOp(bool UseReg);
unsigned ARMLowerPICELF(const GlobalValue *GV, unsigned Align, EVT VT);

// Call handling routines.
private:
Expand Down Expand Up @@ -648,6 +649,9 @@ unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, EVT VT) {
Align = TD.getTypeAllocSize(GV->getType());
}

if (Subtarget->isTargetELF() && RelocM == Reloc::PIC_)
return ARMLowerPICELF(GV, Align, VT);

// Grab index.
unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 :
(Subtarget->isThumb() ? 4 : 8);
Expand Down Expand Up @@ -2796,6 +2800,47 @@ bool ARMFastISel::TryToFoldLoad(MachineInstr *MI, unsigned OpNo,
return true;
}

unsigned ARMFastISel::ARMLowerPICELF(const GlobalValue *GV,
unsigned Align, EVT VT) {
bool UseGOTOFF = GV->hasLocalLinkage() || GV->hasHiddenVisibility();
ARMConstantPoolConstant *CPV =
ARMConstantPoolConstant::Create(GV, UseGOTOFF ? ARMCP::GOTOFF : ARMCP::GOT);
unsigned Idx = MCP.getConstantPoolIndex(CPV, Align);

unsigned Opc;
unsigned DestReg1 = createResultReg(TLI.getRegClassFor(VT));
// Load value.
if (isThumb2) {
AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
TII.get(ARM::t2LDRpci), DestReg1)
.addConstantPoolIndex(Idx));
Opc = UseGOTOFF ? ARM::t2ADDrr : ARM::t2LDRs;
} else {
// The extra immediate is for addrmode2.
AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
DL, TII.get(ARM::LDRcp), DestReg1)
.addConstantPoolIndex(Idx).addImm(0));
Opc = UseGOTOFF ? ARM::ADDrr : ARM::LDRrs;
}

unsigned GlobalBaseReg = AFI->getGlobalBaseReg();
if (GlobalBaseReg == 0) {
GlobalBaseReg = MRI.createVirtualRegister(TLI.getRegClassFor(VT));
AFI->setGlobalBaseReg(GlobalBaseReg);
}

unsigned DestReg2 = createResultReg(TLI.getRegClassFor(VT));
MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
DL, TII.get(Opc), DestReg2)
.addReg(DestReg1)
.addReg(GlobalBaseReg);
if (!UseGOTOFF)
MIB.addImm(0);
AddOptionalDefs(MIB);

return DestReg2;
}

namespace llvm {
FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo,
const TargetLibraryInfo *libInfo) {
Expand Down
62 changes: 62 additions & 0 deletions lib/Target/ARM/ARMInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@

#include "ARMInstrInfo.h"
#include "ARM.h"
#include "ARMConstantPoolValue.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMTargetMachine.h"
#include "MCTargetDesc/ARMAddressingModes.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInst.h"
using namespace llvm;
Expand Down Expand Up @@ -84,3 +88,61 @@ unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const {

return 0;
}

namespace {
/// ARMCGBR - Create Global Base Reg pass. This initializes the PIC
/// global base register for ARM ELF.
struct ARMCGBR : public MachineFunctionPass {
static char ID;
ARMCGBR() : MachineFunctionPass(ID) {}

virtual bool runOnMachineFunction(MachineFunction &MF) {
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
if (AFI->getGlobalBaseReg() == 0)
return false;

const ARMTargetMachine *TM =
static_cast<const ARMTargetMachine *>(&MF.getTarget());
if (TM->getRelocationModel() != Reloc::PIC_)
return false;

LLVMContext* Context = &MF.getFunction()->getContext();
GlobalValue *GV = new GlobalVariable(Type::getInt32Ty(*Context), false,
GlobalValue::ExternalLinkage, 0,
"_GLOBAL_OFFSET_TABLE_");
unsigned Id = AFI->createPICLabelUId();
ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(GV, Id);
unsigned Align = TM->getTargetData()->getPrefTypeAlignment(GV->getType());
unsigned Idx = MF.getConstantPool()->getConstantPoolIndex(CPV, Align);

MachineBasicBlock &FirstMBB = MF.front();
MachineBasicBlock::iterator MBBI = FirstMBB.begin();
DebugLoc DL = FirstMBB.findDebugLoc(MBBI);
unsigned GlobalBaseReg = AFI->getGlobalBaseReg();
unsigned Opc = TM->getSubtarget<ARMSubtarget>().isThumb2() ?
ARM::t2LDRpci : ARM::LDRcp;
const TargetInstrInfo &TII = *TM->getInstrInfo();
MachineInstrBuilder MIB = BuildMI(FirstMBB, MBBI, DL,
TII.get(Opc), GlobalBaseReg)
.addConstantPoolIndex(Idx);
if (Opc == ARM::LDRcp)
MIB.addImm(0);
AddDefaultPred(MIB);

return true;
}

virtual const char *getPassName() const {
return "ARM PIC Global Base Reg Initialization";
}

virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
MachineFunctionPass::getAnalysisUsage(AU);
}
};
}

char ARMCGBR::ID = 0;
FunctionPass*
llvm::createARMGlobalBaseRegPass() { return new ARMCGBR(); }
12 changes: 10 additions & 2 deletions lib/Target/ARM/ARMMachineFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ class ARMFunctionInfo : public MachineFunctionInfo {
/// pass.
DenseMap<unsigned, unsigned> CPEClones;

/// GlobalBaseReg - keeps track of the virtual register initialized for
/// use as the global base register. This is used for PIC in some PIC
/// relocation models.
unsigned GlobalBaseReg;

public:
ARMFunctionInfo() :
isThumb(false),
Expand All @@ -119,7 +124,7 @@ class ARMFunctionInfo : public MachineFunctionInfo {
GPRCS1Frames(0), GPRCS2Frames(0), DPRCSFrames(0),
NumAlignedDPRCS2Regs(0),
JumpTableUId(0), PICLabelUId(0),
VarArgsFrameIndex(0), HasITBlocks(false) {}
VarArgsFrameIndex(0), HasITBlocks(false), GlobalBaseReg(0) {}

explicit ARMFunctionInfo(MachineFunction &MF) :
isThumb(MF.getTarget().getSubtarget<ARMSubtarget>().isThumb()),
Expand All @@ -130,7 +135,7 @@ class ARMFunctionInfo : public MachineFunctionInfo {
GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0),
GPRCS1Frames(32), GPRCS2Frames(32), DPRCSFrames(32),
JumpTableUId(0), PICLabelUId(0),
VarArgsFrameIndex(0), HasITBlocks(false) {}
VarArgsFrameIndex(0), HasITBlocks(false), GlobalBaseReg(0) {}

bool isThumbFunction() const { return isThumb; }
bool isThumb1OnlyFunction() const { return isThumb && !hasThumb2; }
Expand Down Expand Up @@ -249,6 +254,9 @@ class ARMFunctionInfo : public MachineFunctionInfo {
bool hasITBlocks() const { return HasITBlocks; }
void setHasITBlocks(bool h) { HasITBlocks = h; }

unsigned getGlobalBaseReg() const { return GlobalBaseReg; }
void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; }

void recordCPEClone(unsigned CPIdx, unsigned CPCloneIdx) {
if (!CPEClones.insert(std::make_pair(CPCloneIdx, CPIdx)).second)
assert(0 && "Duplicate entries!");
Expand Down
5 changes: 5 additions & 0 deletions lib/Target/ARM/ARMTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ bool ARMPassConfig::addPreISel() {

bool ARMPassConfig::addInstSelector() {
addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));

const ARMSubtarget *Subtarget = &getARMSubtarget();
if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() &&
TM->Options.EnableFastISel)
addPass(createARMGlobalBaseRegPass());
return false;
}

Expand Down
18 changes: 18 additions & 0 deletions test/CodeGen/ARM/fast-isel-pic.ll
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=pic -mtriple=thumbv7-apple-ios | FileCheck %s --check-prefix=THUMB
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=pic -mtriple=arm-apple-ios | FileCheck %s --check-prefix=ARM
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=pic -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=ARMv7
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=pic -mtriple=thumbv7-none-linux-gnueabi | FileCheck %s --check-prefix=THUMB-ELF
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=pic -mtriple=armv7-none-linux-gnueabi | FileCheck %s --check-prefix=ARMv7-ELF

@g = global i32 0, align 4

Expand All @@ -10,13 +12,21 @@ entry:
; THUMB: movw [[reg0:r[0-9]+]],
; THUMB: movt [[reg0]],
; THUMB: add [[reg0]], pc
; THUMB-ELF: LoadGV
; THUMB-ELF: ldr.n r[[reg0:[0-9]+]],
; THUMB-ELF: ldr.n r[[reg1:[0-9]+]],
; THUMB-ELF: ldr r[[reg0]], [r[[reg1]], r[[reg0]]]
; ARM: LoadGV
; ARM: ldr [[reg1:r[0-9]+]],
; ARM: add [[reg1]], pc, [[reg1]]
; ARMv7: LoadGV
; ARMv7: movw [[reg2:r[0-9]+]],
; ARMv7: movt [[reg2]],
; ARMv7: add [[reg2]], pc, [[reg2]]
; ARMv7-ELF: LoadGV
; ARMv7-ELF: ldr r[[reg2:[0-9]+]],
; ARMv7-ELF: ldr r[[reg3:[0-9]+]],
; ARMv7-ELF: ldr r[[reg2]], [r[[reg3]], r[[reg2]]]
%tmp = load i32* @g
ret i32 %tmp
}
Expand All @@ -30,6 +40,10 @@ entry:
; THUMB: movt r[[reg3]],
; THUMB: add r[[reg3]], pc
; THUMB: ldr r[[reg3]], [r[[reg3]]]
; THUMB-ELF: LoadIndirectSymbol
; THUMB-ELF: ldr.n r[[reg3:[0-9]+]],
; THUMB-ELF: ldr.n r[[reg4:[0-9]+]],
; THUMB-ELF: ldr r[[reg3]], [r[[reg4]], r[[reg3]]]
; ARM: LoadIndirectSymbol
; ARM: ldr [[reg4:r[0-9]+]],
; ARM: ldr [[reg4]], [pc, [[reg4]]]
Expand All @@ -38,6 +52,10 @@ entry:
; ARMv7: movt r[[reg5]],
; ARMv7: add r[[reg5]], pc, r[[reg5]]
; ARMv7: ldr r[[reg5]], [r[[reg5]]]
; ARMv7-ELF: LoadIndirectSymbol
; ARMv7-ELF: ldr r[[reg5:[0-9]+]],
; ARMv7-ELF: ldr r[[reg6:[0-9]+]],
; ARMv7-ELF: ldr r[[reg5]], [r[[reg6]], r[[reg5]]]
%tmp = load i32* @i
ret i32 %tmp
}

0 comments on commit 8f50647

Please sign in to comment.