[Hexagon] Add target feature to generate long calls
llvm-svn: 276638
diff --git a/llvm/lib/Target/Hexagon/Hexagon.td b/llvm/lib/Target/Hexagon/Hexagon.td
index aaa0f3e..f6a2e4f 100644
--- a/llvm/lib/Target/Hexagon/Hexagon.td
+++ b/llvm/lib/Target/Hexagon/Hexagon.td
@@ -27,11 +27,12 @@
def ArchV55: SubtargetFeature<"v55", "HexagonArchVersion", "V55", "Hexagon V55">;
def ArchV60: SubtargetFeature<"v60", "HexagonArchVersion", "V60", "Hexagon V60">;
-// Hexagon ISA Extensions
-def ExtensionHVX: SubtargetFeature<"hvx", "UseHVXOps",
- "true", "Hexagon HVX instructions">;
-def ExtensionHVXDbl: SubtargetFeature<"hvx-double", "UseHVXDblOps",
- "true", "Hexagon HVX Double instructions">;
+def FeatureHVX: SubtargetFeature<"hvx", "UseHVXOps", "true",
+ "Hexagon HVX instructions">;
+def FeatureHVXDbl: SubtargetFeature<"hvx-double", "UseHVXDblOps", "true",
+ "Hexagon HVX Double instructions">;
+def FeatureLongCalls: SubtargetFeature<"long-calls", "UseLongCalls", "true",
+ "Use constant-extended calls">;
//===----------------------------------------------------------------------===//
// Hexagon Instruction Predicate Definitions.
@@ -45,10 +46,10 @@
def UseMEMOP : Predicate<"HST->useMemOps()">;
def IEEERndNearV5T : Predicate<"HST->modeIEEERndNear()">;
def UseHVXDbl : Predicate<"HST->useHVXDblOps()">,
- AssemblerPredicate<"ExtensionHVXDbl">;
+ AssemblerPredicate<"FeatureHVXDbl">;
def UseHVXSgl : Predicate<"HST->useHVXSglOps()">;
def UseHVX : Predicate<"HST->useHVXSglOps() ||HST->useHVXDblOps()">,
- AssemblerPredicate<"ExtensionHVX">;
+ AssemblerPredicate<"FeatureHVX">;
//===----------------------------------------------------------------------===//
// Classes used for relation maps.
@@ -269,7 +270,7 @@
def : Proc<"hexagonv55", HexagonModelV55,
[ArchV4, ArchV5, ArchV55]>;
def : Proc<"hexagonv60", HexagonModelV60,
- [ArchV4, ArchV5, ArchV55, ArchV60, ExtensionHVX]>;
+ [ArchV4, ArchV5, ArchV55, ArchV60, FeatureHVX]>;
//===----------------------------------------------------------------------===//
// Declare the target which we are implementing
diff --git a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
index 2540214..43ff10b 100644
--- a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
@@ -149,6 +149,10 @@
cl::Hidden, cl::ZeroOrMore, cl::desc("Max count of stack frame "
"shrink-wraps"));
+static cl::opt<bool> EnableSaveRestoreLong("enable-save-restore-long",
+ cl::Hidden, cl::desc("Enable long calls for save-restore stubs."),
+ cl::init(false), cl::ZeroOrMore);
+
static cl::opt<bool> UseAllocframe("use-allocframe", cl::init(true),
cl::Hidden, cl::desc("Use allocframe more conservatively"));
@@ -342,7 +346,7 @@
ShrinkCounter++;
}
- auto &HST = static_cast<const HexagonSubtarget&>(MF.getSubtarget());
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
auto &HRI = *HST.getRegisterInfo();
MachineDominatorTree MDT;
@@ -440,7 +444,7 @@
/// in one place allows shrink-wrapping of the stack frame.
void HexagonFrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
- auto &HST = static_cast<const HexagonSubtarget&>(MF.getSubtarget());
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
auto &HRI = *HST.getRegisterInfo();
MachineFrameInfo *MFI = MF.getFrameInfo();
@@ -581,7 +585,7 @@
if (!hasFP(MF))
return;
- auto &HST = static_cast<const HexagonSubtarget&>(MF.getSubtarget());
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
auto &HII = *HST.getInstrInfo();
auto &HRI = *HST.getRegisterInfo();
unsigned SP = HRI.getStackRegister();
@@ -1049,7 +1053,8 @@
MachineBasicBlock::iterator MI = MBB.begin();
PrologueStubs = false;
MachineFunction &MF = *MBB.getParent();
- auto &HII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
+ auto &HII = *HST.getInstrInfo();
if (useSpillFunction(MF, CSI)) {
PrologueStubs = true;
@@ -1059,20 +1064,31 @@
StkOvrFlowEnabled);
auto &HTM = static_cast<const HexagonTargetMachine&>(MF.getTarget());
bool IsPIC = HTM.isPositionIndependent();
+ bool LongCalls = HST.useLongCalls() || EnableSaveRestoreLong;
// Call spill function.
DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc();
unsigned SpillOpc;
- if (StkOvrFlowEnabled)
- SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_PIC
- : Hexagon::SAVE_REGISTERS_CALL_V4STK;
- else
- SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_PIC
- : Hexagon::SAVE_REGISTERS_CALL_V4;
+ if (StkOvrFlowEnabled) {
+ if (LongCalls)
+ SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT_PIC
+ : Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT;
+ else
+ SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_PIC
+ : Hexagon::SAVE_REGISTERS_CALL_V4STK;
+ } else {
+ if (LongCalls)
+ SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_EXT_PIC
+ : Hexagon::SAVE_REGISTERS_CALL_V4_EXT;
+ else
+ SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_PIC
+ : Hexagon::SAVE_REGISTERS_CALL_V4;
+ }
MachineInstr *SaveRegsCall =
BuildMI(MBB, MI, DL, HII.get(SpillOpc))
.addExternalSymbol(SpillFun);
+
// Add callee-saved registers as use.
addCalleeSaveRegistersAsImpOperand(SaveRegsCall, CSI, false, true);
// Add live in registers.
@@ -1104,7 +1120,8 @@
MachineBasicBlock::iterator MI = MBB.getFirstTerminator();
MachineFunction &MF = *MBB.getParent();
- auto &HII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
+ auto &HST = MF.getSubtarget<HexagonSubtarget>();
+ auto &HII = *HST.getInstrInfo();
if (useRestoreFunction(MF, CSI)) {
bool HasTC = hasTailCall(MBB) || !hasReturn(MBB);
@@ -1113,6 +1130,7 @@
const char *RestoreFn = getSpillFunctionFor(MaxR, Kind);
auto &HTM = static_cast<const HexagonTargetMachine&>(MF.getTarget());
bool IsPIC = HTM.isPositionIndependent();
+ bool LongCalls = HST.useLongCalls() || EnableSaveRestoreLong;
// Call spill function.
DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc()
@@ -1120,17 +1138,27 @@
MachineInstr *DeallocCall = nullptr;
if (HasTC) {
- unsigned ROpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC
- : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4;
- DeallocCall = BuildMI(MBB, MI, DL, HII.get(ROpc))
+ unsigned RetOpc;
+ if (LongCalls)
+ RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC
+ : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT;
+ else
+ RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC
+ : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4;
+ DeallocCall = BuildMI(MBB, MI, DL, HII.get(RetOpc))
.addExternalSymbol(RestoreFn);
} else {
// The block has a return.
MachineBasicBlock::iterator It = MBB.getFirstTerminator();
assert(It->isReturn() && std::next(It) == MBB.end());
- unsigned ROpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC
- : Hexagon::RESTORE_DEALLOC_RET_JMP_V4;
- DeallocCall = BuildMI(MBB, It, DL, HII.get(ROpc))
+ unsigned RetOpc;
+ if (LongCalls)
+ RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC
+ : Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT;
+ else
+ RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC
+ : Hexagon::RESTORE_DEALLOC_RET_JMP_V4;
+ DeallocCall = BuildMI(MBB, It, DL, HII.get(RetOpc))
.addExternalSymbol(RestoreFn);
// Transfer the function live-out registers.
DeallocCall->copyImplicitOps(MF, *It);
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index cdd4c2f..2362ef8 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -842,14 +842,17 @@
InFlag = SDValue();
}
+ bool LongCalls = MF.getSubtarget<HexagonSubtarget>().useLongCalls();
+ unsigned Flags = LongCalls ? HexagonII::HMOTF_ConstExtended : 0;
+
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
// node so that legalize doesn't hack it.
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, PtrVT);
+ Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, PtrVT, 0, Flags);
} else if (ExternalSymbolSDNode *S =
dyn_cast<ExternalSymbolSDNode>(Callee)) {
- Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT);
+ Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, Flags);
}
// Returns a chain & a flag for retval copy to use.
diff --git a/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp b/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp
index 00dfed7..1073053 100644
--- a/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp
@@ -44,14 +44,17 @@
const char *SpecialMemcpyName =
"__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes";
+ const MachineFunction &MF = DAG.getMachineFunction();
+ bool LongCalls = MF.getSubtarget<HexagonSubtarget>().useLongCalls();
+ unsigned Flags = LongCalls ? HexagonII::HMOTF_ConstExtended : 0;
TargetLowering::CallLoweringInfo CLI(DAG);
CLI.setDebugLoc(dl)
.setChain(Chain)
.setCallee(TLI.getLibcallCallingConv(RTLIB::MEMCPY),
Type::getVoidTy(*DAG.getContext()),
- DAG.getTargetExternalSymbol(
- SpecialMemcpyName, TLI.getPointerTy(DAG.getDataLayout())),
+ DAG.getTargetExternalSymbol(SpecialMemcpyName,
+ TLI.getPointerTy(DAG.getDataLayout()), Flags),
std::move(Args))
.setDiscardResult();
diff --git a/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp b/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp
index 73d3bd1..2771142 100644
--- a/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonSubtarget.cpp
@@ -69,6 +69,10 @@
cl::Hidden, cl::ZeroOrMore, cl::init(false),
cl::desc("Enable subregister liveness tracking for Hexagon"));
+static cl::opt<bool> OverrideLongCalls("hexagon-long-calls",
+ cl::Hidden, cl::ZeroOrMore, cl::init(false),
+ cl::desc("If present, forces/disables the use of long calls"));
+
void HexagonSubtarget::initializeEnvironment() {
UseMemOps = false;
ModeIEEERndNear = false;
@@ -94,12 +98,15 @@
UseHVXOps = false;
UseHVXDblOps = false;
+ UseLongCalls = false;
ParseSubtargetFeatures(CPUString, FS);
if (EnableHexagonHVX.getPosition())
UseHVXOps = EnableHexagonHVX;
if (EnableHexagonHVXDouble.getPosition())
UseHVXDblOps = EnableHexagonHVXDouble;
+ if (OverrideLongCalls.getPosition())
+ UseLongCalls = OverrideLongCalls;
return *this;
}
diff --git a/llvm/lib/Target/Hexagon/HexagonSubtarget.h b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
index 77d0966..56939cf 100644
--- a/llvm/lib/Target/Hexagon/HexagonSubtarget.h
+++ b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
@@ -34,6 +34,7 @@
virtual void anchor();
bool UseMemOps, UseHVXOps, UseHVXDblOps;
+ bool UseLongCalls;
bool ModeIEEERndNear;
public:
@@ -101,6 +102,7 @@
bool useHVXOps() const { return UseHVXOps; }
bool useHVXDblOps() const { return UseHVXOps && UseHVXDblOps; }
bool useHVXSglOps() const { return UseHVXOps && !UseHVXDblOps; }
+ bool useLongCalls() const { return UseLongCalls; }
bool useBSBScheduling() const { return UseBSBScheduling; }
bool enableMachineScheduler() const override;