llvm.org GIT mirror llvm / db5a82b
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 Pat Gavlin 5 years ago
14 changed file(s) with 90 addition(s) and 18 deletion(s). Raw diff Collapse all Expand all
24862486 /// Return the register ID of the name passed in. Used by named register
24872487 /// global variables extension. There is no target-independent behaviour
24882488 /// so the default action is to bail.
2489 virtual unsigned getRegisterByName(const char* RegName, EVT VT) const {
2489 virtual unsigned getRegisterByName(const char* RegName, EVT VT,
2490 SelectionDAG &DAG) const {
24902491 report_fatal_error("Named registers not implemented for this target");
24912492 }
24922493
19311931 MDNodeSDNode *MD = dyn_cast(Op->getOperand(1));
19321932 const MDString *RegStr = dyn_cast(MD->getMD()->getOperand(0));
19331933 unsigned Reg =
1934 TLI->getRegisterByName(RegStr->getString().data(), Op->getValueType(0));
1934 TLI->getRegisterByName(RegStr->getString().data(), Op->getValueType(0),
1935 *CurDAG);
19351936 SDValue New = CurDAG->getCopyFromReg(
19361937 Op->getOperand(0), dl, Reg, Op->getValueType(0));
19371938 New->setNodeId(-1);
19441945 MDNodeSDNode *MD = dyn_cast(Op->getOperand(1));
19451946 const MDString *RegStr = dyn_cast(MD->getMD()->getOperand(0));
19461947 unsigned Reg = TLI->getRegisterByName(RegStr->getString().data(),
1947 Op->getOperand(2).getValueType());
1948 Op->getOperand(2).getValueType(),
1949 *CurDAG);
19481950 SDValue New = CurDAG->getCopyToReg(
19491951 Op->getOperand(0), dl, Reg, Op->getOperand(2));
19501952 New->setNodeId(-1);
40644064
40654065 // FIXME? Maybe this could be a TableGen attribute on some registers and
40664066 // this table could be generated automatically from RegInfo.
4067 unsigned AArch64TargetLowering::getRegisterByName(const char* RegName,
4068 EVT VT) const {
4067 unsigned AArch64TargetLowering::getRegisterByName(const char* RegName, EVT VT,
4068 SelectionDAG &DAG) const {
40694069 unsigned Reg = StringSwitch(RegName)
40704070 .Case("sp", AArch64::SP)
40714071 .Default(0);
472472 bool combineRepeatedFPDivisors(unsigned NumUsers) const override;
473473
474474 ConstraintType getConstraintType(StringRef Constraint) const override;
475 unsigned getRegisterByName(const char* RegName, EVT VT) const override;
475 unsigned getRegisterByName(const char* RegName, EVT VT,
476 SelectionDAG &DAG) const override;
476477
477478 /// Examine constraint string and operand type and determine a weight value.
478479 /// The operand object must already have been set up with the operand type.
41004100
41014101 // FIXME? Maybe this could be a TableGen attribute on some registers and
41024102 // this table could be generated automatically from RegInfo.
4103 unsigned ARMTargetLowering::getRegisterByName(const char* RegName,
4104 EVT VT) const {
4103 unsigned ARMTargetLowering::getRegisterByName(const char* RegName, EVT VT,
4104 SelectionDAG &DAG) const {
41054105 unsigned Reg = StringSwitch(RegName)
41064106 .Case("sp", ARM::SP)
41074107 .Default(0);
531531 SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const;
532532 SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
533533
534 unsigned getRegisterByName(const char* RegName, EVT VT) const override;
534 unsigned getRegisterByName(const char* RegName, EVT VT,
535 SelectionDAG &DAG) const override;
535536
536537 /// isFMAFasterThanFMulAndFAdd - Return true if an FMA operation is faster
537538 /// than a pair of fmul and fadd instructions. fmuladd intrinsics will be
39263926
39273927 // FIXME? Maybe this could be a TableGen attribute on some registers and
39283928 // this table could be generated automatically from RegInfo.
3929 unsigned MipsTargetLowering::getRegisterByName(const char* RegName,
3930 EVT VT) const {
3929 unsigned MipsTargetLowering::getRegisterByName(const char* RegName, EVT VT,
3930 SelectionDAG &DAG) const {
39313931 // Named registers is expected to be fairly rare. For now, just support $28
39323932 // since the linux kernel uses it.
39333933 if (Subtarget.isGP64bit()) {
265265
266266 void HandleByVal(CCState *, unsigned &, unsigned) const override;
267267
268 unsigned getRegisterByName(const char* RegName, EVT VT) const override;
268 unsigned getRegisterByName(const char* RegName, EVT VT,
269 SelectionDAG &DAG) const override;
269270
270271 protected:
271272 SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const;
1103011030
1103111031 // FIXME? Maybe this could be a TableGen attribute on some registers and
1103211032 // this table could be generated automatically from RegInfo.
11033 unsigned PPCTargetLowering::getRegisterByName(const char* RegName,
11034 EVT VT) const {
11033 unsigned PPCTargetLowering::getRegisterByName(const char* RegName, EVT VT,
11034 SelectionDAG &DAG) const {
1103511035 bool isPPC64 = Subtarget.isPPC64();
1103611036 bool isDarwinABI = Subtarget.isDarwinABI();
1103711037
489489 SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG,
490490 std::vector *Created) const override;
491491
492 unsigned getRegisterByName(const char* RegName, EVT VT) const override;
492 unsigned getRegisterByName(const char* RegName, EVT VT,
493 SelectionDAG &DAG) const override;
493494
494495 void computeKnownBitsForTargetNode(const SDValue Op,
495496 APInt &KnownZero,
1626116261
1626216262 // FIXME? Maybe this could be a TableGen attribute on some registers and
1626316263 // this table could be generated automatically from RegInfo.
16264 unsigned X86TargetLowering::getRegisterByName(const char* RegName,
16265 EVT VT) const {
16264 unsigned X86TargetLowering::getRegisterByName(const char* RegName, EVT VT,
16265 SelectionDAG &DAG) const {
16266 const TargetFrameLowering &TFI = *Subtarget->getFrameLowering();
16267 const MachineFunction &MF = DAG.getMachineFunction();
16268
1626616269 unsigned Reg = StringSwitch(RegName)
1626716270 .Case("esp", X86::ESP)
1626816271 .Case("rsp", X86::RSP)
16272 .Case("ebp", X86::EBP)
16273 .Case("rbp", X86::RBP)
1626916274 .Default(0);
16275
16276 if (Reg == X86::EBP || Reg == X86::RBP) {
16277 if (!TFI.hasFP(MF))
16278 report_fatal_error("register " + StringRef(RegName) +
16279 " is allocatable: function has no frame pointer");
16280 #ifndef NDEBUG
16281 else {
16282 const X86RegisterInfo *RegInfo = Subtarget->getRegisterInfo();
16283 unsigned FrameReg =
16284 RegInfo->getPtrSizedFrameRegister(DAG.getMachineFunction());
16285 assert((FrameReg == X86::EBP || FrameReg == X86::RBP) &&
16286 "Invalid Frame Register!");
16287 }
16288 #endif
16289 }
16290
1627016291 if (Reg)
1627116292 return Reg;
16293
1627216294 report_fatal_error("Invalid register name global variable");
1627316295 }
1627416296
872872 return nullptr; // nothing to do, move along.
873873 }
874874
875 unsigned getRegisterByName(const char* RegName, EVT VT) const override;
875 unsigned getRegisterByName(const char* RegName, EVT VT,
876 SelectionDAG &DAG) const override;
876877
877878 /// This method returns a target specific FastISel object,
878879 /// or null if the target does not support "fast" ISel.
0 ; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
1 ; RUN: llc < %s -mtriple=x86_64-linux-gnueabi | FileCheck %s
2 ; RUN: opt < %s -O3 -S -mtriple=x86_64-linux-gnueabi | FileCheck %s --check-prefix=OPT
3
4 define i64 @get_frame() #0 {
5 entry:
6 ; CHECK-LABEL: get_frame:
7 ; CHECK: movq %rbp, %rax
8 %sp = call i64 @llvm.read_register.i64(metadata !0)
9 ; OPT: @llvm.read_register.i64
10 ret i64 %sp
11 }
12
13 define void @set_frame(i64 %val) #0 {
14 entry:
15 ; CHECK-LABEL: set_frame:
16 ; CHECK: movq %rdi, %rbp
17 call void @llvm.write_register.i64(metadata !0, i64 %val)
18 ; OPT: @llvm.write_register.i64
19 ret void
20 }
21
22 declare i64 @llvm.read_register.i64(metadata) nounwind
23 declare void @llvm.write_register.i64(metadata, i64) nounwind
24
25 ; register unsigned long current_stack_pointer asm("rbp");
26 ; CHECK-NOT: .asciz "rbp"
27 !0 = !{!"rbp\00"}
28
29 attributes #0 = { nounwind "no-frame-pointer-elim"="true" }
0 ; RUN: not llc < %s -mtriple=x86_64-linux-gnueabi 2>&1 | FileCheck %s
1
2 define i32 @get_frame() nounwind {
3 entry:
4 ; CHECK: register ebp is allocatable: function has no frame pointer
5 %fp = call i32 @llvm.read_register.i32(metadata !0)
6 ret i32 %fp
7 }
8
9 declare i32 @llvm.read_register.i32(metadata) nounwind
10
11 !0 = !{!"ebp\00"}