Skip to content

[Xtensa] Lower GlobalAddress/BlockAddress/JumpTable #95256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 58 additions & 13 deletions llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
Expand All @@ -42,26 +43,48 @@ getModifierVariantKind(XtensaCP::XtensaCPModifier Modifier) {
}

void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) {
MCInst LoweredMI;
lowerToMCInst(MI, LoweredMI);
EmitToStreamer(*OutStreamer, LoweredMI);
unsigned Opc = MI->getOpcode();

switch (Opc) {
case Xtensa::BR_JT:
EmitToStreamer(
*OutStreamer,
MCInstBuilder(Xtensa::JX).addReg(MI->getOperand(0).getReg()));
return;
default:
MCInst LoweredMI;
lowerToMCInst(MI, LoweredMI);
EmitToStreamer(*OutStreamer, LoweredMI);
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a default?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created "default" case

}

void XtensaAsmPrinter::emitMachineConstantPoolValue(
MachineConstantPoolValue *MCPV) {
XtensaConstantPoolValue *ACPV = static_cast<XtensaConstantPoolValue *>(MCPV);
MCSymbol *MCSym;

assert(ACPV->isExtSymbol() && "unrecognized constant pool value");

XtensaConstantPoolSymbol *XtensaSym = cast<XtensaConstantPoolSymbol>(ACPV);
const char *Sym = XtensaSym->getSymbol();
std::string SymName(Sym);

if (XtensaSym->isPrivateLinkage())
SymName = ".L" + SymName;
if (ACPV->isBlockAddress()) {
const BlockAddress *BA =
cast<XtensaConstantPoolConstant>(ACPV)->getBlockAddress();
MCSym = GetBlockAddressSymbol(BA);
} else if (ACPV->isJumpTable()) {
unsigned Idx = cast<XtensaConstantPoolJumpTable>(ACPV)->getIndex();
MCSym = this->GetJTISymbol(Idx, false);
} else {
assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
XtensaConstantPoolSymbol *XtensaSym = cast<XtensaConstantPoolSymbol>(ACPV);
const char *SymName = XtensaSym->getSymbol();

if (XtensaSym->isPrivateLinkage()) {
const DataLayout &DL = getDataLayout();
MCSym = OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +
SymName);
Comment on lines +81 to +82
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think something further down is supposed to append the prefix for you but I'm no MC expert

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've found that that "DL.getPrivateGlobalPrefix()" code returns appropriate prefix for Xtensa for private linkage case and such code is used for similar purposes in ARM backend and other backends. So, I used it to substitute hardcoded ".L" prefix.

} else {
MCSym = OutContext.getOrCreateSymbol(SymName);
}
}

MCSym = GetExternalSymbolSymbol(StringRef(SymName));
MCSymbol *LblSym = GetCPISymbol(ACPV->getLabelId());
auto *TS =
static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
Expand All @@ -71,7 +94,7 @@ void XtensaAsmPrinter::emitMachineConstantPoolValue(
std::string SymName(MCSym->getName());
StringRef Modifier = ACPV->getModifierText();
SymName += Modifier;
MCSym = GetExternalSymbolSymbol(StringRef(SymName));
MCSym = OutContext.getOrCreateSymbol(SymName);
}

const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, VK, OutContext);
Expand Down Expand Up @@ -140,6 +163,10 @@ XtensaAsmPrinter::GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
return GetCPISymbol(MO.getIndex());
}

MCSymbol *XtensaAsmPrinter::GetJumpTableSymbol(const MachineOperand &MO) const {
return GetJTISymbol(MO.getIndex());
}

