[llvm] [Xtensa] Lower GlobalAddress/BlockAddress/JumpTable (PR #95256)
Andrei Safronov via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 17 16:06:38 PDT 2024
https://github.com/andreisfr updated https://github.com/llvm/llvm-project/pull/95256
>From b62eea6970570338947eebc917b893e8437d7f9c Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Wed, 12 Jun 2024 17:05:08 +0300
Subject: [PATCH 1/2] [Xtensa] Lower GlobalAddress/BlockAddress/JumpTable
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.
---
llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp | 57 +++++++--
llvm/lib/Target/Xtensa/XtensaAsmPrinter.h | 2 +
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 109 ++++++++++++++++++
llvm/lib/Target/Xtensa/XtensaISelLowering.h | 11 ++
llvm/lib/Target/Xtensa/XtensaInstrInfo.td | 15 +++
llvm/lib/Target/Xtensa/XtensaOperators.td | 4 +
llvm/test/CodeGen/Xtensa/blockaddress.ll | 26 +++++
llvm/test/CodeGen/Xtensa/brcc.ll | 77 +++++++++++++
llvm/test/CodeGen/Xtensa/indirectbr.ll | 32 +++++
llvm/test/CodeGen/Xtensa/jumpt.ll | 40 +++++++
10 files changed, 366 insertions(+), 7 deletions(-)
create mode 100644 llvm/test/CodeGen/Xtensa/blockaddress.ll
create mode 100644 llvm/test/CodeGen/Xtensa/brcc.ll
create mode 100644 llvm/test/CodeGen/Xtensa/indirectbr.ll
create mode 100644 llvm/test/CodeGen/Xtensa/jumpt.ll
diff --git a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
index e222919b28dc9..fe23885549770 100644
--- a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
@@ -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"
@@ -42,6 +43,17 @@ getModifierVariantKind(XtensaCP::XtensaCPModifier Modifier) {
}
void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) {
+ unsigned Opc = MI->getOpcode();
+
+ switch (Opc) {
+ case Xtensa::BR_JT: {
+ EmitToStreamer(
+ *OutStreamer,
+ MCInstBuilder(Xtensa::JX).addReg(MI->getOperand(0).getReg()));
+ return;
+ }
+ }
+
MCInst LoweredMI;
lowerToMCInst(MI, LoweredMI);
EmitToStreamer(*OutStreamer, LoweredMI);
@@ -52,16 +64,25 @@ void XtensaAsmPrinter::emitMachineConstantPoolValue(
XtensaConstantPoolValue *ACPV = static_cast<XtensaConstantPoolValue *>(MCPV);
MCSymbol *MCSym;
- assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
+ 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 *Sym = XtensaSym->getSymbol();
+ std::string SymName(Sym);
- XtensaConstantPoolSymbol *XtensaSym = cast<XtensaConstantPoolSymbol>(ACPV);
- const char *Sym = XtensaSym->getSymbol();
- std::string SymName(Sym);
+ if (XtensaSym->isPrivateLinkage())
+ SymName = ".L" + SymName;
- if (XtensaSym->isPrivateLinkage())
- SymName = ".L" + SymName;
+ MCSym = GetExternalSymbolSymbol(StringRef(SymName));
+ }
- MCSym = GetExternalSymbolSymbol(StringRef(SymName));
MCSymbol *LblSym = GetCPISymbol(ACPV->getLabelId());
auto *TS =
static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer());
@@ -140,6 +161,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,
@@ -152,6 +177,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();
@@ -191,6 +230,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:
diff --git a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.h b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.h
index f3fec19724aab..f9cf5ae8c9f65 100644
--- a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.h
+++ b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.h
@@ -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;
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 6c3258b4bb46c..0f17db6031a8e 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -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);
@@ -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
//===----------------------------------------------------------------------===//
@@ -519,6 +537,87 @@ 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 = 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;
+}
+
+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);
+ 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 PTy = getPointerTy(TD);
+ 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(PTy, DL, Chain, Addr,
+ MachinePointerInfo::getJumpTable(DAG.getMachineFunction()));
+ return DAG.getNode(XtensaISD::BR_JT, DL, MVT::Other, LD.getValue(1), LD,
+ TargetJT);
+}
+
+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));
+
+ return getAddrPCRel(CPAddr, DAG);
+}
+
SDValue XtensaTargetLowering::getAddrPCRel(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
@@ -580,8 +679,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(cast<BlockAddressSDNode>(Op), DAG);
+ case ISD::JumpTable:
+ return LowerJumpTable(cast<JumpTableSDNode>(Op), DAG);
case ISD::ConstantPool:
return LowerConstantPool(cast<ConstantPoolSDNode>(Op), DAG);
case ISD::STACKSAVE:
@@ -597,6 +704,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:
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
index 6f6ec391430a9..67729e564485b 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
@@ -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.
@@ -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;
@@ -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(BlockAddressSDNode *Node, SelectionDAG &DAG) const;
+
+ SDValue LowerJumpTable(JumpTableSDNode *JT, SelectionDAG &DAG) const;
+
SDValue LowerConstantPool(ConstantPoolSDNode *CP, SelectionDAG &DAG) const;
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index 6e9e75257ccf4..f68d20dcdd54a 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -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
//===----------------------------------------------------------------------===//
@@ -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
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/Xtensa/XtensaOperators.td b/llvm/lib/Target/Xtensa/XtensaOperators.td
index cd4d831c85b58..88d3c9dfe7fd8 100644
--- a/llvm/lib/Target/Xtensa/XtensaOperators.td
+++ b/llvm/lib/Target/Xtensa/XtensaOperators.td
@@ -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
//===----------------------------------------------------------------------===//
@@ -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]>;
diff --git a/llvm/test/CodeGen/Xtensa/blockaddress.ll b/llvm/test/CodeGen/Xtensa/blockaddress.ll
new file mode 100644
index 0000000000000..bbeb1790a1b78
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/blockaddress.ll
@@ -0,0 +1,26 @@
+; RUN: llc --mtriple=xtensa < %s | FileCheck %s
+
+ at 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
+}
diff --git a/llvm/test/CodeGen/Xtensa/brcc.ll b/llvm/test/CodeGen/Xtensa/brcc.ll
new file mode 100644
index 0000000000000..83f6dfd1aebc3
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/brcc.ll
@@ -0,0 +1,77 @@
+; RUN: llc -march=xtensa < %s | FileCheck %s
+
+; CHECK-LABEL: brcc1:
+; CHECK: bge a3, a2, .LBB0_2
+; CHECK: addi a2, a2, 4
+; CHECK: .LBB0_2:
+define i32 @brcc1(i32 %a, i32 %b) nounwind {
+entry:
+ %wb = icmp sgt i32 %a, %b
+ br i1 %wb, label %t1, label %t2
+t1:
+ %t1v = add i32 %a, 4
+ br label %exit
+t2:
+ %t2v = add i32 %b, 8
+ br label %exit
+exit:
+ %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+ ret i32 %v
+}
+
+; CHECK-LABEL: brcc2
+; CHECK: bgeu a3, a2, .LBB1_2
+; CHECK: addi a2, a2, 4
+; CHECK: .LBB1_2:
+define i32 @brcc2(i32 %a, i32 %b) nounwind {
+entry:
+ %wb = icmp ugt i32 %a, %b
+ br i1 %wb, label %t1, label %t2
+t1:
+ %t1v = add i32 %a, 4
+ br label %exit
+t2:
+ %t2v = add i32 %b, 8
+ br label %exit
+exit:
+ %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+ ret i32 %v
+}
+
+; CHECK-LABEL: brcc3:
+; CHECK: blt a3, a2, .LBB2_2
+; CHECK: addi a2, a2, 4
+; CHECK: .LBB2_2:
+define i32 @brcc3(i32 %a, i32 %b) nounwind {
+entry:
+ %wb = icmp sle i32 %a, %b
+ br i1 %wb, label %t1, label %t2
+t1:
+ %t1v = add i32 %a, 4
+ br label %exit
+t2:
+ %t2v = add i32 %b, 8
+ br label %exit
+exit:
+ %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+ ret i32 %v
+}
+
+; CHECK-LABEL: brcc4
+; CHECK: bltu a3, a2, .LBB3_2
+; CHECK: addi a2, a2, 4
+; CHECK: .LBB3_2:
+define i32 @brcc4(i32 %a, i32 %b) nounwind {
+entry:
+ %wb = icmp ule i32 %a, %b
+ br i1 %wb, label %t1, label %t2
+t1:
+ %t1v = add i32 %a, 4
+ br label %exit
+t2:
+ %t2v = add i32 %b, 8
+ br label %exit
+exit:
+ %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+ ret i32 %v
+}
diff --git a/llvm/test/CodeGen/Xtensa/indirectbr.ll b/llvm/test/CodeGen/Xtensa/indirectbr.ll
new file mode 100644
index 0000000000000..c4181c28826f4
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/indirectbr.ll
@@ -0,0 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc -mtriple=xtensa -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=XTENSA %s
+
+define i32 @indirectbr(i8* %target) nounwind {
+; XTENSA-LABEL: indirectbr:
+; XTENSA: jx a2
+; XTENSA-NEXT: .LBB0_1: # %test_label
+; XTENSA-NEXT: movi a2, 0
+; XTENSA-NEXT: ret
+ indirectbr i8* %target, [label %test_label]
+test_label:
+ br label %ret
+ret:
+ ret i32 0
+}
+
+define i32 @indirectbr_with_offset(i8* %a) nounwind {
+; XTENSA-LABEL: indirectbr_with_offset:
+; XTENSA: movi a8, 1380
+; XTENSA-NEXT: add a8, a2, a8
+; XTENSA-NEXT: jx a8
+; XTENSA-NEXT: .LBB1_1: # %test_label
+; XTENSA-NEXT: movi a2, 0
+; XTENSA-NEXT: ret
+ %target = getelementptr inbounds i8, i8* %a, i32 1380
+ indirectbr i8* %target, [label %test_label]
+test_label:
+ br label %ret
+ret:
+ ret i32 0
+}
diff --git a/llvm/test/CodeGen/Xtensa/jumpt.ll b/llvm/test/CodeGen/Xtensa/jumpt.ll
new file mode 100644
index 0000000000000..66c2fc39e3952
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/jumpt.ll
@@ -0,0 +1,40 @@
+; RUN: llc -mtriple=xtensa -verify-machineinstrs < %s \
+; RUN: | FileCheck %s
+
+define void @switch_4_xtensa(i32 %in, ptr %out) nounwind {
+; CHECK: .literal_position
+; CHECK-NEXT: .LCPI0_0, .LJTI0_0
+; CHECK-LABEL: switch_4_xtensa:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi a9, a2, -1
+; CHECK-NEXT: movi a8, 3
+; CHECK-NEXT: bltu a8, a9, .LBB0_6
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: l32r a10, .LCPI0_0
+; CHECK-NEXT: addx4 a9, a9, a10
+; CHECK-NEXT: l32i a9, a9, 0
+; CHECK-NEXT: jx a9
+; CHECK: ret
+
+entry:
+ switch i32 %in, label %exit [
+ i32 1, label %bb1
+ i32 2, label %bb2
+ i32 3, label %bb3
+ i32 4, label %bb4
+ ]
+bb1:
+ store i32 4, ptr %out
+ br label %exit
+bb2:
+ store i32 3, ptr %out
+ br label %exit
+bb3:
+ store i32 2, ptr %out
+ br label %exit
+bb4:
+ store i32 1, ptr %out
+ br label %exit
+exit:
+ ret void
+}
>From 8d7a687f7c74e2fd882f597eec40a8a574a44273 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Tue, 18 Jun 2024 01:58:44 +0300
Subject: [PATCH 2/2] [Xtensa] Minor fixes in lowering
GlobalAddress/BlockAddress/JumptTable.
Remove redundant code and correct pointer type variable initialization.
Also improve asm printing.
---
llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp | 28 ++++++-----
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 47 +++++++------------
llvm/lib/Target/Xtensa/XtensaISelLowering.h | 4 +-
3 files changed, 33 insertions(+), 46 deletions(-)
diff --git a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
index fe23885549770..3f99387f759d9 100644
--- a/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaAsmPrinter.cpp
@@ -46,17 +46,17 @@ void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) {
unsigned Opc = MI->getOpcode();
switch (Opc) {
- case Xtensa::BR_JT: {
+ 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;
}
- }
-
- MCInst LoweredMI;
- lowerToMCInst(MI, LoweredMI);
- EmitToStreamer(*OutStreamer, LoweredMI);
}
void XtensaAsmPrinter::emitMachineConstantPoolValue(
@@ -74,13 +74,15 @@ void XtensaAsmPrinter::emitMachineConstantPoolValue(
} else {
assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
XtensaConstantPoolSymbol *XtensaSym = cast<XtensaConstantPoolSymbol>(ACPV);
- const char *Sym = XtensaSym->getSymbol();
- std::string SymName(Sym);
+ const char *SymName = XtensaSym->getSymbol();
- if (XtensaSym->isPrivateLinkage())
- SymName = ".L" + SymName;
-
- MCSym = GetExternalSymbolSymbol(StringRef(SymName));
+ if (XtensaSym->isPrivateLinkage()) {
+ const DataLayout &DL = getDataLayout();
+ MCSym = OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +
+ SymName);
+ } else {
+ MCSym = OutContext.getOrCreateSymbol(SymName);
+ }
}
MCSymbol *LblSym = GetCPISymbol(ACPV->getLabelId());
@@ -92,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);
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 0f17db6031a8e..6509793012504 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -541,42 +541,26 @@ SDValue XtensaTargetLowering::LowerGlobalAddress(SDValue Op,
SelectionDAG &DAG) const {
const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Op);
SDLoc DL(Op);
- auto PtrVt = getPointerTy(DAG.getDataLayout());
+ auto PtrVT = Op.getValueType();
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 CPAddr = DAG.getTargetConstantPool(GV, PtrVT, Align(4));
SDValue CPWrap = getAddrPCRel(CPAddr, DAG);
return CPWrap;
}
-SDValue XtensaTargetLowering::LowerBlockAddress(BlockAddressSDNode *Node,
+SDValue XtensaTargetLowering::LowerBlockAddress(SDValue Op,
SelectionDAG &DAG) const {
+ BlockAddressSDNode *Node = cast<BlockAddressSDNode>(Op);
const BlockAddress *BA = Node->getBlockAddress();
- EVT PtrVT = getPointerTy(DAG.getDataLayout());
+ 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;
}
@@ -590,30 +574,31 @@ SDValue XtensaTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) const {
const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
const DataLayout &TD = DAG.getDataLayout();
- EVT PTy = getPointerTy(TD);
+ 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(PTy, DL, Chain, Addr,
+ 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(JumpTableSDNode *JT,
+SDValue XtensaTargetLowering::LowerJumpTable(SDValue Op,
SelectionDAG &DAG) const {
- SDLoc DL(JT);
- EVT PtrVt = getPointerTy(DAG.getDataLayout());
+ 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));
+ SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4));
return getAddrPCRel(CPAddr, DAG);
}
@@ -686,9 +671,9 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
case ISD::GlobalAddress:
return LowerGlobalAddress(Op, DAG);
case ISD::BlockAddress:
- return LowerBlockAddress(cast<BlockAddressSDNode>(Op), DAG);
+ return LowerBlockAddress(Op, DAG);
case ISD::JumpTable:
- return LowerJumpTable(cast<JumpTableSDNode>(Op), DAG);
+ return LowerJumpTable(Op, DAG);
case ISD::ConstantPool:
return LowerConstantPool(cast<ConstantPoolSDNode>(Op), DAG);
case ISD::STACKSAVE:
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
index 67729e564485b..23a0217daaa96 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
@@ -80,9 +80,9 @@ class XtensaTargetLowering : public TargetLowering {
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
- SDValue LowerBlockAddress(BlockAddressSDNode *Node, SelectionDAG &DAG) const;
+ SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
- SDValue LowerJumpTable(JumpTableSDNode *JT, SelectionDAG &DAG) const;
+ SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerConstantPool(ConstantPoolSDNode *CP, SelectionDAG &DAG) const;
More information about the llvm-commits
mailing list