Skip to content

[Xtensa] Implement THREADPTR and DFPAccel Xtensa Options. #145543

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

andreisfr
Copy link
Contributor

Implment base support of the TLS functionality using Xtensa THREADPTR Option. Implement basic functionality of the DFPAccel Option(registers support).

Implment base support of the TLS functionality using Xtensa THREADPTR Option.
Implement basic functionality of the DFPAccel Option(registers support).
@llvmbot llvmbot added mc Machine (object) code backend:Xtensa labels Jun 24, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 24, 2025

@llvm/pr-subscribers-mc

@llvm/pr-subscribers-backend-xtensa

Author: Andrei Safronov (andreisfr)

Changes

Implment base support of the TLS functionality using Xtensa THREADPTR Option. Implement basic functionality of the DFPAccel Option(registers support).


Full diff: https://github.com/llvm/llvm-project/pull/145543.diff

15 Files Affected:

  • (modified) llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp (+6-1)
  • (modified) llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp (+14)
  • (modified) llvm/lib/Target/Xtensa/XtensaFeatures.td (+10)
  • (modified) llvm/lib/Target/Xtensa/XtensaISelLowering.cpp (+51)
  • (modified) llvm/lib/Target/Xtensa/XtensaISelLowering.h (+4)
  • (modified) llvm/lib/Target/Xtensa/XtensaInstrInfo.td (+1-1)
  • (modified) llvm/lib/Target/Xtensa/XtensaOperators.td (+5)
  • (modified) llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp (+4-1)
  • (modified) llvm/lib/Target/Xtensa/XtensaRegisterInfo.td (+10-1)
  • (modified) llvm/lib/Target/Xtensa/XtensaSubtarget.h (+1-1)
  • (added) llvm/test/CodeGen/Xtensa/threadptr.ll (+19)
  • (added) llvm/test/MC/Disassembler/Xtensa/dfpaccel.txt (+19)
  • (added) llvm/test/MC/Disassembler/Xtensa/threadptr.txt (+11)
  • (added) llvm/test/MC/Xtensa/dfpaccel.s (+53)
  • (added) llvm/test/MC/Xtensa/threadptr.s (+21)
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
+
+@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

Comment on lines +53 to +56
if (Specifier == Xtensa::S_TPOFF)
return ELF::R_XTENSA_TLS_TPOFF;
else
return ELF::R_XTENSA_32;
Copy link
Contributor

Choose a reason for hiding this comment

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

No else after return, use return of ternary operator?

return Xtensa::F64R_HI;
} else if (MRI.getEncodingValue(Xtensa::F64S) == Code) {
return Xtensa::F64S;
} else if (MRI.getEncodingValue(Xtensa::THREADPTR) == Code) {
Copy link
Contributor

Choose a reason for hiding this comment

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

no else after return

TLSModel::Model model = getTargetMachine().getTLSModel(GV);

if (!Subtarget.hasTHREADPTR()) {
report_fatal_error("only emulated TLS supported");
Copy link
Contributor

Choose a reason for hiding this comment

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

Avoid using report_fatal_error, in this case you can use DiagnosticInfoUnsupported and return poison

report_fatal_error("only emulated TLS supported");
}

if ((model == TLSModel::LocalExec) || (model == TLSModel::InitialExec)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if ((model == TLSModel::LocalExec) || (model == TLSModel::InitialExec)) {
if (model == TLSModel::LocalExec || model == TLSModel::InitialExec) {


return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer, Addr);
} else
report_fatal_error("only local-exec and initial-exec TLS mode supported");
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto. Also can change this to early exit in the failure case

Comment on lines +17 to +18
%tmp1 = load i32, ptr @i
ret i32 %tmp1
Copy link
Contributor

Choose a reason for hiding this comment

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

2 space indent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:Xtensa mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants