forked from OSchip/llvm-project
[AIX] TOC pseudo expansion for 64bit large + 64bit small + 32bit large models
This patch provides support for peudo ops including ADDIStocHA8, ADDIStocHA, LWZtocL, LDtoc, LDtocL for AIX, lowering them from MIR to assembly. Differential Revision: https://reviews.llvm.org/D68341 llvm-svn: 375113
This commit is contained in:
parent
5e962e8d7d
commit
ffe2ec5170
|
@ -235,6 +235,8 @@ public:
|
||||||
VK_PPC_TOC_LO, // symbol@toc@l
|
VK_PPC_TOC_LO, // symbol@toc@l
|
||||||
VK_PPC_TOC_HI, // symbol@toc@h
|
VK_PPC_TOC_HI, // symbol@toc@h
|
||||||
VK_PPC_TOC_HA, // symbol@toc@ha
|
VK_PPC_TOC_HA, // symbol@toc@ha
|
||||||
|
VK_PPC_U, // symbol@u
|
||||||
|
VK_PPC_L, // symbol@l
|
||||||
VK_PPC_DTPMOD, // symbol@dtpmod
|
VK_PPC_DTPMOD, // symbol@dtpmod
|
||||||
VK_PPC_TPREL_LO, // symbol@tprel@l
|
VK_PPC_TPREL_LO, // symbol@tprel@l
|
||||||
VK_PPC_TPREL_HI, // symbol@tprel@h
|
VK_PPC_TPREL_HI, // symbol@tprel@h
|
||||||
|
|
|
@ -259,6 +259,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
|
||||||
case VK_PPC_TOC_LO: return "toc@l";
|
case VK_PPC_TOC_LO: return "toc@l";
|
||||||
case VK_PPC_TOC_HI: return "toc@h";
|
case VK_PPC_TOC_HI: return "toc@h";
|
||||||
case VK_PPC_TOC_HA: return "toc@ha";
|
case VK_PPC_TOC_HA: return "toc@ha";
|
||||||
|
case VK_PPC_U: return "u";
|
||||||
|
case VK_PPC_L: return "l";
|
||||||
case VK_PPC_DTPMOD: return "dtpmod";
|
case VK_PPC_DTPMOD: return "dtpmod";
|
||||||
case VK_PPC_TPREL_LO: return "tprel@l";
|
case VK_PPC_TPREL_LO: return "tprel@l";
|
||||||
case VK_PPC_TPREL_HI: return "tprel@h";
|
case VK_PPC_TPREL_HI: return "tprel@h";
|
||||||
|
@ -373,6 +375,8 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
|
||||||
.Case("toc@l", VK_PPC_TOC_LO)
|
.Case("toc@l", VK_PPC_TOC_LO)
|
||||||
.Case("toc@h", VK_PPC_TOC_HI)
|
.Case("toc@h", VK_PPC_TOC_HI)
|
||||||
.Case("toc@ha", VK_PPC_TOC_HA)
|
.Case("toc@ha", VK_PPC_TOC_HA)
|
||||||
|
.Case("u", VK_PPC_U)
|
||||||
|
.Case("l", VK_PPC_L)
|
||||||
.Case("tls", VK_PPC_TLS)
|
.Case("tls", VK_PPC_TLS)
|
||||||
.Case("dtpmod", VK_PPC_DTPMOD)
|
.Case("dtpmod", VK_PPC_DTPMOD)
|
||||||
.Case("tprel@l", VK_PPC_TPREL_LO)
|
.Case("tprel@l", VK_PPC_TPREL_LO)
|
||||||
|
|
|
@ -66,6 +66,31 @@ void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
|
||||||
|
|
||||||
void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
|
void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
|
||||||
StringRef Annot, const MCSubtargetInfo &STI) {
|
StringRef Annot, const MCSubtargetInfo &STI) {
|
||||||
|
// Customize printing of the addis instruction on AIX. When an operand is a
|
||||||
|
// symbol reference, the instruction syntax is changed to look like a load
|
||||||
|
// operation, i.e:
|
||||||
|
// Transform: addis $rD, $rA, $src --> addis $rD, $src($rA).
|
||||||
|
if (TT.isOSAIX() &&
|
||||||
|
(MI->getOpcode() == PPC::ADDIS8 || MI->getOpcode() == PPC::ADDIS) &&
|
||||||
|
MI->getOperand(2).isExpr()) {
|
||||||
|
assert((MI->getOperand(0).isReg() && MI->getOperand(1).isReg()) &&
|
||||||
|
"The first and the second operand of an addis instruction"
|
||||||
|
" should be registers.");
|
||||||
|
|
||||||
|
assert(isa<MCSymbolRefExpr>(MI->getOperand(2).getExpr()) &&
|
||||||
|
"The third operand of an addis instruction should be a symbol "
|
||||||
|
"reference expression if it is an expression at all.");
|
||||||
|
|
||||||
|
O << "\taddis ";
|
||||||
|
printOperand(MI, 0, O);
|
||||||
|
O << ", ";
|
||||||
|
printOperand(MI, 2, O);
|
||||||
|
O << "(";
|
||||||
|
printOperand(MI, 1, O);
|
||||||
|
O << ")";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check for slwi/srwi mnemonics.
|
// Check for slwi/srwi mnemonics.
|
||||||
if (MI->getOpcode() == PPC::RLWINM) {
|
if (MI->getOpcode() == PPC::RLWINM) {
|
||||||
unsigned char SH = MI->getOperand(2).getImm();
|
unsigned char SH = MI->getOperand(2).getImm();
|
||||||
|
|
|
@ -536,6 +536,8 @@ static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO,
|
||||||
void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
MCInst TmpInst;
|
MCInst TmpInst;
|
||||||
const bool IsDarwin = TM.getTargetTriple().isOSDarwin();
|
const bool IsDarwin = TM.getTargetTriple().isOSDarwin();
|
||||||
|
const bool IsPPC64 = Subtarget->isPPC64();
|
||||||
|
const bool IsAIX = Subtarget->isAIXABI();
|
||||||
const Module *M = MF->getFunction().getParent();
|
const Module *M = MF->getFunction().getParent();
|
||||||
PICLevel::Level PL = M->getPICLevel();
|
PICLevel::Level PL = M->getPICLevel();
|
||||||
|
|
||||||
|
@ -683,11 +685,10 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
|
|
||||||
const MachineOperand &MO = MI->getOperand(1);
|
const MachineOperand &MO = MI->getOperand(1);
|
||||||
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
|
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
|
||||||
"Unexpected operand type for LWZtoc pseudo.");
|
"Invalid operand for LWZtoc.");
|
||||||
|
|
||||||
// Map the operand to its corresponding MCSymbol.
|
// Map the operand to its corresponding MCSymbol.
|
||||||
const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
|
const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
|
||||||
const bool IsAIX = TM.getTargetTriple().isOSAIX();
|
|
||||||
|
|
||||||
// Create a reference to the GOT entry for the symbol. The GOT entry will be
|
// Create a reference to the GOT entry for the symbol. The GOT entry will be
|
||||||
// synthesized later.
|
// synthesized later.
|
||||||
|
@ -700,7 +701,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise use the TOC. 'TOCEntry' is a label used to reference the
|
// Otherwise, use the TOC. 'TOCEntry' is a label used to reference the
|
||||||
// storage allocated in the TOC which contains the address of
|
// storage allocated in the TOC which contains the address of
|
||||||
// 'MOSymbol'. Said TOC entry will be synthesized later.
|
// 'MOSymbol'. Said TOC entry will be synthesized later.
|
||||||
MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
|
MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
|
||||||
|
@ -732,6 +733,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
case PPC::LDtocCPT:
|
case PPC::LDtocCPT:
|
||||||
case PPC::LDtocBA:
|
case PPC::LDtocBA:
|
||||||
case PPC::LDtoc: {
|
case PPC::LDtoc: {
|
||||||
|
assert(!IsDarwin && "TOC is an ELF/XCOFF construct");
|
||||||
|
|
||||||
// Transform %x3 = LDtoc @min1, %x2
|
// Transform %x3 = LDtoc @min1, %x2
|
||||||
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
|
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
|
||||||
|
|
||||||
|
@ -748,15 +751,77 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
MCSymbol *TOCEntry =
|
MCSymbol *TOCEntry =
|
||||||
lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO, *this));
|
lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO, *this));
|
||||||
|
|
||||||
|
const MCSymbolRefExpr::VariantKind VK =
|
||||||
|
IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC;
|
||||||
const MCExpr *Exp =
|
const MCExpr *Exp =
|
||||||
MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC,
|
MCSymbolRefExpr::create(TOCEntry, VK, OutContext);
|
||||||
OutContext);
|
|
||||||
TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
|
TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
|
||||||
EmitToStreamer(*OutStreamer, TmpInst);
|
EmitToStreamer(*OutStreamer, TmpInst);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case PPC::ADDIStocHA: {
|
||||||
|
assert((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large) &&
|
||||||
|
"This pseudo should only be selected for 32-bit large code model on"
|
||||||
|
" AIX.");
|
||||||
|
|
||||||
|
// Transform %rd = ADDIStocHA %rA, @sym(%r2)
|
||||||
|
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
|
||||||
|
|
||||||
|
// Change the opcode to ADDIS.
|
||||||
|
TmpInst.setOpcode(PPC::ADDIS);
|
||||||
|
|
||||||
|
const MachineOperand &MO = MI->getOperand(2);
|
||||||
|
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
|
||||||
|
"Invalid operand for ADDIStocHA.");
|
||||||
|
|
||||||
|
// Map the machine operand to its corresponding MCSymbol.
|
||||||
|
MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
|
||||||
|
|
||||||
|
// Always use TOC on AIX. Map the global address operand to be a reference
|
||||||
|
// to the TOC entry we will synthesize later. 'TOCEntry' is a label used to
|
||||||
|
// reference the storage allocated in the TOC which contains the address of
|
||||||
|
// 'MOSymbol'.
|
||||||
|
MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
|
||||||
|
const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry,
|
||||||
|
MCSymbolRefExpr::VK_PPC_U,
|
||||||
|
OutContext);
|
||||||
|
TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
|
||||||
|
EmitToStreamer(*OutStreamer, TmpInst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case PPC::LWZtocL: {
|
||||||
|
assert(IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large &&
|
||||||
|
"This pseudo should only be selected for 32-bit large code model on"
|
||||||
|
" AIX.");
|
||||||
|
|
||||||
|
// Transform %rd = LWZtocL @sym, %rs.
|
||||||
|
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
|
||||||
|
|
||||||
|
// Change the opcode to lwz.
|
||||||
|
TmpInst.setOpcode(PPC::LWZ);
|
||||||
|
|
||||||
|
const MachineOperand &MO = MI->getOperand(1);
|
||||||
|
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
|
||||||
|
"Invalid operand for LWZtocL.");
|
||||||
|
|
||||||
|
// Map the machine operand to its corresponding MCSymbol.
|
||||||
|
MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
|
||||||
|
|
||||||
|
// Always use TOC on AIX. Map the global address operand to be a reference
|
||||||
|
// to the TOC entry we will synthesize later. 'TOCEntry' is a label used to
|
||||||
|
// reference the storage allocated in the TOC which contains the address of
|
||||||
|
// 'MOSymbol'.
|
||||||
|
MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
|
||||||
|
const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry,
|
||||||
|
MCSymbolRefExpr::VK_PPC_L,
|
||||||
|
OutContext);
|
||||||
|
TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
|
||||||
|
EmitToStreamer(*OutStreamer, TmpInst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
case PPC::ADDIStocHA8: {
|
case PPC::ADDIStocHA8: {
|
||||||
|
assert(!IsDarwin && "TOC is an ELF/XCOFF construct");
|
||||||
|
|
||||||
// Transform %xd = ADDIStocHA8 %x2, @sym
|
// Transform %xd = ADDIStocHA8 %x2, @sym
|
||||||
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
|
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
|
||||||
|
|
||||||
|
@ -778,9 +843,11 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
(MO.isCPI() && TM.getCodeModel() == CodeModel::Large))
|
(MO.isCPI() && TM.getCodeModel() == CodeModel::Large))
|
||||||
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
|
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
|
||||||
|
|
||||||
|
const MCSymbolRefExpr::VariantKind VK =
|
||||||
|
IsAIX ? MCSymbolRefExpr::VK_PPC_U : MCSymbolRefExpr::VK_PPC_TOC_HA;
|
||||||
|
|
||||||
const MCExpr *Exp =
|
const MCExpr *Exp =
|
||||||
MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_HA,
|
MCSymbolRefExpr::create(MOSymbol, VK, OutContext);
|
||||||
OutContext);
|
|
||||||
|
|
||||||
if (!MO.isJTI() && MO.getOffset())
|
if (!MO.isJTI() && MO.getOffset())
|
||||||
Exp = MCBinaryExpr::createAdd(Exp,
|
Exp = MCBinaryExpr::createAdd(Exp,
|
||||||
|
@ -793,6 +860,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case PPC::LDtocL: {
|
case PPC::LDtocL: {
|
||||||
|
assert(!IsDarwin && "TOC is an ELF/XCOFF construct");
|
||||||
|
|
||||||
// Transform %xd = LDtocL @sym, %xs
|
// Transform %xd = LDtocL @sym, %xs
|
||||||
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
|
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
|
||||||
|
|
||||||
|
@ -817,9 +886,10 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large)
|
if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large)
|
||||||
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
|
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
|
||||||
|
|
||||||
|
const MCSymbolRefExpr::VariantKind VK =
|
||||||
|
IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO;
|
||||||
const MCExpr *Exp =
|
const MCExpr *Exp =
|
||||||
MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_LO,
|
MCSymbolRefExpr::create(MOSymbol, VK, OutContext);
|
||||||
OutContext);
|
|
||||||
TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
|
TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
|
||||||
EmitToStreamer(*OutStreamer, TmpInst);
|
EmitToStreamer(*OutStreamer, TmpInst);
|
||||||
return;
|
return;
|
||||||
|
@ -855,8 +925,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
const GlobalValue *GValue = MO.getGlobal();
|
const GlobalValue *GValue = MO.getGlobal();
|
||||||
MCSymbol *MOSymbol = getSymbol(GValue);
|
MCSymbol *MOSymbol = getSymbol(GValue);
|
||||||
const MCExpr *SymGotTprel =
|
const MCExpr *SymGotTprel =
|
||||||
MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA,
|
MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA,
|
||||||
OutContext);
|
OutContext);
|
||||||
EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
|
EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
|
||||||
.addReg(MI->getOperand(0).getReg())
|
.addReg(MI->getOperand(0).getReg())
|
||||||
.addReg(MI->getOperand(1).getReg())
|
.addReg(MI->getOperand(1).getReg())
|
||||||
|
|
|
@ -328,6 +328,7 @@ bool PPCInstrInfo::isReallyTriviallyReMaterializable(const MachineInstr &MI,
|
||||||
case PPC::LIS:
|
case PPC::LIS:
|
||||||
case PPC::LIS8:
|
case PPC::LIS8:
|
||||||
case PPC::QVGPCI:
|
case PPC::QVGPCI:
|
||||||
|
case PPC::ADDIStocHA:
|
||||||
case PPC::ADDIStocHA8:
|
case PPC::ADDIStocHA8:
|
||||||
case PPC::ADDItocL:
|
case PPC::ADDItocL:
|
||||||
case PPC::LOAD_STACK_GUARD:
|
case PPC::LOAD_STACK_GUARD:
|
||||||
|
|
|
@ -1,21 +1,45 @@
|
||||||
; RUN: llc -mtriple powerpc-ibm-aix-xcoff \
|
; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc-ibm-aix-xcoff \
|
||||||
; RUN: -code-model=small < %s | FileCheck %s
|
; RUN: -code-model=small < %s | FileCheck %s --check-prefixes=CHECK,SMALL
|
||||||
|
|
||||||
|
; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc-ibm-aix-xcoff \
|
||||||
|
; RUN: -code-model=large < %s | FileCheck %s --check-prefixes=CHECK,LARGE
|
||||||
|
|
||||||
@b = common global i32 0
|
|
||||||
@a = common global i32 0
|
@a = common global i32 0
|
||||||
|
|
||||||
define void @test() {
|
define i32 @test_load() {
|
||||||
%1 = load i32, i32* @b
|
entry:
|
||||||
store i32 %1, i32* @a
|
%0 = load i32, i32* @a
|
||||||
|
ret i32 %0
|
||||||
|
}
|
||||||
|
|
||||||
|
; SMALL-LABEL: .test_load:{{$}}
|
||||||
|
; SMALL: lwz [[REG1:[0-9]+]], LC0(2)
|
||||||
|
; SMALL: lwz [[REG2:[0-9]+]], 0([[REG1]])
|
||||||
|
; SMALL: blr
|
||||||
|
|
||||||
|
; LARGE-LABEL: .test_load:{{$}}
|
||||||
|
; LARGE: addis [[REG1:[0-9]+]], LC0@u(2)
|
||||||
|
; LARGE: lwz [[REG2:[0-9]+]], LC0@l([[REG1]])
|
||||||
|
; LARGE: lwz [[REG3:[0-9]+]], 0([[REG2]])
|
||||||
|
; LARGE: blr
|
||||||
|
|
||||||
|
@b = common global i32 0
|
||||||
|
|
||||||
|
define void @test_store(i32 %0) {
|
||||||
|
store i32 %0, i32* @b
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; CHECK-LABEL: test
|
; SMALL-LABEL: .test_store:{{$}}
|
||||||
; CHECK-DAG: lwz [[REG1:[0-9]+]], LC0(2)
|
; SMALL: lwz [[REG1:[0-9]+]], LC1(2)
|
||||||
; CHECK-DAG: lwz [[REG2:[0-9]+]], LC1(2)
|
; SMALL: stw [[REG2:[0-9]+]], 0([[REG1]])
|
||||||
; CHECK-DAG: lwz [[REG3:[0-9]+]], 0([[REG1]])
|
; SMALL: blr
|
||||||
; CHECK: stw [[REG3]], 0([[REG2]])
|
|
||||||
; CHECK: blr
|
; LARGE-LABEL: .test_store:{{$}}
|
||||||
|
; LARGE: addis [[REG1:[0-9]+]], LC1@u(2)
|
||||||
|
; LARGE: lwz [[REG2:[0-9]+]], LC1@l([[REG1]])
|
||||||
|
; LARGE: stw [[REG3:[0-9]+]], 0([[REG2]])
|
||||||
|
; LARGE: blr
|
||||||
|
|
||||||
; TODO Update test when TOC-entry emission lands.
|
; TODO Update test when TOC-entry emission lands.
|
||||||
; CHECK-NOT: .tc
|
; CHECK-NOT: .tc
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc64-ibm-aix-xcoff \
|
||||||
|
; RUN: -code-model=small < %s | FileCheck %s --check-prefixes=CHECK,SMALL
|
||||||
|
|
||||||
|
; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc64-ibm-aix-xcoff \
|
||||||
|
; RUN: -code-model=large < %s | FileCheck %s --check-prefixes=CHECK,LARGE
|
||||||
|
|
||||||
|
@a = common global i32 0
|
||||||
|
|
||||||
|
define zeroext i32 @test_load() {
|
||||||
|
entry:
|
||||||
|
%0 = load i32, i32* @a
|
||||||
|
ret i32 %0
|
||||||
|
}
|
||||||
|
|
||||||
|
; SMALL-LABEL: .test_load:{{$}}
|
||||||
|
; SMALL: ld [[REG1:[0-9]+]], LC0(2)
|
||||||
|
; SMALL: lwz [[REG2:[0-9]+]], 0([[REG1]])
|
||||||
|
; SMALL: blr
|
||||||
|
|
||||||
|
; LARGE-LABEL: .test_load:{{$}}
|
||||||
|
; LARGE: addis [[REG1:[0-9]+]], LC0@u(2)
|
||||||
|
; LARGE: ld [[REG2:[0-9]+]], LC0@l([[REG1]])
|
||||||
|
; LARGE: lwz [[REG3:[0-9]+]], 0([[REG2]])
|
||||||
|
; LARGE: blr
|
||||||
|
|
||||||
|
@b = common global i32 0
|
||||||
|
|
||||||
|
define void @test_store(i32 zeroext %0) {
|
||||||
|
store i32 %0, i32* @b
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; SMALL-LABEL: .test_store:{{$}}
|
||||||
|
; SMALL: ld [[REG1:[0-9]+]], LC1(2)
|
||||||
|
; SMALL: stw [[REG2:[0-9]+]], 0([[REG1]])
|
||||||
|
; SMALL: blr
|
||||||
|
|
||||||
|
; LARGE-LABEL: .test_store:{{$}}
|
||||||
|
; LARGE: addis [[REG1:[0-9]+]], LC1@u(2)
|
||||||
|
; LARGE: ld [[REG2:[0-9]+]], LC1@l([[REG1]])
|
||||||
|
; LARGE: stw [[REG3:[0-9]+]], 0([[REG2]])
|
||||||
|
; LARGE: blr
|
||||||
|
|
||||||
|
; TODO Update test when TOC-entry emission lands.
|
||||||
|
; CHECK-NOT: .tc
|
Loading…
Reference in New Issue