Index: llvm/lib/Target/Xtensa/XtensaISelLowering.h =================================================================== --- llvm/lib/Target/Xtensa/XtensaISelLowering.h +++ llvm/lib/Target/Xtensa/XtensaISelLowering.h @@ -46,6 +46,7 @@ explicit XtensaTargetLowering(const TargetMachine &TM, const XtensaSubtarget &STI); + bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override; const char *getTargetNodeName(unsigned Opcode) const override; @@ -73,6 +74,10 @@ SDValue LowerImmediate(SDValue Op, SelectionDAG &DAG) const; SDValue LowerImmediateFP(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerBlockAddress(BlockAddressSDNode *Node, SelectionDAG &DAG) const; + SDValue LowerJumpTable(JumpTableSDNode *JT, SelectionDAG &DAG) const; + SDValue LowerConstantPool(ConstantPoolSDNode *CP, SelectionDAG &DAG) const; SDValue getAddrPCRel(SDValue Op, SelectionDAG &DAG) const; Index: llvm/lib/Target/Xtensa/XtensaISelLowering.cpp =================================================================== --- llvm/lib/Target/Xtensa/XtensaISelLowering.cpp +++ llvm/lib/Target/Xtensa/XtensaISelLowering.cpp @@ -43,6 +43,7 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &tm, const XtensaSubtarget &STI) : TargetLowering(tm), Subtarget(STI) { + MVT PtrVT = MVT::i32; // Set up the register classes. addRegisterClass(MVT::i32, &Xtensa::ARRegClass); @@ -68,10 +69,22 @@ setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); } + // Handle the various types of symbolic address. + setOperationAction(ISD::ConstantPool, PtrVT, Custom); + setOperationAction(ISD::GlobalAddress, PtrVT, Custom); + setOperationAction(ISD::BlockAddress, PtrVT, Custom); + setOperationAction(ISD::JumpTable, PtrVT, Custom); + // Compute derived properties from the register classes computeRegisterProperties(STI.getRegisterInfo()); } +bool XtensaTargetLowering::isOffsetFoldingLegal( + const GlobalAddressSDNode *GA) const { + // The Xtensa target isn't yet aware of offsets. + return false; +} + bool XtensaTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const { return false; @@ -571,6 +584,86 @@ return Op; } +SDValue XtensaTargetLowering::LowerGlobalAddress(SDValue Op, + SelectionDAG &DAG) const { + // Reloc::Model RM = DAG.getTarget().getRelocationModel(); + SDLoc DL(Op); + + if (GlobalAddressSDNode *G = dyn_cast(Op)) { + auto PtrVt = getPointerTy(DAG.getDataLayout()); + const GlobalValue *GV = G->getGlobal(); + + // Check Op SDNode users + // If there are only CALL nodes, don't expand Global Address + SDNode &OpNode = *Op.getNode(); + bool Val = false; + for (SDNode::use_iterator UI = OpNode.use_begin(); UI != OpNode.use_end(); + ++UI) { + SDNode &User = *UI.getUse().getUser(); + unsigned OpCode = User.getOpcode(); + if (OpCode != XtensaISD::CALL) { + Val = true; + break; + } + } + if (!Val) { + SDValue TargAddr = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVt, + 0, 0 /* TargetFlags */); + return TargAddr; + } + + SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVt, Align(4)); + SDValue CPWrap = getAddrPCRel(CPAddr, DAG); + + return CPWrap; + } + llvm_unreachable("invalid global addresses to lower"); +} + +SDValue XtensaTargetLowering::LowerBlockAddress(BlockAddressSDNode *Node, + SelectionDAG &DAG) const { + const BlockAddress *BA = Node->getBlockAddress(); + EVT PtrVT = getPointerTy(DAG.getDataLayout()); + + XtensaConstantPoolValue *CPV = + XtensaConstantPoolConstant::Create(BA, 0, XtensaCP::CPBlockAddress, 0); + SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4)); + + SDValue CPWrap = getAddrPCRel(CPAddr, DAG); + return CPWrap; +} + +SDValue XtensaTargetLowering::LowerJumpTable(JumpTableSDNode *JT, + SelectionDAG &DAG) const { + SDLoc DL(JT); + EVT PtrVt = getPointerTy(DAG.getDataLayout()); + + // Create a constant pool entry for the callee address + XtensaConstantPoolValue *CPV = + XtensaConstantPoolJumpTable::Create(*DAG.getContext(), JT->getIndex()); + + // Get the address of the callee into a register + SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVt, Align(4)); + SDValue CPWrap = getAddrPCRel(CPAddr, DAG); + + return CPWrap; +} + +SDValue XtensaTargetLowering::LowerConstantPool(ConstantPoolSDNode *CP, + SelectionDAG &DAG) const { + EVT PtrVT = getPointerTy(DAG.getDataLayout()); + + SDValue Result; + if (CP->isMachineConstantPoolEntry()) + Result = + DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT, CP->getAlign()); + else + Result = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, CP->getAlign(), + CP->getOffset()); + + return getAddrPCRel(Result, DAG); +} + SDValue XtensaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { @@ -578,6 +671,14 @@ return LowerImmediate(Op, DAG); case ISD::ConstantFP: return LowerImmediateFP(Op, DAG); + case ISD::GlobalAddress: + return LowerGlobalAddress(Op, DAG); + case ISD::BlockAddress: + return LowerBlockAddress(cast(Op), DAG); + case ISD::JumpTable: + return LowerJumpTable(cast(Op), DAG); + case ISD::ConstantPool: + return LowerConstantPool(cast(Op), DAG); default: llvm_unreachable("Unexpected node to lower"); } Index: llvm/lib/Target/Xtensa/XtensaMCInstLower.h =================================================================== --- llvm/lib/Target/Xtensa/XtensaMCInstLower.h +++ llvm/lib/Target/Xtensa/XtensaMCInstLower.h @@ -39,6 +39,10 @@ MCOperand lowerOperand(const MachineOperand &MO, unsigned Offset = 0) const; private: + MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const; + + MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const; + MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const; MCOperand LowerSymbolOperand(const MachineOperand &MO, Index: llvm/lib/Target/Xtensa/XtensaMCInstLower.cpp =================================================================== --- llvm/lib/Target/Xtensa/XtensaMCInstLower.cpp +++ llvm/lib/Target/Xtensa/XtensaMCInstLower.cpp @@ -28,6 +28,16 @@ XtensaAsmPrinter &asmPrinter) : Ctx(ctx), Printer(asmPrinter) {} +MCSymbol * +XtensaMCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { + return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); +} + +MCSymbol * +XtensaMCInstLower::GetJumpTableSymbol(const MachineOperand &MO) const { + return Printer.GetJTISymbol(MO.getIndex()); +} + MCSymbol * XtensaMCInstLower::GetConstantPoolIndexSymbol(const MachineOperand &MO) const { // Create a symbol for the name. @@ -53,6 +63,13 @@ Symbol = Printer.GetBlockAddressSymbol(MO.getBlockAddress()); Offset += MO.getOffset(); break; + case MachineOperand::MO_ExternalSymbol: + Symbol = GetExternalSymbolSymbol(MO); + Offset += MO.getOffset(); + break; + case MachineOperand::MO_JumpTableIndex: + Symbol = GetJumpTableSymbol(MO); + break; case MachineOperand::MO_ConstantPoolIndex: Symbol = GetConstantPoolIndexSymbol(MO); Offset += MO.getOffset(); @@ -91,7 +108,12 @@ return MCOperand::createImm(MO.getImm() + Offset); case MachineOperand::MO_RegisterMask: break; + case MachineOperand::MO_MachineBasicBlock: + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: + case MachineOperand::MO_JumpTableIndex: case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_BlockAddress: return LowerSymbolOperand(MO, MOTy, Offset); default: llvm_unreachable("unknown operand type");