MCOperand
XtensaAsmPrinter::LowerSymbolOperand(const MachineOperand &MO,
MachineOperand::MachineOperandType MOTy,
Expand All @@ -152,6 +179,20 @@ XtensaAsmPrinter::LowerSymbolOperand(const MachineOperand &MO,
Symbol = getSymbol(MO.getGlobal());
Offset += MO.getOffset();
break;
case MachineOperand::MO_MachineBasicBlock:
Symbol = MO.getMBB()->getSymbol();
break;
case MachineOperand::MO_BlockAddress:
Symbol = GetBlockAddressSymbol(MO.getBlockAddress());
Offset += MO.getOffset();
break;
case MachineOperand::MO_ExternalSymbol:
Symbol = GetExternalSymbolSymbol(MO.getSymbolName());
Offset += MO.getOffset();
break;
case MachineOperand::MO_JumpTableIndex:
Symbol = GetJumpTableSymbol(MO);
break;
case MachineOperand::MO_ConstantPoolIndex:
Symbol = GetConstantPoolIndexSymbol(MO);
Offset += MO.getOffset();
Expand Down Expand Up @@ -191,6 +232,10 @@ MCOperand XtensaAsmPrinter::lowerOperand(const MachineOperand &MO,
case MachineOperand::MO_RegisterMask:
break;
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_MachineBasicBlock:
case MachineOperand::MO_BlockAddress:
case MachineOperand::MO_ExternalSymbol:
case MachineOperand::MO_JumpTableIndex:
case MachineOperand::MO_ConstantPoolIndex:
return LowerSymbolOperand(MO, MOTy, Offset);
default:
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaAsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class LLVM_LIBRARY_VISIBILITY XtensaAsmPrinter : public AsmPrinter {

MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const;

MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const;

MCOperand LowerSymbolOperand(const MachineOperand &MO,
MachineOperand::MachineOperandType MOTy,
unsigned Offset) const;
Expand Down
94 changes: 94 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
}

setOperationAction(ISD::ConstantPool, PtrVT, Custom);
setOperationAction(ISD::GlobalAddress, PtrVT, Custom);
setOperationAction(ISD::BlockAddress, PtrVT, Custom);
setOperationAction(ISD::JumpTable, PtrVT, Custom);

// Expand jump table branches as address arithmetic followed by an
// indirect jump.
setOperationAction(ISD::BR_JT, MVT::Other, Custom);

setOperationPromotedToType(ISD::BR_CC, MVT::i1, MVT::i32);
setOperationAction(ISD::BR_CC, MVT::i32, Legal);
setOperationAction(ISD::BR_CC, MVT::i64, Expand);
setOperationAction(ISD::BR_CC, MVT::f32, Expand);

// Implement custom stack allocations
setOperationAction(ISD::DYNAMIC_STACKALLOC, PtrVT, Custom);
Expand All @@ -88,6 +100,12 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
computeRegisterProperties(STI.getRegisterInfo());
}

bool XtensaTargetLowering::isOffsetFoldingLegal(
const GlobalAddressSDNode *GA) const {
// The Xtensa target isn't yet aware of offsets.
return false;
}

//===----------------------------------------------------------------------===//
// Calling conventions
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -519,6 +537,72 @@ SDValue XtensaTargetLowering::LowerImmediate(SDValue Op,
return Op;
}

SDValue XtensaTargetLowering::LowerGlobalAddress(SDValue Op,
SelectionDAG &DAG) const {
const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Op);
SDLoc DL(Op);
auto PtrVT = Op.getValueType();
const GlobalValue *GV = G->getGlobal();

SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, Align(4));
SDValue CPWrap = getAddrPCRel(CPAddr, DAG);

return CPWrap;
}

SDValue XtensaTargetLowering::LowerBlockAddress(SDValue Op,
SelectionDAG &DAG) const {
BlockAddressSDNode *Node = cast<BlockAddressSDNode>(Op);
const BlockAddress *BA = Node->getBlockAddress();
EVT PtrVT = Op.getValueType();

XtensaConstantPoolValue *CPV =
XtensaConstantPoolConstant::Create(BA, 0, XtensaCP::CPBlockAddress);
SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4));
SDValue CPWrap = getAddrPCRel(CPAddr, DAG);

return CPWrap;
}

SDValue XtensaTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) const {
SDValue Chain = Op.getOperand(0);
SDValue Table = Op.getOperand(1);
SDValue Index = Op.getOperand(2);
SDLoc DL(Op);
JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
MachineFunction &MF = DAG.getMachineFunction();
const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
const DataLayout &TD = DAG.getDataLayout();
EVT PtrVT = Table.getValueType();
unsigned EntrySize = MJTI->getEntrySize(TD);

Index = DAG.getNode(ISD::MUL, DL, Index.getValueType(), Index,
DAG.getConstant(EntrySize, DL, Index.getValueType()));
SDValue Addr = DAG.getNode(ISD::ADD, DL, Index.getValueType(), Index, Table);
SDValue LD =
DAG.getLoad(PtrVT, DL, Chain, Addr,
MachinePointerInfo::getJumpTable(DAG.getMachineFunction()));

return DAG.getNode(XtensaISD::BR_JT, DL, MVT::Other, LD.getValue(1), LD,
TargetJT);
}

SDValue XtensaTargetLowering::LowerJumpTable(SDValue Op,
SelectionDAG &DAG) const {
JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
EVT PtrVT = Op.getValueType();

// 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));

return getAddrPCRel(CPAddr, DAG);
}

