Skip to content

Commit 2ec76dd

Browse files
andreisfrAlexisPerry
authored andcommitted
[Xtensa] Lower GlobalAddress/BlockAddress/JumpTable (llvm#95256)
This patch implements lowering of the GlobalAddress, BlockAddress, JumpTable and BR_JT. Also patch adds legal support of the BR_CC operation for i32 type.
1 parent 43bc452 commit 2ec76dd

File tree

10 files changed

+359
-13
lines changed

10 files changed

+359
-13
lines changed

llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
2323
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
2424
#include "llvm/MC/MCExpr.h"
25+
#include "llvm/MC/MCInstBuilder.h"
2526
#include "llvm/MC/MCSectionELF.h"
2627
#include "llvm/MC/MCStreamer.h"
2728
#include "llvm/MC/MCSymbol.h"
@@ -42,26 +43,48 @@ getModifierVariantKind(XtensaCP::XtensaCPModifier Modifier) {
4243
}
4344

4445
void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) {
45-
MCInst LoweredMI;
46-
lowerToMCInst(MI, LoweredMI);
47-
EmitToStreamer(*OutStreamer, LoweredMI);
46+
unsigned Opc = MI->getOpcode();
47+
48+
switch (Opc) {
49+
case Xtensa::BR_JT:
50+
EmitToStreamer(
51+
*OutStreamer,
52+
MCInstBuilder(Xtensa::JX).addReg(MI->getOperand(0).getReg()));
53+
return;
54+
default:
55+
MCInst LoweredMI;
56+
lowerToMCInst(MI, LoweredMI);
57+
EmitToStreamer(*OutStreamer, LoweredMI);
58+
return;
59+
}
4860
}
4961

5062
void XtensaAsmPrinter::emitMachineConstantPoolValue(
5163
MachineConstantPoolValue *MCPV) {
5264
XtensaConstantPoolValue *ACPV = static_cast<XtensaConstantPoolValue *>(MCPV);
5365
MCSymbol *MCSym;
5466

55-
assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
56-
57-
XtensaConstantPoolSymbol *XtensaSym = cast<XtensaConstantPoolSymbol>(ACPV);
58-
const char *Sym = XtensaSym->getSymbol();
59-
std::string SymName(Sym);
60-
61-
if (XtensaSym->isPrivateLinkage())
62-
SymName = ".L" + SymName;
67+
if (ACPV->isBlockAddress()) {
68+
const BlockAddress *BA =
69+
cast<XtensaConstantPoolConstant>(ACPV)->getBlockAddress();
70+
MCSym = GetBlockAddressSymbol(BA);
71+
} else if (ACPV->isJumpTable()) {
72+
unsigned Idx = cast<XtensaConstantPoolJumpTable>(ACPV)->getIndex();
73+
MCSym = this->GetJTISymbol(Idx, false);
74+
} else {
75+
assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
76+
XtensaConstantPoolSymbol *XtensaSym = cast<XtensaConstantPoolSymbol>(ACPV);
77+
const char *SymName = XtensaSym->getSymbol();
78+
79+
if (XtensaSym->isPrivateLinkage()) {
80+
const DataLayout &DL = getDataLayout();
81+
MCSym = OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +
82+
SymName);
83+
} else {
84+
MCSym = OutContext.getOrCreateSymbol(SymName);
85+
}
86+
}
6387

64-
MCSym = GetExternalSymbolSymbol(StringRef(SymName));
6588
MCSymbol *LblSym = GetCPISymbol(ACPV->getLabelId());
6689
auto *TS =
6790
static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
@@ -71,7 +94,7 @@ void XtensaAsmPrinter::emitMachineConstantPoolValue(
7194
std::string SymName(MCSym->getName());
7295
StringRef Modifier = ACPV->getModifierText();
7396
SymName += Modifier;
74-
MCSym = GetExternalSymbolSymbol(StringRef(SymName));
97+
MCSym = OutContext.getOrCreateSymbol(SymName);
7598
}
7699

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

