aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2005-11-16 00:48:01 +0000
committerNate Begeman <natebegeman@mac.com>2005-11-16 00:48:01 +0000
commit422b0cee7a32636303398d8788f98a59bf15381c (patch)
treeded4c66bb7c76b6ac954d1a5cbea8fb7d316b7b1
parent427189ad5108f34126316cd475ff236ab0fb41f8 (diff)
Patch to clean up function call pseudos and support the BLA instruction,
which branches to an absolute address. This is required to support objc direct dispatch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24370 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/PowerPC/PPCAsmPrinter.cpp4
-rw-r--r--lib/Target/PowerPC/PPCCodeEmitter.cpp2
-rw-r--r--lib/Target/PowerPC/PPCISelDAGToDAG.cpp23
-rw-r--r--lib/Target/PowerPC/PPCISelPattern.cpp9
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td13
5 files changed, 31 insertions, 20 deletions
diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp
index fd3c13ed69..9ef6579d30 100644
--- a/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -152,6 +152,10 @@ namespace {
TM.getInstrInfo()->isCall(MI->getOpcode()));
}
}
+ void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo,
+ MVT::ValueType VT) {
+ O << (int)MI->getOperand(OpNo).getImmedValue()*4;
+ }
void printPICLabel(const MachineInstr *MI, unsigned OpNo,
MVT::ValueType VT) {
// FIXME: should probably be converted to cout.width and cout.fill
diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp
index 6a8df47b50..d576b79eb7 100644
--- a/lib/Target/PowerPC/PPCCodeEmitter.cpp
+++ b/lib/Target/PowerPC/PPCCodeEmitter.cpp
@@ -196,7 +196,7 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) {
MO.getGlobal()->hasWeakLinkage() ||
MO.getGlobal()->isExternal();
unsigned Reloc = 0;
- if (MI.getOpcode() == PPC::CALLpcrel)
+ if (MI.getOpcode() == PPC::BL)
Reloc = PPC::reloc_pcrel_bx;
else {
switch (MI.getOpcode()) {
diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 64161b59e2..ad0a0a0219 100644
--- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -735,6 +735,14 @@ SDOperand PPCDAGToDAGISel::SelectSETCC(SDOperand Op) {
return SDOperand(N, 0);
}
+/// isCallCompatibleAddress - Return true if the specified 32-bit value is
+/// representable in the immediate field of a Bx instruction.
+static bool isCallCompatibleAddress(ConstantSDNode *C) {
+ int Addr = C->getValue();
+ if (Addr & 3) return false; // Low 2 bits are implicitly zero.
+ return (Addr << 6 >> 6) == Addr; // Top 6 bits have to be sext of immediate.
+}
+
SDOperand PPCDAGToDAGISel::SelectCALL(SDOperand Op) {
SDNode *N = Op.Val;
SDOperand Chain = Select(N->getOperand(0));
@@ -744,13 +752,18 @@ SDOperand PPCDAGToDAGISel::SelectCALL(SDOperand Op) {
if (GlobalAddressSDNode *GASD =
dyn_cast<GlobalAddressSDNode>(N->getOperand(1))) {
- CallOpcode = PPC::CALLpcrel;
+ CallOpcode = PPC::BL;
CallOperands.push_back(CurDAG->getTargetGlobalAddress(GASD->getGlobal(),
MVT::i32));
} else if (ExternalSymbolSDNode *ESSDN =
dyn_cast<ExternalSymbolSDNode>(N->getOperand(1))) {
- CallOpcode = PPC::CALLpcrel;
+ CallOpcode = PPC::BL;
CallOperands.push_back(N->getOperand(1));
+ } else if (isa<ConstantSDNode>(N->getOperand(1)) &&
+ isCallCompatibleAddress(cast<ConstantSDNode>(N->getOperand(1)))) {
+ ConstantSDNode *C = cast<ConstantSDNode>(N->getOperand(1));
+ CallOpcode = PPC::BLA;
+ CallOperands.push_back(getI32Imm((int)C->getValue() >> 2));
} else {
// Copy the callee address into the CTR register.
SDOperand Callee = Select(N->getOperand(1));
@@ -759,11 +772,9 @@ SDOperand PPCDAGToDAGISel::SelectCALL(SDOperand Op) {
// Copy the callee address into R12 on darwin.
SDOperand R12 = CurDAG->getRegister(PPC::R12, MVT::i32);
Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R12, Callee);
-
- CallOperands.push_back(getI32Imm(20)); // Information to encode indcall
- CallOperands.push_back(getI32Imm(0)); // Information to encode indcall
+
CallOperands.push_back(R12);
- CallOpcode = PPC::CALLindirect;
+ CallOpcode = PPC::BCTRL;
}
unsigned GPR_idx = 0, FPR_idx = 0;
diff --git a/lib/Target/PowerPC/PPCISelPattern.cpp b/lib/Target/PowerPC/PPCISelPattern.cpp
index 1a9d09c64b..628295c095 100644
--- a/lib/Target/PowerPC/PPCISelPattern.cpp
+++ b/lib/Target/PowerPC/PPCISelPattern.cpp
@@ -842,18 +842,15 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
// Emit the correct call instruction based on the type of symbol called.
if (GlobalAddressSDNode *GASD =
dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) {
- CallMI = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(),
- true);
+ CallMI = BuildMI(PPC::BL, 1).addGlobalAddress(GASD->getGlobal(), true);
} else if (ExternalSymbolSDNode *ESSDN =
dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) {
- CallMI = BuildMI(PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(),
- true);
+ CallMI = BuildMI(PPC::BL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
} else {
Tmp1 = SelectExpr(N.getOperand(1));
BuildMI(BB, PPC::MTCTR, 1).addReg(Tmp1);
BuildMI(BB, PPC::OR4, 2, PPC::R12).addReg(Tmp1).addReg(Tmp1);
- CallMI = BuildMI(PPC::CALLindirect, 3).addImm(20).addImm(0)
- .addReg(PPC::R12);
+ CallMI = BuildMI(PPC::BCTRL, 1).addReg(PPC::R12);
}
// Load the register args to virtual regs
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index 73362a9846..f65de6115d 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/lib/Target/PowerPC/PPCInstrInfo.td
@@ -128,6 +128,9 @@ def s16immX4 : Operand<i32> { // Multiply imm by 4 before printing.
def target : Operand<i32> {
let PrintMethod = "printBranchOperand";
}
+def aaddr : Operand<i32> {
+ let PrintMethod = "printAbsAddrOperand";
+}
def piclabel: Operand<i32> {
let PrintMethod = "printPICLabel";
}
@@ -186,9 +189,6 @@ let isBranch = 1, isTerminator = 1 in {
target:$true, target:$false),
"; COND_BRANCH", []>;
def B : IForm<18, 0, 0, (ops target:$func), "b $func", BrB>;
-//def BA : IForm<18, 1, 0, (ops target:$func), "ba $func", BrB>;
- def BL : IForm<18, 0, 1, (ops target:$func), "bl $func", BrB>;
-//def BLA : IForm<18, 1, 1, (ops target:$func), "bla $func", BrB>;
// FIXME: 4*CR# needs to be added to the BI field!
// This will only work for CR0 as it stands now
@@ -217,10 +217,9 @@ let isCall = 1,
LR,CTR,
CR0,CR1,CR5,CR6,CR7] in {
// Convenient aliases for call instructions
- def CALLpcrel : IForm<18, 0, 1, (ops target:$func, variable_ops),
- "bl $func", BrB>;
- def CALLindirect : XLForm_2_ext<19, 528, 20, 0, 1,
- (ops variable_ops), "bctrl", BrB>;
+ def BL : IForm<18, 0, 1, (ops target:$func, variable_ops), "bl $func", BrB>;
+ def BLA : IForm<18, 1, 1, (ops aaddr:$func, variable_ops), "bla $func", BrB>;
+ def BCTRL : XLForm_2_ext<19, 528, 20, 0, 1, (ops variable_ops), "bctrl", BrB>;
}
// D-Form instructions. Most instructions that perform an operation on a