mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
Allow {e,r}bp as the target of {read,write}_register.
This patch allows the read_register and write_register intrinsics to read/write the RBP/EBP registers on X86 iff the targeted register is the frame pointer for the containing function. Differential Revision: http://reviews.llvm.org/D10977 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241827 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
dc219dddde
commit
db5a82b861
@ -2487,7 +2487,8 @@ public:
|
||||
/// Return the register ID of the name passed in. Used by named register
|
||||
/// global variables extension. There is no target-independent behaviour
|
||||
/// so the default action is to bail.
|
||||
virtual unsigned getRegisterByName(const char* RegName, EVT VT) const {
|
||||
virtual unsigned getRegisterByName(const char* RegName, EVT VT,
|
||||
SelectionDAG &DAG) const {
|
||||
report_fatal_error("Named registers not implemented for this target");
|
||||
}
|
||||
|
||||
|
@ -1932,7 +1932,8 @@ SDNode
|
||||
MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(Op->getOperand(1));
|
||||
const MDString *RegStr = dyn_cast<MDString>(MD->getMD()->getOperand(0));
|
||||
unsigned Reg =
|
||||
TLI->getRegisterByName(RegStr->getString().data(), Op->getValueType(0));
|
||||
TLI->getRegisterByName(RegStr->getString().data(), Op->getValueType(0),
|
||||
*CurDAG);
|
||||
SDValue New = CurDAG->getCopyFromReg(
|
||||
Op->getOperand(0), dl, Reg, Op->getValueType(0));
|
||||
New->setNodeId(-1);
|
||||
@ -1945,7 +1946,8 @@ SDNode
|
||||
MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(Op->getOperand(1));
|
||||
const MDString *RegStr = dyn_cast<MDString>(MD->getMD()->getOperand(0));
|
||||
unsigned Reg = TLI->getRegisterByName(RegStr->getString().data(),
|
||||
Op->getOperand(2).getValueType());
|
||||
Op->getOperand(2).getValueType(),
|
||||
*CurDAG);
|
||||
SDValue New = CurDAG->getCopyToReg(
|
||||
Op->getOperand(0), dl, Reg, Op->getOperand(2));
|
||||
New->setNodeId(-1);
|
||||
|
@ -4065,8 +4065,8 @@ SDValue AArch64TargetLowering::LowerFRAMEADDR(SDValue Op,
|
||||
|
||||
// FIXME? Maybe this could be a TableGen attribute on some registers and
|
||||
// this table could be generated automatically from RegInfo.
|
||||
unsigned AArch64TargetLowering::getRegisterByName(const char* RegName,
|
||||
EVT VT) const {
|
||||
unsigned AArch64TargetLowering::getRegisterByName(const char* RegName, EVT VT,
|
||||
SelectionDAG &DAG) const {
|
||||
unsigned Reg = StringSwitch<unsigned>(RegName)
|
||||
.Case("sp", AArch64::SP)
|
||||
.Default(0);
|
||||
|
@ -473,7 +473,8 @@ private:
|
||||
bool combineRepeatedFPDivisors(unsigned NumUsers) const override;
|
||||
|
||||
ConstraintType getConstraintType(StringRef Constraint) const override;
|
||||
unsigned getRegisterByName(const char* RegName, EVT VT) const override;
|
||||
unsigned getRegisterByName(const char* RegName, EVT VT,
|
||||
SelectionDAG &DAG) const override;
|
||||
|
||||
/// Examine constraint string and operand type and determine a weight value.
|
||||
/// The operand object must already have been set up with the operand type.
|
||||
|
@ -4101,8 +4101,8 @@ SDValue ARMTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
|
||||
|
||||
// FIXME? Maybe this could be a TableGen attribute on some registers and
|
||||
// this table could be generated automatically from RegInfo.
|
||||
unsigned ARMTargetLowering::getRegisterByName(const char* RegName,
|
||||
EVT VT) const {
|
||||
unsigned ARMTargetLowering::getRegisterByName(const char* RegName, EVT VT,
|
||||
SelectionDAG &DAG) const {
|
||||
unsigned Reg = StringSwitch<unsigned>(RegName)
|
||||
.Case("sp", ARM::SP)
|
||||
.Default(0);
|
||||
|
@ -532,7 +532,8 @@ namespace llvm {
|
||||
SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
unsigned getRegisterByName(const char* RegName, EVT VT) const override;
|
||||
unsigned getRegisterByName(const char* RegName, EVT VT,
|
||||
SelectionDAG &DAG) const override;
|
||||
|
||||
/// isFMAFasterThanFMulAndFAdd - Return true if an FMA operation is faster
|
||||
/// than a pair of fmul and fadd instructions. fmuladd intrinsics will be
|
||||
|
@ -3927,8 +3927,8 @@ MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB,
|
||||
|
||||
// FIXME? Maybe this could be a TableGen attribute on some registers and
|
||||
// this table could be generated automatically from RegInfo.
|
||||
unsigned MipsTargetLowering::getRegisterByName(const char* RegName,
|
||||
EVT VT) const {
|
||||
unsigned MipsTargetLowering::getRegisterByName(const char* RegName, EVT VT,
|
||||
SelectionDAG &DAG) const {
|
||||
// Named registers is expected to be fairly rare. For now, just support $28
|
||||
// since the linux kernel uses it.
|
||||
if (Subtarget.isGP64bit()) {
|
||||
|
@ -266,7 +266,8 @@ namespace llvm {
|
||||
|
||||
void HandleByVal(CCState *, unsigned &, unsigned) const override;
|
||||
|
||||
unsigned getRegisterByName(const char* RegName, EVT VT) const override;
|
||||
unsigned getRegisterByName(const char* RegName, EVT VT,
|
||||
SelectionDAG &DAG) const override;
|
||||
|
||||
protected:
|
||||
SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const;
|
||||
|
@ -11031,8 +11031,8 @@ SDValue PPCTargetLowering::LowerFRAMEADDR(SDValue Op,
|
||||
|
||||
// FIXME? Maybe this could be a TableGen attribute on some registers and
|
||||
// this table could be generated automatically from RegInfo.
|
||||
unsigned PPCTargetLowering::getRegisterByName(const char* RegName,
|
||||
EVT VT) const {
|
||||
unsigned PPCTargetLowering::getRegisterByName(const char* RegName, EVT VT,
|
||||
SelectionDAG &DAG) const {
|
||||
bool isPPC64 = Subtarget.isPPC64();
|
||||
bool isDarwinABI = Subtarget.isDarwinABI();
|
||||
|
||||
|
@ -490,7 +490,8 @@ namespace llvm {
|
||||
SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG,
|
||||
std::vector<SDNode *> *Created) const override;
|
||||
|
||||
unsigned getRegisterByName(const char* RegName, EVT VT) const override;
|
||||
unsigned getRegisterByName(const char* RegName, EVT VT,
|
||||
SelectionDAG &DAG) const override;
|
||||
|
||||
void computeKnownBitsForTargetNode(const SDValue Op,
|
||||
APInt &KnownZero,
|
||||
|
@ -16262,14 +16262,36 @@ SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
|
||||
|
||||
// FIXME? Maybe this could be a TableGen attribute on some registers and
|
||||
// this table could be generated automatically from RegInfo.
|
||||
unsigned X86TargetLowering::getRegisterByName(const char* RegName,
|
||||
EVT VT) const {
|
||||
unsigned X86TargetLowering::getRegisterByName(const char* RegName, EVT VT,
|
||||
SelectionDAG &DAG) const {
|
||||
const TargetFrameLowering &TFI = *Subtarget->getFrameLowering();
|
||||
const MachineFunction &MF = DAG.getMachineFunction();
|
||||
|
||||
unsigned Reg = StringSwitch<unsigned>(RegName)
|
||||
.Case("esp", X86::ESP)
|
||||
.Case("rsp", X86::RSP)
|
||||
.Case("ebp", X86::EBP)
|
||||
.Case("rbp", X86::RBP)
|
||||
.Default(0);
|
||||
|
||||
if (Reg == X86::EBP || Reg == X86::RBP) {
|
||||
if (!TFI.hasFP(MF))
|
||||
report_fatal_error("register " + StringRef(RegName) +
|
||||
" is allocatable: function has no frame pointer");
|
||||
#ifndef NDEBUG
|
||||
else {
|
||||
const X86RegisterInfo *RegInfo = Subtarget->getRegisterInfo();
|
||||
unsigned FrameReg =
|
||||
RegInfo->getPtrSizedFrameRegister(DAG.getMachineFunction());
|
||||
assert((FrameReg == X86::EBP || FrameReg == X86::RBP) &&
|
||||
"Invalid Frame Register!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (Reg)
|
||||
return Reg;
|
||||
|
||||
report_fatal_error("Invalid register name global variable");
|
||||
}
|
||||
|
||||
|
@ -873,7 +873,8 @@ namespace llvm {
|
||||
return nullptr; // nothing to do, move along.
|
||||
}
|
||||
|
||||
unsigned getRegisterByName(const char* RegName, EVT VT) const override;
|
||||
unsigned getRegisterByName(const char* RegName, EVT VT,
|
||||
SelectionDAG &DAG) const override;
|
||||
|
||||
/// This method returns a target specific FastISel object,
|
||||
/// or null if the target does not support "fast" ISel.
|
||||
|
30
test/CodeGen/X86/frameregister.ll
Normal file
30
test/CodeGen/X86/frameregister.ll
Normal file
@ -0,0 +1,30 @@
|
||||
; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=x86_64-linux-gnueabi | FileCheck %s
|
||||
; RUN: opt < %s -O3 -S -mtriple=x86_64-linux-gnueabi | FileCheck %s --check-prefix=OPT
|
||||
|
||||
define i64 @get_frame() #0 {
|
||||
entry:
|
||||
; CHECK-LABEL: get_frame:
|
||||
; CHECK: movq %rbp, %rax
|
||||
%sp = call i64 @llvm.read_register.i64(metadata !0)
|
||||
; OPT: @llvm.read_register.i64
|
||||
ret i64 %sp
|
||||
}
|
||||
|
||||
define void @set_frame(i64 %val) #0 {
|
||||
entry:
|
||||
; CHECK-LABEL: set_frame:
|
||||
; CHECK: movq %rdi, %rbp
|
||||
call void @llvm.write_register.i64(metadata !0, i64 %val)
|
||||
; OPT: @llvm.write_register.i64
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i64 @llvm.read_register.i64(metadata) nounwind
|
||||
declare void @llvm.write_register.i64(metadata, i64) nounwind
|
||||
|
||||
; register unsigned long current_stack_pointer asm("rbp");
|
||||
; CHECK-NOT: .asciz "rbp"
|
||||
!0 = !{!"rbp\00"}
|
||||
|
||||
attributes #0 = { nounwind "no-frame-pointer-elim"="true" }
|
12
test/CodeGen/X86/read-fp-no-frame-pointer.ll
Normal file
12
test/CodeGen/X86/read-fp-no-frame-pointer.ll
Normal file
@ -0,0 +1,12 @@
|
||||
; RUN: not llc < %s -mtriple=x86_64-linux-gnueabi 2>&1 | FileCheck %s
|
||||
|
||||
define i32 @get_frame() nounwind {
|
||||
entry:
|
||||
; CHECK: register ebp is allocatable: function has no frame pointer
|
||||
%fp = call i32 @llvm.read_register.i32(metadata !0)
|
||||
ret i32 %fp
|
||||
}
|
||||
|
||||
declare i32 @llvm.read_register.i32(metadata) nounwind
|
||||
|
||||
!0 = !{!"ebp\00"}
|
Loading…
Reference in New Issue
Block a user