[X86] support reserve r8~r15 on X86_64 (#180242)
Which is under discussion in https://github.com/llvm/llvm-project/issues/179036 Add new options -ffixed_r{8-15} for clang X86 target, like option "-ffixed_x" for RISCV/AArch64 target. Also, add target-feature +reserve-r{8-15} for the X86 backend. The registers which are specified reserved will not be used in RegAlloc/CalleeSave. Then the reserved registers can be maintained by user. It will be useful for the runtime/interpreter implementation. Other registers are used in specific instructions or mechanism, so they can't be reserved.
This commit is contained in:
parent
1b633d6d6d
commit
e71f327b46
@ -5526,8 +5526,8 @@ def mrestrict_it: Flag<["-"], "mrestrict-it">, Group<m_arm_Features_Group>,
|
||||
def mno_restrict_it: Flag<["-"], "mno-restrict-it">, Group<m_arm_Features_Group>,
|
||||
HelpText<"Allow generation of complex IT blocks.">;
|
||||
def marm : Flag<["-"], "marm">, Alias<mno_thumb>;
|
||||
def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_arm_Features_Group>,
|
||||
HelpText<"Reserve the r9 register (ARM only)">;
|
||||
def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_Group>,
|
||||
HelpText<"Reserve the r9 register (ARM/x86_64 only)">;
|
||||
def mno_movt : Flag<["-"], "mno-movt">, Group<m_arm_Features_Group>,
|
||||
HelpText<"Disallow use of movt/movw pairs (ARM only)">;
|
||||
def mcrc : Flag<["-"], "mcrc">, Group<m_Group>,
|
||||
@ -6844,7 +6844,7 @@ def mno_hexagon_hvx_ieee_fp : Flag<["-"], "mno-hvx-ieee-fp">,
|
||||
Group<m_hexagon_Features_Group>,
|
||||
HelpText<"Disable Hexagon HVX IEEE floating-point">;
|
||||
def ffixed_r19: Flag<["-"], "ffixed-r19">, Group<f_Group>,
|
||||
HelpText<"Reserve register r19 (Hexagon only)">;
|
||||
HelpText<"Reserve register r19 (Hexagon/x86_64 only; x86_64 requires APX EGPR)">;
|
||||
} // let Flags = [TargetSpecific]
|
||||
def mmemops : Flag<["-"], "mmemops">, Group<m_hexagon_Features_Group>,
|
||||
Visibility<[ClangOption, CC1Option]>,
|
||||
@ -7168,6 +7168,13 @@ def mapxf : Flag<["-"], "mapxf">, Group<m_x86_Features_Group>;
|
||||
def mno_apxf : Flag<["-"], "mno-apxf">, Group<m_x86_Features_Group>;
|
||||
def mapx_inline_asm_use_gpr32 : Flag<["-"], "mapx-inline-asm-use-gpr32">, Group<m_Group>,
|
||||
HelpText<"Enable use of GPR32 in inline assembly for APX">;
|
||||
foreach i = {8, 10-15} in
|
||||
def ffixed_r#i : Flag<["-"], "ffixed-r"#i>, Group<m_Group>,
|
||||
HelpText<"Reserve the r"#i#" register (x86_64 only)">;
|
||||
foreach i = {16-18,20-31} in
|
||||
def ffixed_r#i : Flag<["-"], "ffixed-r"#i>, Group<m_Group>,
|
||||
HelpText<"Reserve the r"#i#" register (x86_64 with APX EGPR only)">;
|
||||
|
||||
} // let Flags = [TargetSpecific]
|
||||
|
||||
// VE feature flags
|
||||
|
||||
@ -807,6 +807,16 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
// -ffixed-r8 through -ffixed-r31 are lowered to reserve-r8 through
|
||||
// reserve-r31 target features, so canonicalize subregister spellings
|
||||
// like r15d/r15w/r15b back to the corresponding 64-bit register first.
|
||||
StringRef Reg64 = RegName;
|
||||
if (Reg64.back() == 'd' || Reg64.back() == 'w' || Reg64.back() == 'b') {
|
||||
Reg64 = Reg64.substr(0, Reg64.size() - 1);
|
||||
}
|
||||
if (getTargetOpts().FeatureMap.lookup(("reserve-" + Reg64).str()))
|
||||
return true;
|
||||
|
||||
// Check if the register is a 32-bit register the backend can handle.
|
||||
return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
|
||||
HasSizeMismatch);
|
||||
|
||||
@ -9,10 +9,12 @@
|
||||
#include "X86.h"
|
||||
#include "clang/Driver/Driver.h"
|
||||
#include "clang/Options/Options.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
#include "llvm/TargetParser/Host.h"
|
||||
#include "llvm/TargetParser/X86TargetParser.h"
|
||||
|
||||
using namespace clang::driver;
|
||||
using namespace clang::driver::tools;
|
||||
@ -149,6 +151,17 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
||||
}
|
||||
|
||||
const llvm::Triple::ArchType ArchType = Triple.getArch();
|
||||
bool HasEGPR = false;
|
||||
|
||||
// -ffixed-r16 through -ffixed-r31 are only valid when the selected x86_64
|
||||
// CPU enables APX EGPR by default; later -target-feature arguments still get
|
||||
// their own validation when translated to backend features.
|
||||
if (ArchType == llvm::Triple::x86_64) {
|
||||
SmallVector<StringRef, 16> CPUFeatures;
|
||||
llvm::X86::getFeaturesForCPU(getX86TargetCPU(D, Args, Triple), CPUFeatures);
|
||||
HasEGPR = llvm::is_contained(CPUFeatures, "+egpr");
|
||||
}
|
||||
|
||||
// Add features to be compatible with gcc for Android.
|
||||
if (Triple.isAndroid()) {
|
||||
if (ArchType == llvm::Triple::x86_64) {
|
||||
@ -258,11 +271,13 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
||||
if (A->getOption().matches(options::OPT_mapxf) ||
|
||||
A->getOption().matches(options::OPT_mno_apxf)) {
|
||||
if (IsNegative) {
|
||||
HasEGPR = false;
|
||||
Features.insert(Features.end(),
|
||||
{"-egpr", "-ndd", "-ccmp", "-nf", "-zu"});
|
||||
if (!Triple.isOSWindows())
|
||||
Features.insert(Features.end(), {"-push2pop2", "-ppx"});
|
||||
} else {
|
||||
HasEGPR = true;
|
||||
Features.insert(Features.end(),
|
||||
{"+egpr", "+ndd", "+ccmp", "+nf", "+zu"});
|
||||
if (!Triple.isOSWindows())
|
||||
@ -288,11 +303,17 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
||||
D.Diag(clang::diag::err_drv_unsupported_option_argument)
|
||||
<< A->getSpelling() << Value;
|
||||
|
||||
if (Value == "egpr")
|
||||
HasEGPR = !IsNegative;
|
||||
|
||||
Features.push_back(
|
||||
Args.MakeArgString((IsNegative ? "-" : "+") + Value));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Name == "egpr")
|
||||
HasEGPR = !IsNegative;
|
||||
Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
|
||||
}
|
||||
|
||||
@ -332,4 +353,43 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
||||
if (A->getOption().matches(options::OPT_m3dnow))
|
||||
D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args);
|
||||
}
|
||||
|
||||
// Handle features corresponding to "-ffixed-X" options
|
||||
#define RESERVE_REG(REG) \
|
||||
if (Args.hasArg(options::OPT_ffixed_##REG)) \
|
||||
Features.push_back("+reserve-" #REG);
|
||||
RESERVE_REG(r8)
|
||||
RESERVE_REG(r9)
|
||||
RESERVE_REG(r10)
|
||||
RESERVE_REG(r11)
|
||||
RESERVE_REG(r12)
|
||||
RESERVE_REG(r13)
|
||||
RESERVE_REG(r14)
|
||||
RESERVE_REG(r15)
|
||||
#define RESERVE_EGPR(REG) \
|
||||
if (Args.hasArg(options::OPT_ffixed_##REG)) { \
|
||||
if (!HasEGPR) \
|
||||
D.Diag(diag::err_drv_unsupported_opt_for_target) \
|
||||
<< "-ffixed-" #REG << Triple.getTriple(); \
|
||||
else \
|
||||
Features.push_back("+reserve-" #REG); \
|
||||
}
|
||||
RESERVE_EGPR(r16)
|
||||
RESERVE_EGPR(r17)
|
||||
RESERVE_EGPR(r18)
|
||||
RESERVE_EGPR(r19)
|
||||
RESERVE_EGPR(r20)
|
||||
RESERVE_EGPR(r21)
|
||||
RESERVE_EGPR(r22)
|
||||
RESERVE_EGPR(r23)
|
||||
RESERVE_EGPR(r24)
|
||||
RESERVE_EGPR(r25)
|
||||
RESERVE_EGPR(r26)
|
||||
RESERVE_EGPR(r27)
|
||||
RESERVE_EGPR(r28)
|
||||
RESERVE_EGPR(r29)
|
||||
RESERVE_EGPR(r30)
|
||||
RESERVE_EGPR(r31)
|
||||
#undef RESERVE_EGPR
|
||||
#undef RESERVE_REG
|
||||
}
|
||||
|
||||
114
clang/test/Driver/x86_64-fixed-r-register.c
Normal file
114
clang/test/Driver/x86_64-fixed-r-register.c
Normal file
@ -0,0 +1,114 @@
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r8 -### %s 2> %t
|
||||
// RUN: FileCheck --check-prefix=CHECK-FIXED-R8 < %t %s
|
||||
// CHECK-FIXED-R8: "-target-feature" "+reserve-r8"
|
||||
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r9 -### %s 2> %t
|
||||
// RUN: FileCheck --check-prefix=CHECK-FIXED-R9 < %t %s
|
||||
// CHECK-FIXED-R9: "-target-feature" "+reserve-r9"
|
||||
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r10 -### %s 2> %t
|
||||
// RUN: FileCheck --check-prefix=CHECK-FIXED-R10 < %t %s
|
||||
// CHECK-FIXED-R10: "-target-feature" "+reserve-r10"
|
||||
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r11 -### %s 2> %t
|
||||
// RUN: FileCheck --check-prefix=CHECK-FIXED-R11 < %t %s
|
||||
// CHECK-FIXED-R11: "-target-feature" "+reserve-r11"
|
||||
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r12 -### %s 2> %t
|
||||
// RUN: FileCheck --check-prefix=CHECK-FIXED-R12 < %t %s
|
||||
// CHECK-FIXED-R12: "-target-feature" "+reserve-r12"
|
||||
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r13 -### %s 2> %t
|
||||
// RUN: FileCheck --check-prefix=CHECK-FIXED-R13 < %t %s
|
||||
// CHECK-FIXED-R13: "-target-feature" "+reserve-r13"
|
||||
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r14 -### %s 2> %t
|
||||
// RUN: FileCheck --check-prefix=CHECK-FIXED-R14 < %t %s
|
||||
// CHECK-FIXED-R14: "-target-feature" "+reserve-r14"
|
||||
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu -ffixed-r15 -### %s 2> %t
|
||||
// RUN: FileCheck --check-prefix=CHECK-FIXED-R15 < %t %s
|
||||
// CHECK-FIXED-R15: "-target-feature" "+reserve-r15"
|
||||
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu -mapx-features=egpr -ffixed-r16 -### %s 2> %t
|
||||
// RUN: FileCheck --check-prefix=CHECK-FIXED-R16 < %t %s
|
||||
// CHECK-FIXED-R16: "-target-feature" "+reserve-r16"
|
||||
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu -mapx-features=egpr -ffixed-r31 -### %s 2> %t
|
||||
// RUN: FileCheck --check-prefix=CHECK-FIXED-R31 < %t %s
|
||||
// CHECK-FIXED-R31: "-target-feature" "+reserve-r31"
|
||||
|
||||
// RUN: not %clang --target=x86_64-unknown-linux-gnu -ffixed-r16 -### %s 2>&1 | FileCheck --check-prefix=CHECK-NO-APX %s
|
||||
// CHECK-NO-APX: error: unsupported option '-ffixed-r16' for target 'x86_64-unknown-linux-gnu'
|
||||
|
||||
// Test multiple of reserve-r# options together.
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu \
|
||||
// RUN: -ffixed-r8 \
|
||||
// RUN: -ffixed-r9 \
|
||||
// RUN: -ffixed-r15 \
|
||||
// RUN: -### %s 2> %t
|
||||
// RUN: FileCheck \
|
||||
// RUN: --check-prefix=CHECK-FIXED-R8 \
|
||||
// RUN: --check-prefix=CHECK-FIXED-R9 \
|
||||
// RUN: --check-prefix=CHECK-FIXED-R15 \
|
||||
// RUN: < %t %s
|
||||
|
||||
// Test all reserve-r# options together.
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu \
|
||||
// RUN: -ffixed-r8 \
|
||||
// RUN: -ffixed-r9 \
|
||||
// RUN: -ffixed-r10 \
|
||||
// RUN: -ffixed-r11 \
|
||||
// RUN: -ffixed-r12 \
|
||||
// RUN: -ffixed-r13 \
|
||||
// RUN: -ffixed-r14 \
|
||||
// RUN: -ffixed-r15 \
|
||||
// RUN: -### %s 2> %t
|
||||
// RUN: FileCheck \
|
||||
// RUN: --check-prefix=CHECK-FIXED-R8 \
|
||||
// RUN: --check-prefix=CHECK-FIXED-R9 \
|
||||
// RUN: --check-prefix=CHECK-FIXED-R10 \
|
||||
// RUN: --check-prefix=CHECK-FIXED-R11 \
|
||||
// RUN: --check-prefix=CHECK-FIXED-R12 \
|
||||
// RUN: --check-prefix=CHECK-FIXED-R13 \
|
||||
// RUN: --check-prefix=CHECK-FIXED-R14 \
|
||||
// RUN: --check-prefix=CHECK-FIXED-R15 \
|
||||
// RUN: < %t %s
|
||||
|
||||
// Test all reserve-r# options together with APX EGPR.
|
||||
// RUN: %clang --target=x86_64-unknown-linux-gnu \
|
||||
// RUN: -mapx-features=egpr \
|
||||
// RUN: -ffixed-r16 \
|
||||
// RUN: -ffixed-r17 \
|
||||
// RUN: -ffixed-r18 \
|
||||
// RUN: -ffixed-r19 \
|
||||
// RUN: -ffixed-r20 \
|
||||
// RUN: -ffixed-r21 \
|
||||
// RUN: -ffixed-r22 \
|
||||
// RUN: -ffixed-r23 \
|
||||
// RUN: -ffixed-r24 \
|
||||
// RUN: -ffixed-r25 \
|
||||
// RUN: -ffixed-r26 \
|
||||
// RUN: -ffixed-r27 \
|
||||
// RUN: -ffixed-r28 \
|
||||
// RUN: -ffixed-r29 \
|
||||
// RUN: -ffixed-r30 \
|
||||
// RUN: -ffixed-r31 \
|
||||
// RUN: -### %s 2> %t
|
||||
// RUN: FileCheck \
|
||||
// RUN: --check-prefix=CHECK-ALL-EGPR \
|
||||
// RUN: < %t %s
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r17"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r18"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r19"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r20"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r21"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r22"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r23"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r24"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r25"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r26"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r27"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r28"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r29"
|
||||
// CHECK-ALL-EGPR: "-target-feature" "+reserve-r30"
|
||||
@ -32,6 +32,13 @@ def IsX32 : SubtargetFeature<"x32", "IsX32", "true",
|
||||
// X86 Subtarget ISA features
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
foreach i = {8-15} in
|
||||
def FeatureReserveR#i : SubtargetFeature<"reserve-r"#i, "ReservedRReg[X86::R"#i#"]", "true",
|
||||
"Reserve R"#i#", making it unavailable as a GPR">;
|
||||
foreach i = {16-31} in
|
||||
def FeatureReserveR#i : SubtargetFeature<"reserve-r"#i, "ReservedRReg[X86::R"#i#"]", "true",
|
||||
"Reserve R"#i#", making it unavailable as a GPR">;
|
||||
|
||||
def FeatureX87 : SubtargetFeature<"x87","HasX87", "true",
|
||||
"Enable X87 float instructions">;
|
||||
|
||||
|
||||
@ -3211,6 +3211,14 @@ void X86FrameLowering::determineCalleeSaves(MachineFunction &MF,
|
||||
BasePtr = getX86SubSuperRegister(BasePtr, 64);
|
||||
SavedRegs.set(BasePtr);
|
||||
}
|
||||
if (STI.is64Bit()) {
|
||||
for (int Reg = SavedRegs.find_first(); Reg != -1;
|
||||
Reg = SavedRegs.find_next(Reg)) {
|
||||
if (STI.isRegisterReservedByUser(Reg)) {
|
||||
SavedRegs.reset(Reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool HasNestArgument(const MachineFunction *MF) {
|
||||
|
||||
@ -28763,6 +28763,9 @@ SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
|
||||
return FrameAddr;
|
||||
}
|
||||
|
||||
#define GET_REGISTER_MATCHER
|
||||
#include "X86GenAsmMatcher.inc"
|
||||
|
||||
// FIXME? Maybe this could be a TableGen attribute on some registers and
|
||||
// this table could be generated automatically from RegInfo.
|
||||
Register X86TargetLowering::getRegisterByName(const char* RegName, LLT VT,
|
||||
@ -28792,6 +28795,15 @@ Register X86TargetLowering::getRegisterByName(const char* RegName, LLT VT,
|
||||
#endif
|
||||
}
|
||||
|
||||
if (Reg)
|
||||
return Reg;
|
||||
|
||||
if (Subtarget.is64Bit()) {
|
||||
Reg = MatchRegisterName(RegName);
|
||||
if (!Subtarget.isRegisterReservedByUser(Reg))
|
||||
Reg = Register();
|
||||
}
|
||||
|
||||
return Reg;
|
||||
}
|
||||
|
||||
|
||||
@ -515,6 +515,17 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||
// Set the Shadow Stack Pointer as reserved.
|
||||
Reserved.set(X86::SSP);
|
||||
|
||||
auto &ST = MF.getSubtarget<X86Subtarget>();
|
||||
if (ST.is64Bit()) {
|
||||
for (size_t Reg = 0; Reg < getNumRegs(); Reg++) {
|
||||
// Set r# as reserved register if user required
|
||||
if (ST.isRegisterReservedByUser(Reg)) {
|
||||
for (const MCPhysReg &SubReg : subregs_inclusive(Reg))
|
||||
Reserved.set(SubReg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the instruction pointer register and its aliases as reserved.
|
||||
for (const MCPhysReg &SubReg : subregs_inclusive(X86::RIP))
|
||||
Reserved.set(SubReg);
|
||||
|
||||
@ -317,7 +317,8 @@ X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
|
||||
unsigned PreferVectorWidthOverride,
|
||||
unsigned RequiredVectorWidth)
|
||||
: X86GenSubtargetInfo(TT, CPU, TuneCPU, FS),
|
||||
PICStyle(PICStyles::Style::None), TM(TM), TargetTriple(TT),
|
||||
PICStyle(PICStyles::Style::None), TM(TM),
|
||||
ReservedRReg(X86::NUM_TARGET_REGS), TargetTriple(TT),
|
||||
StackAlignOverride(StackAlignOverride),
|
||||
PreferVectorWidthOverride(PreferVectorWidthOverride),
|
||||
RequiredVectorWidth(RequiredVectorWidth),
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include "X86ISelLowering.h"
|
||||
#include "X86InstrInfo.h"
|
||||
#include "X86SelectionDAGInfo.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
||||
#include "llvm/IR/CallingConv.h"
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
@ -65,6 +66,9 @@ class X86Subtarget final : public X86GenSubtargetInfo {
|
||||
#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
|
||||
bool ATTRIBUTE = DEFAULT;
|
||||
#include "X86GenSubtargetInfo.inc"
|
||||
/// ReservedRReg R#i is not available as a general purpose register.
|
||||
BitVector ReservedRReg;
|
||||
|
||||
/// The minimum alignment known to hold of the stack frame on
|
||||
/// entry to the function and which must be maintained by every function.
|
||||
Align stackAlignment = Align(4);
|
||||
@ -155,6 +159,10 @@ public:
|
||||
const LegalizerInfo *getLegalizerInfo() const override;
|
||||
const RegisterBankInfo *getRegBankInfo() const override;
|
||||
|
||||
bool isRegisterReservedByUser(Register i) const override {
|
||||
return ReservedRReg[i.id()];
|
||||
}
|
||||
|
||||
private:
|
||||
/// Initialize the full set of dependencies so we can use an initializer
|
||||
/// list for X86Subtarget.
|
||||
|
||||
114
llvm/test/CodeGen/X86/reserveRreg.ll
Normal file
114
llvm/test/CodeGen/X86/reserveRreg.ll
Normal file
@ -0,0 +1,114 @@
|
||||
;; Check if manually reserved registers are always excluded from being saved by
|
||||
;; the function prolog/epilog, even for callee-saved ones, as per GCC behavior.
|
||||
|
||||
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
|
||||
|
||||
define preserve_mostcc void @t8() "target-features"="+reserve-r8" {
|
||||
; CHECK-LABEL: t8:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl $256, %r8d
|
||||
; CHECK-NEXT: #APP
|
||||
; CHECK-NEXT: #NO_APP
|
||||
; CHECK-NEXT: ret
|
||||
call i64 asm sideeffect "", "={r8},{r8}"(i64 256)
|
||||
ret void
|
||||
}
|
||||
|
||||
define preserve_mostcc void @t9() "target-features"="+reserve-r9" {
|
||||
; CHECK-LABEL: t9:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl $256, %r9d
|
||||
; CHECK-NEXT: #APP
|
||||
; CHECK-NEXT: #NO_APP
|
||||
; CHECK-NEXT: ret
|
||||
call i64 asm sideeffect "", "={r9},{r9}"(i64 256)
|
||||
ret void
|
||||
}
|
||||
|
||||
define preserve_mostcc void @t10() "target-features"="+reserve-r10" {
|
||||
; CHECK-LABEL: t10:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl $256, %r10d
|
||||
; CHECK-NEXT: #APP
|
||||
; CHECK-NEXT: #NO_APP
|
||||
; CHECK-NEXT: ret
|
||||
call i64 asm sideeffect "", "={r10},{r10}"(i64 256)
|
||||
ret void
|
||||
}
|
||||
|
||||
define preserve_mostcc void @t11() "target-features"="+reserve-r11" {
|
||||
; CHECK-LABEL: t11:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl $256, %r11d
|
||||
; CHECK-NEXT: #APP
|
||||
; CHECK-NEXT: #NO_APP
|
||||
; CHECK-NEXT: ret
|
||||
call i64 asm sideeffect "", "={r11},{r11}"(i64 256)
|
||||
ret void
|
||||
}
|
||||
|
||||
define preserve_mostcc void @t12() "target-features"="+reserve-r12" {
|
||||
; CHECK-LABEL: t12:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl $256, %r12d
|
||||
; CHECK-NEXT: #APP
|
||||
; CHECK-NEXT: #NO_APP
|
||||
; CHECK-NEXT: ret
|
||||
call i64 asm sideeffect "", "={r12},{r12}"(i64 256)
|
||||
ret void
|
||||
}
|
||||
|
||||
define preserve_mostcc void @t13() "target-features"="+reserve-r13" {
|
||||
; CHECK-LABEL: t13:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl $256, %r13d
|
||||
; CHECK-NEXT: #APP
|
||||
; CHECK-NEXT: #NO_APP
|
||||
; CHECK-NEXT: ret
|
||||
call i64 asm sideeffect "", "={r13},{r13}"(i64 256)
|
||||
ret void
|
||||
}
|
||||
|
||||
define preserve_mostcc void @t14() "target-features"="+reserve-r14" {
|
||||
; CHECK-LABEL: t14:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl $256, %r14d
|
||||
; CHECK-NEXT: #APP
|
||||
; CHECK-NEXT: #NO_APP
|
||||
; CHECK-NEXT: ret
|
||||
call i64 asm sideeffect "", "={r14},{r14}"(i64 256)
|
||||
ret void
|
||||
}
|
||||
|
||||
define preserve_mostcc void @t15() "target-features"="+reserve-r15" {
|
||||
; CHECK-LABEL: t15:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl $256, %r15d
|
||||
; CHECK-NEXT: #APP
|
||||
; CHECK-NEXT: #NO_APP
|
||||
; CHECK-NEXT: ret
|
||||
call i64 asm sideeffect "", "={r15},{r15}"(i64 256)
|
||||
ret void
|
||||
}
|
||||
|
||||
define preserve_mostcc void @t16() "target-features"="+egpr,+reserve-r16" {
|
||||
; CHECK-LABEL: t16:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl $256, %r16d
|
||||
; CHECK-NEXT: #APP
|
||||
; CHECK-NEXT: #NO_APP
|
||||
; CHECK-NEXT: ret
|
||||
call i64 asm sideeffect "", "={r16},{r16}"(i64 256)
|
||||
ret void
|
||||
}
|
||||
|
||||
define preserve_mostcc void @t31() "target-features"="+egpr,+reserve-r31" {
|
||||
; CHECK-LABEL: t31:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl $256, %r31d
|
||||
; CHECK-NEXT: #APP
|
||||
; CHECK-NEXT: #NO_APP
|
||||
; CHECK-NEXT: ret
|
||||
call i64 asm sideeffect "", "={r31},{r31}"(i64 256)
|
||||
ret void
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user