166+
MCSymbol *XtensaAsmPrinter::GetJumpTableSymbol(const MachineOperand &MO) const {
167+
return GetJTISymbol(MO.getIndex());
168+
}
169+
143170
MCOperand
144171
XtensaAsmPrinter::LowerSymbolOperand(const MachineOperand &MO,
145172
MachineOperand::MachineOperandType MOTy,
@@ -152,6 +179,20 @@ XtensaAsmPrinter::LowerSymbolOperand(const MachineOperand &MO,
152179
Symbol = getSymbol(MO.getGlobal());
153180
Offset += MO.getOffset();
154181
break;
182+
case MachineOperand::MO_MachineBasicBlock:
183+
Symbol = MO.getMBB()->getSymbol();
184+
break;
185+
case MachineOperand::MO_BlockAddress:
186+
Symbol = GetBlockAddressSymbol(MO.getBlockAddress());
187+
Offset += MO.getOffset();
188+
break;
189+
case MachineOperand::MO_ExternalSymbol:
190+
Symbol = GetExternalSymbolSymbol(MO.getSymbolName());
191+
Offset += MO.getOffset();
192+
break;
193+
case MachineOperand::MO_JumpTableIndex:
194+
Symbol = GetJumpTableSymbol(MO);
195+
break;
155196
case MachineOperand::MO_ConstantPoolIndex:
156197
Symbol = GetConstantPoolIndexSymbol(MO);
157198
Offset += MO.getOffset();
@@ -191,6 +232,10 @@ MCOperand XtensaAsmPrinter::lowerOperand(const MachineOperand &MO,
191232
case MachineOperand::MO_RegisterMask:
192233
break;
193234
case MachineOperand::MO_GlobalAddress:
235+
case MachineOperand::MO_MachineBasicBlock:
236+
case MachineOperand::MO_BlockAddress:
237+
case MachineOperand::MO_ExternalSymbol:
238+
case MachineOperand::MO_JumpTableIndex:
194239
case MachineOperand::MO_ConstantPoolIndex:
195240
return LowerSymbolOperand(MO, MOTy, Offset);
196241
default:

llvm/lib/Target/Xtensa/XtensaAsmPrinter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class LLVM_LIBRARY_VISIBILITY XtensaAsmPrinter : public AsmPrinter {
4444

4545
MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const;
4646

47+
MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const;
48+
4749
MCOperand LowerSymbolOperand(const MachineOperand &MO,
4850
MachineOperand::MachineOperandType MOTy,
4951
unsigned Offset) const;

llvm/lib/Target/Xtensa/XtensaISelLowering.cpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
7777
}
7878

7979
setOperationAction(ISD::ConstantPool, PtrVT, Custom);
80+
setOperationAction(ISD::GlobalAddress, PtrVT, Custom);
81+
setOperationAction(ISD::BlockAddress, PtrVT, Custom);
82+
setOperationAction(ISD::JumpTable, PtrVT, Custom);
83+
84+
// Expand jump table branches as address arithmetic followed by an
85+
// indirect jump.
86+
setOperationAction(ISD::BR_JT, MVT::Other, Custom);
87+
88+
setOperationPromotedToType(ISD::BR_CC, MVT::i1, MVT::i32);
89+
setOperationAction(ISD::BR_CC, MVT::i32, Legal);
90+
setOperationAction(ISD::BR_CC, MVT::i64, Expand);
91+
setOperationAction(ISD::BR_CC, MVT::f32, Expand);
8092

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

103+
bool XtensaTargetLowering::isOffsetFoldingLegal(
104+
const GlobalAddressSDNode *GA) const {
105+
// The Xtensa target isn't yet aware of offsets.
106+
return false;
107+
}
108+
91109
//===----------------------------------------------------------------------===//
92110
// Calling conventions
93111
//===----------------------------------------------------------------------===//
@@ -519,6 +537,72 @@ SDValue XtensaTargetLowering::LowerImmediate(SDValue Op,
519537
return Op;
520538
}
521539

540+
SDValue XtensaTargetLowering::LowerGlobalAddress(SDValue Op,
541+
SelectionDAG &DAG) const {
542+
const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Op);
543+
SDLoc DL(Op);
544+
auto PtrVT = Op.getValueType();
545+
const GlobalValue *GV = G->getGlobal();
546+
547+
SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, Align(4));
548+
SDValue CPWrap = getAddrPCRel(CPAddr, DAG);
549+
550+
return CPWrap;
551+
}
552+
553+
SDValue XtensaTargetLowering::LowerBlockAddress(SDValue Op,
554+
SelectionDAG &DAG) const {
555+
BlockAddressSDNode *Node = cast<BlockAddressSDNode>(Op);
556+
const BlockAddress *BA = Node->getBlockAddress();
557+
EVT PtrVT = Op.getValueType();
558+
559+
XtensaConstantPoolValue *CPV =
560+
XtensaConstantPoolConstant::Create(BA, 0, XtensaCP::CPBlockAddress);
561+
SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4));
562+
SDValue CPWrap = getAddrPCRel(CPAddr, DAG);
563+
564+
return CPWrap;
565+
}
566+
567+
SDValue XtensaTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) const {
568+
SDValue Chain = Op.getOperand(0);
569+
SDValue Table = Op.getOperand(1);
570+
SDValue Index = Op.getOperand(2);
571+
SDLoc DL(Op);
572+
JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
573+
MachineFunction &MF = DAG.getMachineFunction();
574+
const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
575+
SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
576+
const DataLayout &TD = DAG.getDataLayout();
577+
EVT PtrVT = Table.getValueType();
578+
unsigned EntrySize = MJTI->getEntrySize(TD);
579+
580+
Index = DAG.getNode(ISD::MUL, DL, Index.getValueType(), Index,
581+
DAG.getConstant(EntrySize, DL, Index.getValueType()));
582+
SDValue Addr = DAG.getNode(ISD::ADD, DL, Index.getValueType(), Index, Table);
583+
SDValue LD =
584+
DAG.getLoad(PtrVT, DL, Chain, Addr,
585+
MachinePointerInfo::getJumpTable(DAG.getMachineFunction()));
586+
587+
return DAG.getNode(XtensaISD::BR_JT, DL, MVT::Other, LD.getValue(1), LD,
588+
TargetJT);
589+
}
590+
591+
SDValue XtensaTargetLowering::LowerJumpTable(SDValue Op,
592+
SelectionDAG &DAG) const {
593+
JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
594+
EVT PtrVT = Op.getValueType();
595+
596+
// Create a constant pool entry for the callee address
597+
XtensaConstantPoolValue *CPV =
598+
XtensaConstantPoolJumpTable::Create(*DAG.getContext(), JT->getIndex());
599+
600+
// Get the address of the callee into a register
601+
SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4));
602+
603+
return getAddrPCRel(CPAddr, DAG);
604+
}
605+
522606
SDValue XtensaTargetLowering::getAddrPCRel(SDValue Op,
523607
SelectionDAG &DAG) const {
524608
SDLoc DL(Op);
@@ -580,8 +664,16 @@ SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
580664
SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
581665
SelectionDAG &DAG) const {
582666
switch (Op.getOpcode()) {
667+
case ISD::BR_JT:
668+
return LowerBR_JT(Op, DAG);
583669
case ISD::Constant:
584670
return LowerImmediate(Op, DAG);
671+
case ISD::GlobalAddress:
672+
return LowerGlobalAddress(Op, DAG);
673+
case ISD::BlockAddress:
674+
return LowerBlockAddress(Op, DAG);
675+
case ISD::JumpTable:
676+
return LowerJumpTable(Op, DAG);
585677
case ISD::ConstantPool:
586678
return LowerConstantPool(cast<ConstantPoolSDNode>(Op), DAG);
587679
case ISD::STACKSAVE:
@@ -597,6 +689,8 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
597689

598690
const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
599691
switch (Opcode) {
692+
case XtensaISD::BR_JT:
693+
return "XtensaISD::BR_JT";
600694
case XtensaISD::CALL:
601695
return "XtensaISD::CALL";
602696
case XtensaISD::PCREL_WRAPPER:

llvm/lib/Target/Xtensa/XtensaISelLowering.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace llvm {
2323
namespace XtensaISD {
2424
enum {
2525
FIRST_NUMBER = ISD::BUILTIN_OP_END,
26+
BR_JT,
2627

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

47+
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
48+
4649
const char *getTargetNodeName(unsigned Opcode) const override;
4750

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

77+
SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
78+
7479
SDValue LowerImmediate(SDValue Op, SelectionDAG &DAG) const;
7580

81+
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
82+
83+
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
84+
85+
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
86+
7687
SDValue LowerConstantPool(ConstantPoolSDNode *CP, SelectionDAG &DAG) const;
7788

7889
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;

llvm/lib/Target/Xtensa/XtensaInstrInfo.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,15 @@ def BBSI : RRI8_Inst<0x07, (outs),
416416
let imm8 = target;
417417
}
418418

419+
def : Pat<(brcc SETGT, AR:$s, AR:$t, bb:$target),
420+
(BLT AR:$t, AR:$s, bb:$target)>;
421+
def : Pat<(brcc SETUGT, AR:$s, AR:$t, bb:$target),
422+
(BLTU AR:$t, AR:$s, bb:$target)>;
423+
def : Pat<(brcc SETLE, AR:$s, AR:$t, bb:$target),
424+
(BGE AR:$t, AR:$s, bb:$target)>;
425+
def : Pat<(brcc SETULE, AR:$s, AR:$t, bb:$target),
426+
(BGEU AR:$t, AR:$s, bb:$target)>;
427+
419428
//===----------------------------------------------------------------------===//
420429
// Call and jump instructions
421430
//===----------------------------------------------------------------------===//
@@ -471,6 +480,12 @@ def : Pat<(Xtensa_call (i32 texternalsym:$dst)),
471480
def : Pat<(Xtensa_call AR:$dst),
472481
(CALLX0 AR:$dst)>;
473482

483+
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1, Size = 3 in {
484+
def BR_JT: Pseudo<(outs), (ins AR:$s, i32imm:$jt),
485+
"!br_jt_p, $s, $jt",
486+
[(Xtensa_brjt AR:$s, tjumptable:$jt)]>;
487+
}
488+
474489
//===----------------------------------------------------------------------===//
475490
// Mem barrier instructions
476491
//===----------------------------------------------------------------------===//

llvm/lib/Target/Xtensa/XtensaOperators.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ def SDT_XtensaWrapPtr : SDTypeProfile<1, 1,
1717
[SDTCisSameAs<0, 1>,
1818
SDTCisPtrTy<0>]>;
1919

20+
def SDT_XtensaBrJT : SDTypeProfile<0, 2,
21+
[SDTCisPtrTy<0>, SDTCisVT<1, i32>]>;
2022
//===----------------------------------------------------------------------===//
2123
// Node definitions
2224
//===----------------------------------------------------------------------===//
@@ -34,3 +36,5 @@ def Xtensa_callseq_start: SDNode<"ISD::CALLSEQ_START", SDT_XtensaCallSeqStart,
3436
def Xtensa_callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_XtensaCallSeqEnd,
3537
[SDNPHasChain, SDNPSideEffect, SDNPOptInGlue,
3638
SDNPOutGlue]>;
39+
40+
def Xtensa_brjt: SDNode<"XtensaISD::BR_JT", SDT_XtensaBrJT, [SDNPHasChain]>;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; RUN: llc --mtriple=xtensa < %s | FileCheck %s
2+
3+
@addr = global ptr null
4+
5+
define void @test_blockaddress() {
6+
7+
store volatile ptr blockaddress(@test_blockaddress, %block), ptr @addr
8+
; CHECK: .literal_position
9+
; CHECK-NEXT: .literal .LCPI0_0, addr
10+
; CHECK-NEXT: .literal .LCPI0_1, .Ltmp0
11+
; CHECK-LABEL: test_blockaddress:
12+
; CHECK: # %bb.0:
13+
; CHECK-NEXT: l32r a8, .LCPI0_0
14+
; CHECK-NEXT: l32r a9, .LCPI0_1
15+
; CHECK-NEXT: s32i a9, a8, 0
16+
; CHECK-NEXT: l32i a8, a8, 0
17+
; CHECK-NEXT: jx a8
18+
; CHECK-NEXT: .Ltmp0:
19+
; CHECK-NEXT: .LBB0_1:
20+
21+
%val = load volatile ptr, ptr @addr
22+
indirectbr ptr %val, [label %block]
23+
24+
block:
25+
ret void
26+
}

0 commit comments

Comments
 (0)