[llvm] [Xtensa] Implement THREADPTR and DFPAccel Xtensa Options. (PR #145543)
Andrei Safronov via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 2 03:29:15 PDT 2025
https://github.com/andreisfr updated https://github.com/llvm/llvm-project/pull/145543
>From dcf0ea1dc2e45ffcdfcb5049aaec6199612637bf Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Tue, 24 Jun 2025 17:38:59 +0300
Subject: [PATCH 1/5] [Xtensa] Implement THREADPTR and DFPAccel Xtensa Options.
Implment base support of the TLS functionality using Xtensa THREADPTR Option.
Implement basic functionality of the DFPAccel Option(registers support).
---
.../MCTargetDesc/XtensaELFObjectWriter.cpp | 7 ++-
.../MCTargetDesc/XtensaMCTargetDesc.cpp | 14 +++++
llvm/lib/Target/Xtensa/XtensaFeatures.td | 10 ++++
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 51 ++++++++++++++++++
llvm/lib/Target/Xtensa/XtensaISelLowering.h | 4 ++
llvm/lib/Target/Xtensa/XtensaInstrInfo.td | 2 +-
llvm/lib/Target/Xtensa/XtensaOperators.td | 5 ++
llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp | 5 +-
llvm/lib/Target/Xtensa/XtensaRegisterInfo.td | 11 +++-
llvm/lib/Target/Xtensa/XtensaSubtarget.h | 2 +-
llvm/test/CodeGen/Xtensa/threadptr.ll | 19 +++++++
llvm/test/MC/Disassembler/Xtensa/dfpaccel.txt | 19 +++++++
.../test/MC/Disassembler/Xtensa/threadptr.txt | 11 ++++
llvm/test/MC/Xtensa/dfpaccel.s | 53 +++++++++++++++++++
llvm/test/MC/Xtensa/threadptr.s | 21 ++++++++
15 files changed, 229 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/CodeGen/Xtensa/threadptr.ll
create mode 100644 llvm/test/MC/Disassembler/Xtensa/dfpaccel.txt
create mode 100644 llvm/test/MC/Disassembler/Xtensa/threadptr.txt
create mode 100644 llvm/test/MC/Xtensa/dfpaccel.s
create mode 100644 llvm/test/MC/Xtensa/threadptr.s
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp
index f2c391b03bd4e..b8e8aee85cbb5 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp
@@ -8,6 +8,7 @@
//
//===----------------------------------------------------------------------===//
+#include "MCTargetDesc/XtensaMCExpr.h"
#include "MCTargetDesc/XtensaMCTargetDesc.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/BinaryFormat/ELF.h"
@@ -45,10 +46,14 @@ XtensaObjectWriter::~XtensaObjectWriter() {}
unsigned XtensaObjectWriter::getRelocType(const MCFixup &Fixup,
const MCValue &Target,
bool IsPCRel) const {
+ uint8_t Specifier = Target.getSpecifier();
switch ((unsigned)Fixup.getKind()) {
case FK_Data_4:
- return ELF::R_XTENSA_32;
+ if (Specifier == Xtensa::S_TPOFF)
+ return ELF::R_XTENSA_TLS_TPOFF;
+ else
+ return ELF::R_XTENSA_32;
default:
return ELF::R_XTENSA_SLOT0_OP;
}
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
index 9a55635674d72..b35debb81ae6d 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
@@ -186,11 +186,17 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
return FeatureBits[Xtensa::FeatureMiscSR];
case Xtensa::PRID:
return RAType == Xtensa::REGISTER_READ && FeatureBits[Xtensa::FeaturePRID];
+ case Xtensa::THREADPTR:
+ return FeatureBits[FeatureTHREADPTR];
case Xtensa::VECBASE:
return FeatureBits[Xtensa::FeatureRelocatableVector];
case Xtensa::FCR:
case Xtensa::FSR:
return FeatureBits[FeatureSingleFloat];
+ case Xtensa::F64R_LO:
+ case Xtensa::F64R_HI:
+ case Xtensa::F64S:
+ return FeatureBits[FeatureDFPAccel];
case Xtensa::WINDOWBASE:
case Xtensa::WINDOWSTART:
return FeatureBits[Xtensa::FeatureWindowed];
@@ -207,6 +213,14 @@ MCRegister Xtensa::getUserRegister(unsigned Code, const MCRegisterInfo &MRI) {
return Xtensa::FCR;
} else if (MRI.getEncodingValue(Xtensa::FSR) == Code) {
return Xtensa::FSR;
+ } else if (MRI.getEncodingValue(Xtensa::F64R_LO) == Code) {
+ return Xtensa::F64R_LO;
+ } else if (MRI.getEncodingValue(Xtensa::F64R_HI) == Code) {
+ return Xtensa::F64R_HI;
+ } else if (MRI.getEncodingValue(Xtensa::F64S) == Code) {
+ return Xtensa::F64S;
+ } else if (MRI.getEncodingValue(Xtensa::THREADPTR) == Code) {
+ return Xtensa::THREADPTR;
}
return Xtensa::NoRegister;
}
diff --git a/llvm/lib/Target/Xtensa/XtensaFeatures.td b/llvm/lib/Target/Xtensa/XtensaFeatures.td
index d48f494388a23..97d5472f3e96c 100644
--- a/llvm/lib/Target/Xtensa/XtensaFeatures.td
+++ b/llvm/lib/Target/Xtensa/XtensaFeatures.td
@@ -98,6 +98,11 @@ def FeatureDataCache : SubtargetFeature<"dcache", "HasDataCache", "true",
def HasDataCache : Predicate<"Subtarget->hasDataCache()">,
AssemblerPredicate<(all_of FeatureDataCache)>;
+def FeatureTHREADPTR : SubtargetFeature<"threadptr", "HasTHREADPTR", "true",
+ "Enable Xtensa THREADPTR option">;
+def HasTHREADPTR : Predicate<"Subtarget->hasTHREADPTR()">,
+ AssemblerPredicate<(all_of FeatureTHREADPTR)>;
+
// Xtensa Interrupts Options.
def FeatureHighPriInterrupts : SubtargetFeature<"highpriinterrupts",
"HasHighPriInterrupts", "true",
@@ -137,3 +142,8 @@ def FeatureCoprocessor : SubtargetFeature<"coprocessor", "HasCoprocessor", "true
"Enable Xtensa Coprocessor option">;
def HasCoprocessor : Predicate<"Subtarget->hasCoprocessor()">,
AssemblerPredicate<(all_of FeatureCoprocessor)>;
+
+def FeatureDFPAccel : SubtargetFeature<"dfpaccel", "HasDFPAccel", "true",
+ "Enable Xtensa Double Precision FP acceleration">;
+def HasDFPAccel : Predicate<"Subtarget->hasDFPAccel()">,
+ AssemblerPredicate<(all_of FeatureDFPAccel)>;
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index d51c573282da7..b52551de64086 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -101,6 +101,7 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::ConstantPool, PtrVT, Custom);
setOperationAction(ISD::GlobalAddress, PtrVT, Custom);
+ setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom);
setOperationAction(ISD::BlockAddress, PtrVT, Custom);
setOperationAction(ISD::JumpTable, PtrVT, Custom);
@@ -919,6 +920,52 @@ SDValue XtensaTargetLowering::LowerGlobalAddress(SDValue Op,
return Res;
}
+SDValue XtensaTargetLowering::LowerGlobalTLSAddress(SDValue Op,
+ SelectionDAG &DAG) const {
+ const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Op);
+ SDLoc DL(Op);
+ auto PtrVT = Op.getValueType();
+ const GlobalValue *GV = G->getGlobal();
+
+ if (DAG.getTarget().useEmulatedTLS())
+ return LowerToTLSEmulatedModel(G, DAG);
+
+ TLSModel::Model model = getTargetMachine().getTLSModel(GV);
+
+ if (!Subtarget.hasTHREADPTR()) {
+ report_fatal_error("only emulated TLS supported");
+ }
+
+ if ((model == TLSModel::LocalExec) || (model == TLSModel::InitialExec)) {
+ bool Priv = GV->isPrivateLinkage(GV->getLinkage());
+ MachineFunction &MF = DAG.getMachineFunction();
+ XtensaMachineFunctionInfo *XtensaFI =
+ MF.getInfo<XtensaMachineFunctionInfo>();
+ unsigned LabelId = XtensaFI->createCPLabelId();
+
+ // Create a constant pool entry for the callee address
+ XtensaConstantPoolValue *CPV = XtensaConstantPoolSymbol::Create(
+ *DAG.getContext(), GV->getName().str().c_str(), LabelId, Priv,
+ XtensaCP::TPOFF);
+
+ // Get the address of the callee into a register
+ SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4));
+ SDValue CPWrap = getAddrPCRel(CPAddr, DAG);
+ SDValue Addr = DAG.getLoad(
+ PtrVT, DL, DAG.getEntryNode(), CPWrap,
+ MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
+
+ SDValue TPRegister = DAG.getRegister(Xtensa::THREADPTR, MVT::i32);
+ SDValue ThreadPointer =
+ DAG.getNode(XtensaISD::RUR, DL, MVT::i32, TPRegister);
+
+ return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer, Addr);
+ } else
+ report_fatal_error("only local-exec and initial-exec TLS mode supported");
+
+ return SDValue();
+}
+
SDValue XtensaTargetLowering::LowerBlockAddress(SDValue Op,
SelectionDAG &DAG) const {
BlockAddressSDNode *Node = cast<BlockAddressSDNode>(Op);
@@ -1353,6 +1400,8 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
return LowerRETURNADDR(Op, DAG);
case ISD::GlobalAddress:
return LowerGlobalAddress(Op, DAG);
+ case ISD::GlobalTLSAddress:
+ return LowerGlobalTLSAddress(Op, DAG);
case ISD::BlockAddress:
return LowerBlockAddress(Op, DAG);
case ISD::JumpTable:
@@ -1406,6 +1455,8 @@ const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
return "XtensaISD::RET";
case XtensaISD::RETW:
return "XtensaISD::RETW";
+ case XtensaISD::RUR:
+ return "XtensaISD::RUR";
case XtensaISD::SELECT_CC:
return "XtensaISD::SELECT_CC";
case XtensaISD::SRCL:
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
index b6f2ebe21c940..91c79b1aa240e 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
@@ -45,6 +45,8 @@ enum {
RET,
RETW,
+ RUR,
+
// Select with condition operator - This selects between a true value and
// a false value (ops #2 and #3) based on the boolean result of comparing
// the lhs and rhs (ops #0 and #1) of a conditional expression with the
@@ -156,6 +158,8 @@ class XtensaTargetLowering : public TargetLowering {
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
+
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index 1335c6faff6b7..02156cefec142 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -576,7 +576,7 @@ def WUR : RRR_Inst<0x00, 0x03, 0x0F, (outs UR:$ur), (ins AR:$t),
}
def RUR : RRR_Inst<0x00, 0x03, 0x0E, (outs AR:$r), (ins UR:$ur),
- "rur\t$r, $ur", []> {
+ "rur\t$r, $ur", [(set AR:$r, (Xtensa_rur UR:$ur))]> {
bits<8> ur;
let s = ur{7-4};
diff --git a/llvm/lib/Target/Xtensa/XtensaOperators.td b/llvm/lib/Target/Xtensa/XtensaOperators.td
index fea13c2298d97..1d70e94d6d5eb 100644
--- a/llvm/lib/Target/Xtensa/XtensaOperators.td
+++ b/llvm/lib/Target/Xtensa/XtensaOperators.td
@@ -38,6 +38,8 @@ def SDT_XtensaEXTUI : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCi
def SDT_XtensaMOVSP : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
+def SDT_XtensaRUR : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+
//===----------------------------------------------------------------------===//
// Node definitions
//===----------------------------------------------------------------------===//
@@ -76,6 +78,9 @@ def Xtensa_extui: SDNode<"XtensaISD::EXTUI", SDT_XtensaEXTUI>;
def Xtensa_movsp: SDNode<"XtensaISD::MOVSP", SDT_XtensaMOVSP,
[SDNPHasChain, SDNPSideEffect, SDNPInGlue]>;
+def Xtensa_rur: SDNode<"XtensaISD::RUR", SDT_XtensaRUR,
+ [SDNPInGlue]>;
+
def Xtensa_cmpoeq : SDNode<"XtensaISD::CMPOEQ", SDT_XtensaCmp, [SDNPOutGlue]>;
def Xtensa_cmpolt : SDNode<"XtensaISD::CMPOLT", SDT_XtensaCmp, [SDNPOutGlue]>;
def Xtensa_cmpole : SDNode<"XtensaISD::CMPOLE", SDT_XtensaCmp, [SDNPOutGlue]>;
diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp
index 74633050861c2..ed76431bf5495 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp
@@ -53,7 +53,10 @@ BitVector XtensaRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
// Reserve frame pointer.
Reserved.set(getFrameRegister(MF));
}
-
+ if (Subtarget.hasTHREADPTR()) {
+ // Reserve frame pointer.
+ Reserved.set(Xtensa::THREADPTR);
+ }
// Reserve stack pointer.
Reserved.set(Xtensa::SP);
return Reserved;
diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
index 644faee51f513..596c4105c1118 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
@@ -234,10 +234,19 @@ class URReg<bits<8> num, string n, list<string> alt = []> : XtensaReg<n> {
let AltNames = alt;
}
+// Thread Pointer register
+def THREADPTR : URReg<231, "threadptr", ["THREADPTR"]>;
+
def FCR : URReg<232, "fcr", ["FCR"]>;
def FSR : URReg<233, "fsr", ["FSR"]>;
-def UR : RegisterClass<"Xtensa", [i32], 32, (add FCR, FSR)>;
+// DFPAccel registers
+def F64R_LO : URReg<234, "f64r_lo", ["F64R_LO"]>;
+def F64R_HI : URReg<235, "f64r_hi", ["F64R_HI"]>;
+def F64S : URReg<236, "f64s", ["F64S"]>;
+
+def UR : RegisterClass<"Xtensa", [i32], 32, (add
+ THREADPTR, FCR, FSR, F64R_LO, F64R_HI, F64S)>;
//===----------------------------------------------------------------------===//
// Floating-Point registers
diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.h b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
index bc32541750ece..fd677a451f3fd 100644
--- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h
+++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
@@ -91,7 +91,7 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo {
bool hasHighPriInterruptsLevel7() const { return HasHighPriInterruptsLevel7; }
bool hasInterrupt() const { return HasInterrupt; }
bool hasException() const { return HasException; }
-
+ bool hasTHREADPTR() const { return HasTHREADPTR; }
bool isWindowedABI() const { return hasWindowed(); }
// Automatically generated by tblgen.
diff --git a/llvm/test/CodeGen/Xtensa/threadptr.ll b/llvm/test/CodeGen/Xtensa/threadptr.ll
new file mode 100644
index 0000000000000..c32373f1aabb2
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/threadptr.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=xtensa -mattr=+threadptr -disable-block-placement -verify-machineinstrs < %s \
+; RUN: | FileCheck %s
+
+ at i = external thread_local global i32
+
+define i32 @f() {
+; CHECK-LABEL: f:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: # %bb.0: # %entry
+; CHECK-NEXT: l32r a8, .LCPI0_0
+; CHECK-NEXT: rur a9, threadptr
+; CHECK-NEXT: add a8, a9, a8
+; CHECK-NEXT: l32i a2, a8, 0
+; CHECK-NEXT: ret
+entry:
+ %tmp1 = load i32, ptr @i
+ ret i32 %tmp1
+}
diff --git a/llvm/test/MC/Disassembler/Xtensa/dfpaccel.txt b/llvm/test/MC/Disassembler/Xtensa/dfpaccel.txt
new file mode 100644
index 0000000000000..e2f06c601fd5f
--- /dev/null
+++ b/llvm/test/MC/Disassembler/Xtensa/dfpaccel.txt
@@ -0,0 +1,19 @@
+# NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5
+# RUN: llvm-mc -triple=xtensa -mattr=+dfpaccel -disassemble %s | FileCheck -check-prefixes=CHECK-DFPACCEL %s
+# RUN: not llvm-mc -triple=xtensa -disassemble %s 2>&1 | FileCheck --implicit-check-not=warning: -check-prefixes=CHECK-CORE %s
+
+## Verify that binary code is correctly disassembled with
+## DFPACCEL option enabled. Also verify that dissasembling without
+## DFPACCEL option generates warnings.
+
+[0xa0,0x3e,0xe3]
+# CHECK-DFPACCEL: rur a3, f64r_lo
+# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding
+
+[0xb0,0x3e,0xe3]
+# CHECK-DFPACCEL: rur a3, f64r_hi
+# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding
+
+[0xc0,0x3e,0xe3]
+# CHECK-DFPACCEL: rur a3, f64s
+# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding
diff --git a/llvm/test/MC/Disassembler/Xtensa/threadptr.txt b/llvm/test/MC/Disassembler/Xtensa/threadptr.txt
new file mode 100644
index 0000000000000..1e8d75fa4003b
--- /dev/null
+++ b/llvm/test/MC/Disassembler/Xtensa/threadptr.txt
@@ -0,0 +1,11 @@
+# NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5
+# RUN: llvm-mc -triple=xtensa -mattr=+threadptr -disassemble %s | FileCheck -check-prefixes=CHECK-THREADPTR %s
+# RUN: not llvm-mc -triple=xtensa -disassemble %s 2>&1 | FileCheck --implicit-check-not=warning: -check-prefixes=CHECK-CORE %s
+
+## Verify that binary code is correctly disassembled with
+## THREADPTR option enabled. Also verify that dissasembling without
+## THREADPTR option generates warnings.
+
+[0x70,0x3e,0xe3]
+# CHECK-THREADPTR: rur a3, threadptr
+# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding
diff --git a/llvm/test/MC/Xtensa/dfpaccel.s b/llvm/test/MC/Xtensa/dfpaccel.s
new file mode 100644
index 0000000000000..13e8c2865f403
--- /dev/null
+++ b/llvm/test/MC/Xtensa/dfpaccel.s
@@ -0,0 +1,53 @@
+# RUN: llvm-mc %s -triple=xtensa -show-encoding --mattr=+dfpaccel \
+# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s
+
+.align 4
+LBL0:
+
+# CHECK-INST: rur a3, f64r_lo
+# CHECK: encoding: [0xa0,0x3e,0xe3]
+rur a3, f64r_lo
+
+# CHECK-INST: rur a3, f64r_lo
+# CHECK: encoding: [0xa0,0x3e,0xe3]
+rur a3, 234
+
+# CHECK-INST: rur a3, f64r_lo
+# CHECK: encoding: [0xa0,0x3e,0xe3]
+rur.f64r_lo a3
+
+# CHECK-INST: wur a3, f64r_lo
+# CHECK: encoding: [0x30,0xea,0xf3]
+wur a3, f64r_lo
+
+# CHECK-INST: rur a3, f64r_hi
+# CHECK: encoding: [0xb0,0x3e,0xe3]
+rur a3, f64r_hi
+
+# CHECK-INST: rur a3, f64r_hi
+# CHECK: encoding: [0xb0,0x3e,0xe3]
+rur a3, 235
+
+# CHECK-INST: rur a3, f64r_hi
+# CHECK: encoding: [0xb0,0x3e,0xe3]
+rur.f64r_hi a3
+
+# CHECK-INST: wur a3, f64r_hi
+# CHECK: encoding: [0x30,0xeb,0xf3]
+wur a3, f64r_hi
+
+# CHECK-INST: rur a3, f64s
+# CHECK: encoding: [0xc0,0x3e,0xe3]
+rur a3, f64s
+
+# CHECK-INST: rur a3, f64s
+# CHECK: encoding: [0xc0,0x3e,0xe3]
+rur a3, 236
+
+# CHECK-INST: rur a3, f64s
+# CHECK: encoding: [0xc0,0x3e,0xe3]
+rur.f64s a3
+
+# CHECK-INST: wur a3, f64s
+# CHECK: encoding: [0x30,0xec,0xf3]
+wur a3, f64s
diff --git a/llvm/test/MC/Xtensa/threadptr.s b/llvm/test/MC/Xtensa/threadptr.s
new file mode 100644
index 0000000000000..c29d1ea91ed80
--- /dev/null
+++ b/llvm/test/MC/Xtensa/threadptr.s
@@ -0,0 +1,21 @@
+# RUN: llvm-mc %s -triple=xtensa -show-encoding --mattr=+threadptr \
+# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s
+
+.align 4
+LBL0:
+
+# CHECK-INST: rur a3, threadptr
+# CHECK: encoding: [0x70,0x3e,0xe3]
+rur a3, threadptr
+
+# CHECK-INST: rur a3, threadptr
+# CHECK: encoding: [0x70,0x3e,0xe3]
+rur a3, 231
+
+# CHECK-INST: rur a3, threadptr
+# CHECK: encoding: [0x70,0x3e,0xe3]
+rur.threadptr a3
+
+# CHECK-INST: wur a3, threadptr
+# CHECK: encoding: [0x30,0xe7,0xf3]
+wur a3, threadptr
>From 8ecbd8173ee6b30c91fdcba00483956ce46563e6 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Fri, 27 Jun 2025 14:38:47 +0300
Subject: [PATCH 2/5] [Xtensa] Minor fixes.
---
.../MCTargetDesc/XtensaELFObjectWriter.cpp | 6 ++----
.../Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp | 17 ++++++++++-------
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 14 ++++++++++----
llvm/test/CodeGen/Xtensa/threadptr.ll | 4 ++--
4 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp
index b8e8aee85cbb5..f756f06da8bcd 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp
@@ -50,10 +50,8 @@ unsigned XtensaObjectWriter::getRelocType(const MCFixup &Fixup,
switch ((unsigned)Fixup.getKind()) {
case FK_Data_4:
- if (Specifier == Xtensa::S_TPOFF)
- return ELF::R_XTENSA_TLS_TPOFF;
- else
- return ELF::R_XTENSA_32;
+ return (Specifier == Xtensa::S_TPOFF ? ELF::R_XTENSA_TLS_TPOFF
+ : ELF::R_XTENSA_32);
default:
return ELF::R_XTENSA_SLOT0_OP;
}
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
index b35debb81ae6d..821cba0fc25c2 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
@@ -209,20 +209,23 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
// Get Xtensa User Register by encoding value.
MCRegister Xtensa::getUserRegister(unsigned Code, const MCRegisterInfo &MRI) {
+ MCRegister UserReg = Xtensa::NoRegister;
+
if (MRI.getEncodingValue(Xtensa::FCR) == Code) {
- return Xtensa::FCR;
+ UserReg = Xtensa::FCR;
} else if (MRI.getEncodingValue(Xtensa::FSR) == Code) {
- return Xtensa::FSR;
+ UserReg = Xtensa::FSR;
} else if (MRI.getEncodingValue(Xtensa::F64R_LO) == Code) {
- return Xtensa::F64R_LO;
+ UserReg = Xtensa::F64R_LO;
} else if (MRI.getEncodingValue(Xtensa::F64R_HI) == Code) {
- return Xtensa::F64R_HI;
+ UserReg = Xtensa::F64R_HI;
} else if (MRI.getEncodingValue(Xtensa::F64S) == Code) {
- return Xtensa::F64S;
+ UserReg = Xtensa::F64S;
} else if (MRI.getEncodingValue(Xtensa::THREADPTR) == Code) {
- return Xtensa::THREADPTR;
+ UserReg = Xtensa::THREADPTR;
}
- return Xtensa::NoRegister;
+
+ return UserReg;
}
static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI,
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index b52551de64086..c0c8390ab2e4f 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -933,10 +933,12 @@ SDValue XtensaTargetLowering::LowerGlobalTLSAddress(SDValue Op,
TLSModel::Model model = getTargetMachine().getTLSModel(GV);
if (!Subtarget.hasTHREADPTR()) {
- report_fatal_error("only emulated TLS supported");
+ DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+ DAG.getMachineFunction().getFunction(), "only emulated TLS supported",
+ DL.getDebugLoc()));
}
- if ((model == TLSModel::LocalExec) || (model == TLSModel::InitialExec)) {
+ if (model == TLSModel::LocalExec || model == TLSModel::InitialExec) {
bool Priv = GV->isPrivateLinkage(GV->getLinkage());
MachineFunction &MF = DAG.getMachineFunction();
XtensaMachineFunctionInfo *XtensaFI =
@@ -960,8 +962,12 @@ SDValue XtensaTargetLowering::LowerGlobalTLSAddress(SDValue Op,
DAG.getNode(XtensaISD::RUR, DL, MVT::i32, TPRegister);
return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer, Addr);
- } else
- report_fatal_error("only local-exec and initial-exec TLS mode supported");
+ } else {
+ DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+ DAG.getMachineFunction().getFunction(),
+ "only local-exec and initial-exec TLS mode supported",
+ DL.getDebugLoc()));
+ }
return SDValue();
}
diff --git a/llvm/test/CodeGen/Xtensa/threadptr.ll b/llvm/test/CodeGen/Xtensa/threadptr.ll
index c32373f1aabb2..f294c8c5bd3ca 100644
--- a/llvm/test/CodeGen/Xtensa/threadptr.ll
+++ b/llvm/test/CodeGen/Xtensa/threadptr.ll
@@ -14,6 +14,6 @@ define i32 @f() {
; CHECK-NEXT: l32i a2, a8, 0
; CHECK-NEXT: ret
entry:
- %tmp1 = load i32, ptr @i
- ret i32 %tmp1
+ %tmp1 = load i32, ptr @i
+ ret i32 %tmp1
}
>From db4f2509556341ce29ee46179459c76a05e49bd1 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Tue, 1 Jul 2025 15:22:08 +0300
Subject: [PATCH 3/5] [Xtensa] Fix TLS Address lowering.
---
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 15 ++++++++-------
llvm/test/CodeGen/Xtensa/invalid-tls.ll | 17 +++++++++++++++++
llvm/test/CodeGen/Xtensa/threadptr.ll | 2 +-
3 files changed, 26 insertions(+), 8 deletions(-)
create mode 100644 llvm/test/CodeGen/Xtensa/invalid-tls.ll
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index c0c8390ab2e4f..665d72d279faf 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -924,7 +924,7 @@ SDValue XtensaTargetLowering::LowerGlobalTLSAddress(SDValue Op,
SelectionDAG &DAG) const {
const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Op);
SDLoc DL(Op);
- auto PtrVT = Op.getValueType();
+ EVT PtrVT = Op.getValueType();
const GlobalValue *GV = G->getGlobal();
if (DAG.getTarget().useEmulatedTLS())
@@ -936,6 +936,7 @@ SDValue XtensaTargetLowering::LowerGlobalTLSAddress(SDValue Op,
DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
DAG.getMachineFunction().getFunction(), "only emulated TLS supported",
DL.getDebugLoc()));
+ return DAG.getUNDEF(Op->getValueType(0));
}
if (model == TLSModel::LocalExec || model == TLSModel::InitialExec) {
@@ -962,14 +963,14 @@ SDValue XtensaTargetLowering::LowerGlobalTLSAddress(SDValue Op,
DAG.getNode(XtensaISD::RUR, DL, MVT::i32, TPRegister);
return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer, Addr);
- } else {
- DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
- DAG.getMachineFunction().getFunction(),
- "only local-exec and initial-exec TLS mode supported",
- DL.getDebugLoc()));
}
- return SDValue();
+ DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+ DAG.getMachineFunction().getFunction(),
+ "only local-exec and initial-exec TLS mode supported",
+ DL.getDebugLoc()));
+
+ return DAG.getUNDEF(Op->getValueType(0));
}
SDValue XtensaTargetLowering::LowerBlockAddress(SDValue Op,
diff --git a/llvm/test/CodeGen/Xtensa/invalid-tls.ll b/llvm/test/CodeGen/Xtensa/invalid-tls.ll
new file mode 100644
index 0000000000000..d948996e2c25e
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/invalid-tls.ll
@@ -0,0 +1,17 @@
+; RUN: not llc -mtriple=xtensa -mattr=+threadptr -relocation-model=pic -verify-machineinstrs < %s 2>&1 \
+; RUN: | FileCheck -check-prefix=XTENSA-PIC %s
+; RUN: not llc -mtriple=xtensa -verify-machineinstrs < %s 2>&1 \
+; RUN: | FileCheck -check-prefix=XTENSA-NO-THREADPTR %s
+
+; XTENSA-PIC: error: <unknown>:0:0: in function f i32 (): only local-exec and initial-exec TLS mode supported
+; XTENSA-PIC: error: <unknown>:0:0: in function f i32 (): PIC relocations are not supported
+
+; XTENSA-NO-THREADPTR: error: <unknown>:0:0: in function f i32 (): only emulated TLS supported
+
+ at i = external thread_local global i32
+
+define i32 @f() {
+entry:
+ %tmp1 = load i32, ptr @i
+ ret i32 %tmp1
+}
diff --git a/llvm/test/CodeGen/Xtensa/threadptr.ll b/llvm/test/CodeGen/Xtensa/threadptr.ll
index f294c8c5bd3ca..148ee7231db78 100644
--- a/llvm/test/CodeGen/Xtensa/threadptr.ll
+++ b/llvm/test/CodeGen/Xtensa/threadptr.ll
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc -mtriple=xtensa -mattr=+threadptr -disable-block-placement -verify-machineinstrs < %s \
+; RUN: llc -mtriple=xtensa -mattr=+threadptr -verify-machineinstrs < %s \
; RUN: | FileCheck %s
@i = external thread_local global i32
>From d601f2874938118e299b1f96914449b69a47a5b5 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Tue, 1 Jul 2025 16:50:02 +0300
Subject: [PATCH 4/5] [Xtensa] Minor fixes.
---
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 665d72d279faf..1ed962d1f59e3 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -967,8 +967,7 @@ SDValue XtensaTargetLowering::LowerGlobalTLSAddress(SDValue Op,
DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
DAG.getMachineFunction().getFunction(),
- "only local-exec and initial-exec TLS mode supported",
- DL.getDebugLoc()));
+ "only local-exec and initial-exec TLS mode supported", DL.getDebugLoc()));
return DAG.getUNDEF(Op->getValueType(0));
}
>From 280cdd51d2b6df399ced8a864e89ffceebd96541 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Wed, 2 Jul 2025 13:25:58 +0300
Subject: [PATCH 5/5] [Xtensa] Fix TLS Address lowering and tests.
---
llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp | 4 ++--
llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 4 ++--
llvm/test/CodeGen/Xtensa/invalid-tls.ll | 4 ++--
llvm/test/CodeGen/Xtensa/threadptr.ll | 3 +--
4 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp
index f756f06da8bcd..4a6e96ed7d191 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp
@@ -50,8 +50,8 @@ unsigned XtensaObjectWriter::getRelocType(const MCFixup &Fixup,
switch ((unsigned)Fixup.getKind()) {
case FK_Data_4:
- return (Specifier == Xtensa::S_TPOFF ? ELF::R_XTENSA_TLS_TPOFF
- : ELF::R_XTENSA_32);
+ return Specifier == Xtensa::S_TPOFF ? ELF::R_XTENSA_TLS_TPOFF
+ : ELF::R_XTENSA_32;
default:
return ELF::R_XTENSA_SLOT0_OP;
}
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 1ed962d1f59e3..c9097f9b9bc5f 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -936,7 +936,7 @@ SDValue XtensaTargetLowering::LowerGlobalTLSAddress(SDValue Op,
DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
DAG.getMachineFunction().getFunction(), "only emulated TLS supported",
DL.getDebugLoc()));
- return DAG.getUNDEF(Op->getValueType(0));
+ return DAG.getPOISON(Op->getValueType(0));
}
if (model == TLSModel::LocalExec || model == TLSModel::InitialExec) {
@@ -969,7 +969,7 @@ SDValue XtensaTargetLowering::LowerGlobalTLSAddress(SDValue Op,
DAG.getMachineFunction().getFunction(),
"only local-exec and initial-exec TLS mode supported", DL.getDebugLoc()));
- return DAG.getUNDEF(Op->getValueType(0));
+ return DAG.getPOISON(Op->getValueType(0));
}
SDValue XtensaTargetLowering::LowerBlockAddress(SDValue Op,
diff --git a/llvm/test/CodeGen/Xtensa/invalid-tls.ll b/llvm/test/CodeGen/Xtensa/invalid-tls.ll
index d948996e2c25e..6aebca30b83da 100644
--- a/llvm/test/CodeGen/Xtensa/invalid-tls.ll
+++ b/llvm/test/CodeGen/Xtensa/invalid-tls.ll
@@ -1,6 +1,6 @@
-; RUN: not llc -mtriple=xtensa -mattr=+threadptr -relocation-model=pic -verify-machineinstrs < %s 2>&1 \
+; RUN: not llc -mtriple=xtensa -mattr=+threadptr -relocation-model=pic -filetype=null < %s 2>&1 \
; RUN: | FileCheck -check-prefix=XTENSA-PIC %s
-; RUN: not llc -mtriple=xtensa -verify-machineinstrs < %s 2>&1 \
+; RUN: not llc -mtriple=xtensa -filetype=null < %s 2>&1 \
; RUN: | FileCheck -check-prefix=XTENSA-NO-THREADPTR %s
; XTENSA-PIC: error: <unknown>:0:0: in function f i32 (): only local-exec and initial-exec TLS mode supported
diff --git a/llvm/test/CodeGen/Xtensa/threadptr.ll b/llvm/test/CodeGen/Xtensa/threadptr.ll
index 148ee7231db78..5e08addd840d4 100644
--- a/llvm/test/CodeGen/Xtensa/threadptr.ll
+++ b/llvm/test/CodeGen/Xtensa/threadptr.ll
@@ -1,6 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc -mtriple=xtensa -mattr=+threadptr -verify-machineinstrs < %s \
-; RUN: | FileCheck %s
+; RUN: llc -mtriple=xtensa -mattr=+threadptr < %s | FileCheck %s
@i = external thread_local global i32
More information about the llvm-commits
mailing list