[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