aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorKazushi (Jam) Marukawa <marukawa@nec.com>2020-02-18 16:09:02 +0100
committerSimon Moll <simon.moll@emea.nec.com>2020-02-18 16:09:12 +0100
commit5526786a56bd5fb187a8c6f601268e58e351b3c8 (patch)
tree656eec0fafb8e3ec033874f69f7fbcdd81d60a15 /llvm/lib
parent0f04384daf78e26652bae3c5ea9cc201c9099b9d (diff)
downloadllvm-5526786a56bd5fb187a8c6f601268e58e351b3c8.zip
llvm-5526786a56bd5fb187a8c6f601268e58e351b3c8.tar.gz
llvm-5526786a56bd5fb187a8c6f601268e58e351b3c8.tar.bz2
[VE] TLS codegen
Summary: Codegen and tests for thread-local storage. This implements only the general dynamic model due to limitations in nld 2.26. Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D74718
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/VE/MCTargetDesc/VEFixupKinds.h6
-rw-r--r--llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp54
-rw-r--r--llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.h4
-rw-r--r--llvm/lib/Target/VE/VEAsmPrinter.cpp71
-rw-r--r--llvm/lib/Target/VE/VEISelLowering.cpp54
-rw-r--r--llvm/lib/Target/VE/VEISelLowering.h4
-rw-r--r--llvm/lib/Target/VE/VEInstrInfo.td26
7 files changed, 218 insertions, 1 deletions
diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEFixupKinds.h b/llvm/lib/Target/VE/MCTargetDesc/VEFixupKinds.h
index 2d79669..46a340f 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/VEFixupKinds.h
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEFixupKinds.h
@@ -42,6 +42,12 @@ enum Fixups {
fixup_ve_plt_hi32,
fixup_ve_plt_lo32,
+ /// fixups for Thread Local Storage
+ fixup_ve_tls_gd_hi32,
+ fixup_ve_tls_gd_lo32,
+ fixup_ve_tpoff_hi32,
+ fixup_ve_tpoff_lo32,
+
// Marker
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp
index abb490e..e601a60 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp
@@ -54,6 +54,10 @@ bool VEMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) {
case VK_VE_GOTOFF_LO32:
case VK_VE_PLT_HI32:
case VK_VE_PLT_LO32:
+ case VK_VE_TLS_GD_HI32:
+ case VK_VE_TLS_GD_LO32:
+ case VK_VE_TPOFF_HI32:
+ case VK_VE_TPOFF_LO32:
return false; // OS << "@<text>("; break;
}
return true;
@@ -90,9 +94,21 @@ void VEMCExpr::printVariantKindSuffix(raw_ostream &OS, VariantKind Kind) {
case VK_VE_PLT_HI32:
OS << "@plt_hi";
break;
+ case VK_VE_TLS_GD_HI32:
+ OS << "@tls_gd_hi";
+ break;
+ case VK_VE_TLS_GD_LO32:
+ OS << "@tls_gd_lo";
+ break;
case VK_VE_PLT_LO32:
OS << "@plt_lo";
break;
+ case VK_VE_TPOFF_HI32:
+ OS << "@tpoff_hi";
+ break;
+ case VK_VE_TPOFF_LO32:
+ OS << "@tpoff_lo";
+ break;
}
}
@@ -108,6 +124,10 @@ VEMCExpr::VariantKind VEMCExpr::parseVariantKind(StringRef name) {
.Case("gotoff_lo", VK_VE_GOTOFF_LO32)
.Case("plt_hi", VK_VE_PLT_HI32)
.Case("plt_lo", VK_VE_PLT_LO32)
+ .Case("tls_gd_hi", VK_VE_TLS_GD_HI32)
+ .Case("tls_gd_lo", VK_VE_TLS_GD_LO32)
+ .Case("tpoff_hi", VK_VE_TPOFF_HI32)
+ .Case("tpoff_lo", VK_VE_TPOFF_LO32)
.Default(VK_VE_None);
}
@@ -135,6 +155,10 @@ VE::Fixups VEMCExpr::getFixupKind(VEMCExpr::VariantKind Kind) {
return VE::fixup_ve_plt_hi32;
case VK_VE_PLT_LO32:
return VE::fixup_ve_plt_lo32;
+ case VK_VE_TLS_GD_HI32:
+ return VE::fixup_ve_tls_gd_hi32;
+ case VK_VE_TLS_GD_LO32:
+ return VE::fixup_ve_tls_gd_lo32;
}
}
@@ -144,10 +168,38 @@ bool VEMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup);
}
+static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
+ switch (Expr->getKind()) {
+ case MCExpr::Target:
+ llvm_unreachable("Can't handle nested target expr!");
+ break;
+
+ case MCExpr::Constant:
+ break;
+
+ case MCExpr::Binary: {
+ const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
+ fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
+ fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
+ break;
+ }
+
+ case MCExpr::SymbolRef: {
+ const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
+ cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
+ break;
+ }
+
+ case MCExpr::Unary:
+ fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
+ break;
+ }
+}
+
void VEMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
Streamer.visitUsedExpr(*getSubExpr());
}
void VEMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
- llvm_unreachable("TODO implement");
+ fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
}
diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.h b/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.h
index 8e88444..e2f6f2c 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.h
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.h
@@ -34,6 +34,10 @@ public:
VK_VE_GOTOFF_LO32,
VK_VE_PLT_HI32,
VK_VE_PLT_LO32,
+ VK_VE_TLS_GD_HI32,
+ VK_VE_TLS_GD_LO32,
+ VK_VE_TPOFF_HI32,
+ VK_VE_TPOFF_LO32,
};
private:
diff --git a/llvm/lib/Target/VE/VEAsmPrinter.cpp b/llvm/lib/Target/VE/VEAsmPrinter.cpp
index 6e6acff..99bbe44 100644
--- a/llvm/lib/Target/VE/VEAsmPrinter.cpp
+++ b/llvm/lib/Target/VE/VEAsmPrinter.cpp
@@ -51,6 +51,8 @@ public:
const MCSubtargetInfo &STI);
void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
const MCSubtargetInfo &STI);
+ void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
+ const MCSubtargetInfo &STI);
void emitInstruction(const MachineInstr *MI) override;
@@ -82,6 +84,15 @@ static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,
OutStreamer.emitInstruction(SICInst, STI);
}
+static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,
+ const MCSubtargetInfo &STI) {
+ MCInst BSICInst;
+ BSICInst.setOpcode(VE::BSIC);
+ BSICInst.addOperand(R1);
+ BSICInst.addOperand(R2);
+ OutStreamer.emitInstruction(BSICInst, STI);
+}
+
static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
const MCSubtargetInfo &STI) {
MCInst LEAInst;
@@ -241,6 +252,63 @@ void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);
}
+void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
+ const MCSubtargetInfo &STI) {
+ const MachineOperand &Addr = MI->getOperand(0);
+ MCSymbol *AddrSym = nullptr;
+
+ switch (Addr.getType()) {
+ default:
+ llvm_unreachable("<unknown operand type>");
+ return;
+ case MachineOperand::MO_MachineBasicBlock:
+ report_fatal_error("MBB is not supported yet");
+ return;
+ case MachineOperand::MO_ConstantPoolIndex:
+ report_fatal_error("ConstantPool is not supported yet");
+ return;
+ case MachineOperand::MO_ExternalSymbol:
+ AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
+ break;
+ case MachineOperand::MO_GlobalAddress:
+ AddrSym = getSymbol(Addr.getGlobal());
+ break;
+ }
+
+ MCOperand RegLR = MCOperand::createReg(VE::SX10); // LR
+ MCOperand RegS0 = MCOperand::createReg(VE::SX0); // S0
+ MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12
+ MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));
+
+ // lea %s0, sym@tls_gd_lo(-24)
+ // and %s0, %s0, (32)0
+ // sic %lr
+ // lea.sl %s0, sym@tls_gd_hi(%s0, %lr)
+ // lea %s12, __tls_get_addr@plt_lo(8)
+ // and %s12, %s12, (32)0
+ // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)
+ // bsic %lr, (, %s12)
+ MCOperand cim24 = MCOperand::createImm(-24);
+ MCOperand loImm =
+ createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext);
+ emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);
+ MCOperand ci32 = MCOperand::createImm(32);
+ emitANDrm0(*OutStreamer, RegS0, ci32, RegS0, STI);
+ emitSIC(*OutStreamer, RegLR, STI);
+ MCOperand hiImm =
+ createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext);
+ emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);
+ MCOperand ci8 = MCOperand::createImm(8);
+ MCOperand loImm2 =
+ createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext);
+ emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);
+ emitANDrm0(*OutStreamer, RegS12, ci32, RegS12, STI);
+ MCOperand hiImm2 =
+ createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext);
+ emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);
+ emitBSIC(*OutStreamer, RegLR, RegS12, STI);
+}
+
void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
switch (MI->getOpcode()) {
@@ -255,6 +323,9 @@ void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
case VE::GETFUNPLT:
lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());
return;
+ case VE::GETTLSADDR:
+ lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());
+ return;
}
MachineBasicBlock::const_instr_iterator I = MI->getIterator();
diff --git a/llvm/lib/Target/VE/VEISelLowering.cpp b/llvm/lib/Target/VE/VEISelLowering.cpp
index 70dc359..3646d5d 100644
--- a/llvm/lib/Target/VE/VEISelLowering.cpp
+++ b/llvm/lib/Target/VE/VEISelLowering.cpp
@@ -572,6 +572,7 @@ VETargetLowering::VETargetLowering(const TargetMachine &TM,
MVT PtrVT = MVT::getIntegerVT(TM.getPointerSizeInBits(0));
setOperationAction(ISD::BlockAddress, PtrVT, Custom);
setOperationAction(ISD::GlobalAddress, PtrVT, Custom);
+ setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom);
/// VAARG handling {
setOperationAction(ISD::VASTART, MVT::Other, Custom);
@@ -640,6 +641,7 @@ const char *VETargetLowering::getTargetNodeName(unsigned Opcode) const {
TARGET_NODE_CASE(Lo)
TARGET_NODE_CASE(Hi)
TARGET_NODE_CASE(GETFUNPLT)
+ TARGET_NODE_CASE(GETTLSADDR)
TARGET_NODE_CASE(CALL)
TARGET_NODE_CASE(RET_FLAG)
TARGET_NODE_CASE(GLOBAL_BASE_REG)
@@ -748,6 +750,56 @@ SDValue VETargetLowering::LowerBlockAddress(SDValue Op,
return makeAddress(Op, DAG);
}
+SDValue
+VETargetLowering::LowerToTLSGeneralDynamicModel(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc dl(Op);
+
+ // Generate the following code:
+ // t1: ch,glue = callseq_start t0, 0, 0
+ // t2: i64,ch,glue = VEISD::GETTLSADDR t1, label, t1:1
+ // t3: ch,glue = callseq_end t2, 0, 0, t2:2
+ // t4: i64,ch,glue = CopyFromReg t3, Register:i64 $sx0, t3:1
+ SDValue Label = withTargetFlags(Op, 0, DAG);
+ EVT PtrVT = Op.getValueType();
+
+ // Lowering the machine isd will make sure everything is in the right
+ // location.
+ SDValue Chain = DAG.getEntryNode();
+ SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
+ const uint32_t *Mask = Subtarget->getRegisterInfo()->getCallPreservedMask(
+ DAG.getMachineFunction(), CallingConv::C);
+ Chain = DAG.getCALLSEQ_START(Chain, 64, 0, dl);
+ SDValue Args[] = {Chain, Label, DAG.getRegisterMask(Mask), Chain.getValue(1)};
+ Chain = DAG.getNode(VEISD::GETTLSADDR, dl, NodeTys, Args);
+ Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(64, dl, true),
+ DAG.getIntPtrConstant(0, dl, true),
+ Chain.getValue(1), dl);
+ Chain = DAG.getCopyFromReg(Chain, dl, VE::SX0, PtrVT, Chain.getValue(1));
+
+ // GETTLSADDR will be codegen'ed as call. Inform MFI that function has calls.
+ MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
+ MFI.setHasCalls(true);
+
+ // Also generate code to prepare a GOT register if it is PIC.
+ if (isPositionIndependent()) {
+ MachineFunction &MF = DAG.getMachineFunction();
+ Subtarget->getInstrInfo()->getGlobalBaseReg(&MF);
+ }
+
+ return Chain;
+}
+
+SDValue VETargetLowering::LowerGlobalTLSAddress(SDValue Op,
+ SelectionDAG &DAG) const {
+ // The current implementation of nld (2.26) doesn't allow local exec model
+ // code described in VE-tls_v1.1.pdf (*1) as its input. Instead, we always
+ // generate the general dynamic model code sequence.
+ //
+ // *1: https://www.nec.com/en/global/prod/hpc/aurora/document/VE-tls_v1.1.pdf
+ return LowerToTLSGeneralDynamicModel(Op, DAG);
+}
+
SDValue VETargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>();
@@ -816,6 +868,8 @@ SDValue VETargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
return LowerBlockAddress(Op, DAG);
case ISD::GlobalAddress:
return LowerGlobalAddress(Op, DAG);
+ case ISD::GlobalTLSAddress:
+ return LowerGlobalTLSAddress(Op, DAG);
case ISD::VASTART:
return LowerVASTART(Op, DAG);
case ISD::VAARG:
diff --git a/llvm/lib/Target/VE/VEISelLowering.h b/llvm/lib/Target/VE/VEISelLowering.h
index 0d3796e..3d27a319b 100644
--- a/llvm/lib/Target/VE/VEISelLowering.h
+++ b/llvm/lib/Target/VE/VEISelLowering.h
@@ -28,6 +28,8 @@ enum NodeType : unsigned {
Lo, // Hi/Lo operations, typically on a global address.
GETFUNPLT, // load function address through %plt insturction
+ GETTLSADDR, // load address for TLS access
+
CALL, // A call instruction.
RET_FLAG, // Return with a flag operand.
GLOBAL_BASE_REG, // Global base reg for PIC.
@@ -77,6 +79,8 @@ public:
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerToTLSGeneralDynamicModel(SDValue Op, SelectionDAG &DAG) const;
/// } Custom Lower
SDValue withTargetFlags(SDValue Op, unsigned TF, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td
index 8fb89c8..4000bda 100644
--- a/llvm/lib/Target/VE/VEInstrInfo.td
+++ b/llvm/lib/Target/VE/VEInstrInfo.td
@@ -216,6 +216,12 @@ def getGOT : Operand<iPTR>;
// GETFUNPLT for PIC
def GetFunPLT : SDNode<"VEISD::GETFUNPLT", SDTIntUnaryOp>;
+// GETTLSADDR for TLS
+def GetTLSAddr : SDNode<"VEISD::GETTLSADDR", SDT_SPCall,
+ [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
+ SDNPVariadic]>;
+
+
//===----------------------------------------------------------------------===//
// VE Flag Conditions
@@ -1027,6 +1033,11 @@ def RET : CF<
"b.l (,%lr)",
[(retflag)]>;
+// Branch and Save IC
+
+let cx = 0, cy = 0, cy = 0, cz = 1, hasSideEffects = 0 /* , Uses = [IC] */ in
+def BSIC : RM<0x08, (outs), (ins I64:$sx, I64:$sz), "bsic $sx, (, ${sz})">;
+
// Branch instruction
let cx = 0, cx2 = 0, bpf = 0 /* NONE */ in
defm BCRL : BCRm<"br${cf}.l", "br.l", 0x18, I64, i64, simm7Op64, uimm6Op64>;
@@ -1197,6 +1208,13 @@ def : Pat<(add (VEhi tglobaladdr:$in1), (VElo tglobaladdr:$in2)),
(LEASLrzi (ANDrm0 (LEAzzi tglobaladdr:$in2), 32),
(tglobaladdr:$in1))>;
+// GlobalTLS address calculation and its optimization
+def : Pat<(VEhi tglobaltlsaddr:$in), (LEASLzzi tglobaltlsaddr:$in)>;
+def : Pat<(VElo tglobaltlsaddr:$in), (ANDrm0 (LEAzzi tglobaltlsaddr:$in), 32)>;
+def : Pat<(add (VEhi tglobaltlsaddr:$in1), (VElo tglobaltlsaddr:$in2)),
+ (LEASLrzi (ANDrm0 (LEAzzi tglobaltlsaddr:$in2), 32),
+ (tglobaltlsaddr:$in1))>;
+
// Address calculation and its optimization
def : Pat<(VEhi texternalsym:$in), (LEASLzzi texternalsym:$in)>;
def : Pat<(VElo texternalsym:$in), (ANDrm0 (LEAzzi texternalsym:$in), 32)>;
@@ -1247,6 +1265,14 @@ def : Pat<(GetFunPLT tglobaladdr:$dst),
def : Pat<(GetFunPLT texternalsym:$dst),
(GETFUNPLT texternalsym:$dst)>;
+// GETTLSADDR for TLS
+let Defs = [SX0, SX10, SX12], hasSideEffects = 0 in
+def GETTLSADDR : Pseudo<(outs), (ins i64imm:$addr),
+ "# GETTLSADDR $addr",
+ [(GetTLSAddr tglobaltlsaddr:$addr)] >;
+
+def : Pat<(GetTLSAddr tglobaltlsaddr:$dst),
+ (GETTLSADDR tglobaltlsaddr:$dst)>;
let Defs = [SX11], Uses = [SX11], hasSideEffects = 0 in {
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt, i64imm:$amt2),