From 422b0cee7a32636303398d8788f98a59bf15381c Mon Sep 17 00:00:00 2001 From: Nate Begeman Date: Wed, 16 Nov 2005 00:48:01 +0000 Subject: [PATCH] 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 --- lib/Target/PowerPC/PPCAsmPrinter.cpp | 4 ++++ lib/Target/PowerPC/PPCCodeEmitter.cpp | 2 +- lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 23 +++++++++++++++++------ lib/Target/PowerPC/PPCISelPattern.cpp | 9 +++------ lib/Target/PowerPC/PPCInstrInfo.td | 13 ++++++------- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index fd3c13ed691..9ef6579d304 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 6a8df47b50d..d576b79eb71 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 64161b59e21..ad0a0a02193 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(N->getOperand(1))) { - CallOpcode = PPC::CALLpcrel; + CallOpcode = PPC::BL; CallOperands.push_back(CurDAG->getTargetGlobalAddress(GASD->getGlobal(), MVT::i32)); } else if (ExternalSymbolSDNode *ESSDN = dyn_cast(N->getOperand(1))) { - CallOpcode = PPC::CALLpcrel; + CallOpcode = PPC::BL; CallOperands.push_back(N->getOperand(1)); + } else if (isa(N->getOperand(1)) && + isCallCompatibleAddress(cast(N->getOperand(1)))) { + ConstantSDNode *C = cast(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 1a9d09c64bc..628295c095c 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(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(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 73362a9846f..f65de6115df 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -128,6 +128,9 @@ def s16immX4 : Operand { // Multiply imm by 4 before printing. def target : Operand { let PrintMethod = "printBranchOperand"; } +def aaddr : Operand { + let PrintMethod = "printAbsAddrOperand"; +} def piclabel: Operand { 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