SDValue XtensaTargetLowering::getAddrPCRel(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
Expand Down Expand Up @@ -580,8 +664,16 @@ SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
SelectionDAG &DAG) const {
switch (Op.getOpcode()) {
case ISD::BR_JT:
return LowerBR_JT(Op, DAG);
case ISD::Constant:
return LowerImmediate(Op, DAG);
case ISD::GlobalAddress:
return LowerGlobalAddress(Op, DAG);
case ISD::BlockAddress:
return LowerBlockAddress(Op, DAG);
case ISD::JumpTable:
return LowerJumpTable(Op, DAG);
case ISD::ConstantPool:
return LowerConstantPool(cast<ConstantPoolSDNode>(Op), DAG);
case ISD::STACKSAVE:
Expand All @@ -597,6 +689,8 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,

const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
case XtensaISD::BR_JT:
return "XtensaISD::BR_JT";
case XtensaISD::CALL:
return "XtensaISD::CALL";
case XtensaISD::PCREL_WRAPPER:
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace llvm {
namespace XtensaISD {
enum {
FIRST_NUMBER = ISD::BUILTIN_OP_END,
BR_JT,

// Calls a function. Operand 0 is the chain operand and operand 1
// is the target address. The arguments start at operand 2.
Expand All @@ -43,6 +44,8 @@ class XtensaTargetLowering : public TargetLowering {
explicit XtensaTargetLowering(const TargetMachine &TM,
const XtensaSubtarget &STI);

bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;

const char *getTargetNodeName(unsigned Opcode) const override;

SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
Expand Down Expand Up @@ -71,8 +74,16 @@ class XtensaTargetLowering : public TargetLowering {
private:
const XtensaSubtarget &Subtarget;

SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;

SDValue LowerImmediate(SDValue Op, SelectionDAG &DAG) const;

SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;

SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;

SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;

SDValue LowerConstantPool(ConstantPoolSDNode *CP, SelectionDAG &DAG) const;

SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,15 @@ def BBSI : RRI8_Inst<0x07, (outs),
let imm8 = target;
}

def : Pat<(brcc SETGT, AR:$s, AR:$t, bb:$target),
(BLT AR:$t, AR:$s, bb:$target)>;
def : Pat<(brcc SETUGT, AR:$s, AR:$t, bb:$target),
(BLTU AR:$t, AR:$s, bb:$target)>;
def : Pat<(brcc SETLE, AR:$s, AR:$t, bb:$target),
(BGE AR:$t, AR:$s, bb:$target)>;
def : Pat<(brcc SETULE, AR:$s, AR:$t, bb:$target),
(BGEU AR:$t, AR:$s, bb:$target)>;

//===----------------------------------------------------------------------===//
// Call and jump instructions
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -471,6 +480,12 @@ def : Pat<(Xtensa_call (i32 texternalsym:$dst)),
def : Pat<(Xtensa_call AR:$dst),
(CALLX0 AR:$dst)>;

let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1, Size = 3 in {
def BR_JT: Pseudo<(outs), (ins AR:$s, i32imm:$jt),
"!br_jt_p, $s, $jt",
[(Xtensa_brjt AR:$s, tjumptable:$jt)]>;
}

//===----------------------------------------------------------------------===//
// Mem barrier instructions
//===----------------------------------------------------------------------===//
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaOperators.td
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def SDT_XtensaWrapPtr : SDTypeProfile<1, 1,
[SDTCisSameAs<0, 1>,
SDTCisPtrTy<0>]>;

def SDT_XtensaBrJT : SDTypeProfile<0, 2,
[SDTCisPtrTy<0>, SDTCisVT<1, i32>]>;
//===----------------------------------------------------------------------===//
// Node definitions
//===----------------------------------------------------------------------===//
Expand All @@ -34,3 +36,5 @@ def Xtensa_callseq_start: SDNode<"ISD::CALLSEQ_START", SDT_XtensaCallSeqStart,
def Xtensa_callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_XtensaCallSeqEnd,
[SDNPHasChain, SDNPSideEffect, SDNPOptInGlue,
SDNPOutGlue]>;

def Xtensa_brjt: SDNode<"XtensaISD::BR_JT", SDT_XtensaBrJT, [SDNPHasChain]>;
26 changes: 26 additions & 0 deletions llvm/test/CodeGen/Xtensa/blockaddress.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
; RUN: llc --mtriple=xtensa < %s | FileCheck %s

@addr = global ptr null

define void @test_blockaddress() {

store volatile ptr blockaddress(@test_blockaddress, %block), ptr @addr
; CHECK: .literal_position
; CHECK-NEXT: .literal .LCPI0_0, addr
; CHECK-NEXT: .literal .LCPI0_1, .Ltmp0
; CHECK-LABEL: test_blockaddress:
; CHECK: # %bb.0:
; CHECK-NEXT: l32r a8, .LCPI0_0
; CHECK-NEXT: l32r a9, .LCPI0_1
; CHECK-NEXT: s32i a9, a8, 0
; CHECK-NEXT: l32i a8, a8, 0
; CHECK-NEXT: jx a8
; CHECK-NEXT: .Ltmp0:
; CHECK-NEXT: .LBB0_1:

%val = load volatile ptr, ptr @addr
indirectbr ptr %val, [label %block]

block:
ret void
}
Loading
Loading