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 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/XtensaMCExpr.h"
#include "MCTargetDesc/XtensaMCTargetDesc.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/BinaryFormat/ELF.h"
Expand Down Expand Up @@ -45,10 +46,12 @@ 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;
return (Specifier == Xtensa::S_TPOFF ? ELF::R_XTENSA_TLS_TPOFF
: ELF::R_XTENSA_32);
default:
return ELF::R_XTENSA_SLOT0_OP;
}
Expand Down
23 changes: 20 additions & 3 deletions llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -203,12 +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) {
UserReg = Xtensa::F64R_LO;
} else if (MRI.getEncodingValue(Xtensa::F64R_HI) == Code) {
UserReg = Xtensa::F64R_HI;
} else if (MRI.getEncodingValue(Xtensa::F64S) == Code) {
UserReg = 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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I rewrote the function code.

UserReg = Xtensa::THREADPTR;
}
return Xtensa::NoRegister;

return UserReg;
}

static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI,
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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)>;
57 changes: 57 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -919,6 +920,58 @@ 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();
Copy link
Contributor

Choose a reason for hiding this comment

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

No auto

const GlobalValue *GV = G->getGlobal();

if (DAG.getTarget().useEmulatedTLS())
return LowerToTLSEmulatedModel(G, DAG);

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

if (!Subtarget.hasTHREADPTR()) {
DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
DAG.getMachineFunction().getFunction(), "only emulated TLS supported",
DL.getDebugLoc()));
}

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 {
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

DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
DAG.getMachineFunction().getFunction(),
"only local-exec and initial-exec TLS mode supported",
DL.getDebugLoc()));
Copy link
Contributor

Choose a reason for hiding this comment

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

In both of these error cases, you need to return a value

Copy link
Contributor

Choose a reason for hiding this comment

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

This also implies there is missing test coverage for the error cases

}

return SDValue();
}

SDValue XtensaTargetLowering::LowerBlockAddress(SDValue Op,
SelectionDAG &DAG) const {
BlockAddressSDNode *Node = cast<BlockAddressSDNode>(Op);
Expand Down Expand Up @@ -1353,6 +1406,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:
Expand Down Expand Up @@ -1406,6 +1461,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:
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/Xtensa/XtensaInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/Xtensa/XtensaOperators.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -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]>;
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 10 additions & 1 deletion llvm/lib/Target/Xtensa/XtensaRegisterInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/Xtensa/XtensaSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
19 changes: 19 additions & 0 deletions llvm/test/CodeGen/Xtensa/threadptr.ll
Original file line number Diff line number Diff line change
@@ -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
}
19 changes: 19 additions & 0 deletions llvm/test/MC/Disassembler/Xtensa/dfpaccel.txt
Original file line number Diff line number Diff line change
@@ -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
11 changes: 11 additions & 0 deletions llvm/test/MC/Disassembler/Xtensa/threadptr.txt
Original file line number Diff line number Diff line change
@@ -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
53 changes: 53 additions & 0 deletions llvm/test/MC/Xtensa/dfpaccel.s
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions llvm/test/MC/Xtensa/threadptr.s
Original file line number Diff line number Diff line change
@@ -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