diff options
author | Alex Bradbury <asb@lowrisc.org> | 2018-01-10 20:12:00 +0000 |
---|---|---|
committer | Alex Bradbury <asb@lowrisc.org> | 2018-01-10 20:12:00 +0000 |
commit | 70f137b6bfe551f5ede1a27b985ba7906adac990 (patch) | |
tree | 4d77f90f43b59a1d13532759a4bf98c4b5997230 | |
parent | 9330e64485aee847682704ddb62750d4b2badf22 (diff) | |
download | bcm5719-llvm-70f137b6bfe551f5ede1a27b985ba7906adac990.tar.gz bcm5719-llvm-70f137b6bfe551f5ede1a27b985ba7906adac990.zip |
[RISCV] Add support for llvm.{frameaddress,returnaddress} intrinsics
llvm-svn: 322218
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 57 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelLowering.h | 2 | ||||
-rw-r--r-- | llvm/test/CodeGen/RISCV/frameaddr-returnaddr.ll | 99 |
3 files changed, 158 insertions, 0 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 0dec008a3e9..d5d23129ff9 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -166,6 +166,10 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op, return lowerSELECT(Op, DAG); case ISD::VASTART: return lowerVASTART(Op, DAG); + case ISD::FRAMEADDR: + return LowerFRAMEADDR(Op, DAG); + case ISD::RETURNADDR: + return LowerRETURNADDR(Op, DAG); } } @@ -284,6 +288,59 @@ SDValue RISCVTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { MachinePointerInfo(SV)); } +SDValue RISCVTargetLowering::LowerFRAMEADDR(SDValue Op, + SelectionDAG &DAG) const { + const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo(); + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + MFI.setFrameAddressIsTaken(true); + unsigned FrameReg = RI.getFrameRegister(MF); + int XLenInBytes = Subtarget.getXLen() / 8; + + EVT VT = Op.getValueType(); + SDLoc DL(Op); + SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameReg, VT); + unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); + while (Depth--) { + int Offset = -(XLenInBytes * 2); + SDValue Ptr = DAG.getNode(ISD::ADD, DL, VT, FrameAddr, + DAG.getIntPtrConstant(Offset, DL)); + FrameAddr = + DAG.getLoad(VT, DL, DAG.getEntryNode(), Ptr, MachinePointerInfo()); + } + return FrameAddr; +} + +SDValue RISCVTargetLowering::LowerRETURNADDR(SDValue Op, + SelectionDAG &DAG) const { + const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo(); + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + MFI.setReturnAddressIsTaken(true); + MVT XLenVT = Subtarget.getXLenVT(); + int XLenInBytes = Subtarget.getXLen() / 8; + + if (verifyReturnAddressArgumentIsConstant(Op, DAG)) + return SDValue(); + + EVT VT = Op.getValueType(); + SDLoc DL(Op); + unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); + if (Depth) { + int Off = -XLenInBytes; + SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); + SDValue Offset = DAG.getConstant(Off, DL, VT); + return DAG.getLoad(VT, DL, DAG.getEntryNode(), + DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset), + MachinePointerInfo()); + } + + // Return the value of the return address register, marking it an implicit + // live-in. + unsigned Reg = MF.addLiveIn(RI.getRARegister(), getRegClassFor(XLenVT)); + return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, XLenVT); +} + MachineBasicBlock * RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index 2f9c202fb64..8ee00cd69a1 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -83,6 +83,8 @@ private: SDValue lowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const; SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const; SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; }; } diff --git a/llvm/test/CodeGen/RISCV/frameaddr-returnaddr.ll b/llvm/test/CodeGen/RISCV/frameaddr-returnaddr.ll new file mode 100644 index 00000000000..eafe0da31fc --- /dev/null +++ b/llvm/test/CodeGen/RISCV/frameaddr-returnaddr.ll @@ -0,0 +1,99 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32I %s + +declare void @notdead(i8*) +declare i8* @llvm.frameaddress(i32) +declare i8* @llvm.returnaddress(i32) + +define i8* @test_frameaddress_0() nounwind { +; RV32I-LABEL: test_frameaddress_0: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw s0, 8(sp) +; RV32I-NEXT: addi s0, sp, 16 +; RV32I-NEXT: mv a0, s0 +; RV32I-NEXT: lw s0, 8(sp) +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = call i8* @llvm.frameaddress(i32 0) + ret i8* %1 +} + +define i8* @test_frameaddress_2() nounwind { +; RV32I-LABEL: test_frameaddress_2: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw s0, 8(sp) +; RV32I-NEXT: addi s0, sp, 16 +; RV32I-NEXT: lw a0, -8(s0) +; RV32I-NEXT: lw a0, -8(a0) +; RV32I-NEXT: lw s0, 8(sp) +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = call i8* @llvm.frameaddress(i32 2) + ret i8* %1 +} + +define i8* @test_frameaddress_3_alloca() nounwind { +; RV32I-LABEL: test_frameaddress_3_alloca: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -112 +; RV32I-NEXT: sw ra, 108(sp) +; RV32I-NEXT: sw s0, 104(sp) +; RV32I-NEXT: addi s0, sp, 112 +; RV32I-NEXT: lui a0, %hi(notdead) +; RV32I-NEXT: addi a1, a0, %lo(notdead) +; RV32I-NEXT: addi a0, s0, -108 +; RV32I-NEXT: jalr a1 +; RV32I-NEXT: lw a0, -8(s0) +; RV32I-NEXT: lw a0, -8(a0) +; RV32I-NEXT: lw a0, -8(a0) +; RV32I-NEXT: lw s0, 104(sp) +; RV32I-NEXT: lw ra, 108(sp) +; RV32I-NEXT: addi sp, sp, 112 +; RV32I-NEXT: ret + %1 = alloca [100 x i8] + %2 = bitcast [100 x i8]* %1 to i8* + call void @notdead(i8* %2) + %3 = call i8* @llvm.frameaddress(i32 3) + ret i8* %3 +} + +define i8* @test_returnaddress_0() nounwind { +; RV32I-LABEL: test_returnaddress_0: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw s0, 8(sp) +; RV32I-NEXT: addi s0, sp, 16 +; RV32I-NEXT: mv a0, ra +; RV32I-NEXT: lw s0, 8(sp) +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = call i8* @llvm.returnaddress(i32 0) + ret i8* %1 +} + +define i8* @test_returnaddress_2() nounwind { +; RV32I-LABEL: test_returnaddress_2: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw s0, 8(sp) +; RV32I-NEXT: addi s0, sp, 16 +; RV32I-NEXT: lw a0, -8(s0) +; RV32I-NEXT: lw a0, -8(a0) +; RV32I-NEXT: lw a0, -4(a0) +; RV32I-NEXT: lw s0, 8(sp) +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret + %1 = call i8* @llvm.returnaddress(i32 2) + ret i8* %1 +} |