From a210ae9ea425993d5961497fbd68867dc91f64f1 Mon Sep 17 00:00:00 2001 From: Andrei Safronov <safronov@espressif.com> Date: Thu, 5 Sep 2024 10:59:44 +0300 Subject: [PATCH 1/3] [Xtensa] Lowering FRAMEADDR/RETURNADDR operations. --- llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 42 +++++++++++++++++++ llvm/lib/Target/Xtensa/XtensaISelLowering.h | 4 ++ .../CodeGen/Xtensa/frameaddr-returnaddr.ll | 22 ++++++++++ 3 files changed, 68 insertions(+) create mode 100644 llvm/test/CodeGen/Xtensa/frameaddr-returnaddr.ll diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp index 0d2ce26a942e0..97d9c3e9f9f47 100644 --- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp @@ -594,6 +594,26 @@ SDValue XtensaTargetLowering::LowerSELECT_CC(SDValue Op, FalseValue, TargetCC); } +SDValue XtensaTargetLowering::LowerRETURNADDR(SDValue Op, + SelectionDAG &DAG) const { + // check the depth + // TODO: xtensa-gcc can handle this, by navigating through the stack, we + // should be able to do this too + assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && + "Return address can be determined only for current frame."); + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + EVT VT = Op.getValueType(); + unsigned RA = Xtensa::A0; + MFI.setReturnAddressIsTaken(true); + + // Return RA, which contains the return address. Mark it an implicit + // live-in. + unsigned Register = MF.addLiveIn(RA, getRegClassFor(MVT::i32)); + return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), Register, VT); +} + SDValue XtensaTargetLowering::LowerImmediate(SDValue Op, SelectionDAG &DAG) const { const ConstantSDNode *CN = cast<ConstantSDNode>(Op); @@ -722,6 +742,24 @@ SDValue XtensaTargetLowering::LowerSTACKRESTORE(SDValue Op, Op.getOperand(1)); } +SDValue XtensaTargetLowering::LowerFRAMEADDR(SDValue Op, + SelectionDAG &DAG) const { + // check the depth + assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && + "Frame address can only be determined for current frame."); + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); + MFI.setFrameAddressIsTaken(true); + EVT VT = Op.getValueType(); + SDLoc DL(Op); + + unsigned FrameRegister = Subtarget.getRegisterInfo()->getFrameRegister(MF); + SDValue FrameAddr = + DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameRegister, VT); + return FrameAddr; +} + SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const { SDValue Chain = Op.getOperand(0); // Legalize the chain. @@ -867,6 +905,8 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op, return LowerBR_JT(Op, DAG); case ISD::Constant: return LowerImmediate(Op, DAG); + case ISD::RETURNADDR: + return LowerRETURNADDR(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); case ISD::BlockAddress: @@ -883,6 +923,8 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op, return LowerSTACKSAVE(Op, DAG); case ISD::STACKRESTORE: return LowerSTACKRESTORE(Op, DAG); + case ISD::FRAMEADDR: + return LowerFRAMEADDR(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); case ISD::SHL_PARTS: diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h index 8e7346b40dfe5..2a878e45047d2 100644 --- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h @@ -125,12 +125,16 @@ class XtensaTargetLowering : public TargetLowering { SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; diff --git a/llvm/test/CodeGen/Xtensa/frameaddr-returnaddr.ll b/llvm/test/CodeGen/Xtensa/frameaddr-returnaddr.ll new file mode 100644 index 0000000000000..69c22733c107a --- /dev/null +++ b/llvm/test/CodeGen/Xtensa/frameaddr-returnaddr.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=xtensa -verify-machineinstrs < %s \ +; RUN: | FileCheck %s + +declare ptr @llvm.frameaddress(i32) +declare ptr @llvm.returnaddress(i32) + +define ptr @test_frameaddress_0() nounwind { +; CHECK-LABEL: test_frameaddress_0: +; CHECK: or a2, a1, a1 +; CHECK-NEXT: ret + %1 = call ptr @llvm.frameaddress(i32 0) + ret ptr %1 +} + +define ptr @test_returnaddress_0() nounwind { +; CHECK-LABEL: test_returnaddress_0: +; CHECK: or a2, a0, a0 +; CHECK-NEXT: ret + %1 = call ptr @llvm.returnaddress(i32 0) + ret ptr %1 +} From d06b489b906d21b7ffe63d12e6b2d258a89308bc Mon Sep 17 00:00:00 2001 From: Andrei Safronov <safronov@espressif.com> Date: Tue, 10 Sep 2024 00:03:19 +0300 Subject: [PATCH 2/3] [Xtensa] Minor corrections. --- llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 29 +++++++++++-------- .../CodeGen/Xtensa/frameaddr-returnaddr.ll | 26 +++++++++++++---- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp index 97d9c3e9f9f47..1de5e2c1961df 100644 --- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp @@ -596,22 +596,23 @@ SDValue XtensaTargetLowering::LowerSELECT_CC(SDValue Op, SDValue XtensaTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { - // check the depth - // TODO: xtensa-gcc can handle this, by navigating through the stack, we - // should be able to do this too - assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && - "Return address can be determined only for current frame."); + // This nodes represent llvm.returnaddress on the DAG. + // It takes one operand, the index of the return address to return. + // An index of zero corresponds to the current function's return address. + // An index of one to the parent's return address, and so on. + // Depths > 0 not supported yet! + if (Op.getConstantOperandVal(0) > 0) + return SDValue(); MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo &MFI = MF.getFrameInfo(); EVT VT = Op.getValueType(); - unsigned RA = Xtensa::A0; MFI.setReturnAddressIsTaken(true); // Return RA, which contains the return address. Mark it an implicit // live-in. - unsigned Register = MF.addLiveIn(RA, getRegClassFor(MVT::i32)); - return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), Register, VT); + Register RA = MF.addLiveIn(Xtensa::A0, getRegClassFor(MVT::i32)); + return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), RA, VT); } SDValue XtensaTargetLowering::LowerImmediate(SDValue Op, @@ -744,9 +745,13 @@ SDValue XtensaTargetLowering::LowerSTACKRESTORE(SDValue Op, SDValue XtensaTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { - // check the depth - assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && - "Frame address can only be determined for current frame."); + // This nodes represent llvm.frameaddress on the DAG. + // It takes one operand, the index of the frame address to return. + // An index of zero corresponds to the current function's frame address. + // An index of one to the parent's frame address, and so on. + // Depths > 0 not supported yet! + if (Op.getConstantOperandVal(0) > 0) + return SDValue(); MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); @@ -754,7 +759,7 @@ SDValue XtensaTargetLowering::LowerFRAMEADDR(SDValue Op, EVT VT = Op.getValueType(); SDLoc DL(Op); - unsigned FrameRegister = Subtarget.getRegisterInfo()->getFrameRegister(MF); + Register FrameRegister = Subtarget.getRegisterInfo()->getFrameRegister(MF); SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameRegister, VT); return FrameAddr; diff --git a/llvm/test/CodeGen/Xtensa/frameaddr-returnaddr.ll b/llvm/test/CodeGen/Xtensa/frameaddr-returnaddr.ll index 69c22733c107a..e7e5094ac9bc4 100644 --- a/llvm/test/CodeGen/Xtensa/frameaddr-returnaddr.ll +++ b/llvm/test/CodeGen/Xtensa/frameaddr-returnaddr.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 -; RUN: llc -mtriple=xtensa -verify-machineinstrs < %s \ +; RUN: llc -mtriple=xtensa < %s \ ; RUN: | FileCheck %s declare ptr @llvm.frameaddress(i32) @@ -9,14 +9,30 @@ define ptr @test_frameaddress_0() nounwind { ; CHECK-LABEL: test_frameaddress_0: ; CHECK: or a2, a1, a1 ; CHECK-NEXT: ret - %1 = call ptr @llvm.frameaddress(i32 0) - ret ptr %1 + %frameaddr = call ptr @llvm.frameaddress(i32 0) + ret ptr %frameaddr } define ptr @test_returnaddress_0() nounwind { ; CHECK-LABEL: test_returnaddress_0: ; CHECK: or a2, a0, a0 ; CHECK-NEXT: ret - %1 = call ptr @llvm.returnaddress(i32 0) - ret ptr %1 + %retaddr = call ptr @llvm.returnaddress(i32 0) + ret ptr %retaddr +} + +define ptr @test_frameaddress_1() nounwind { +; CHECK-LABEL: test_frameaddress_1: +; CHECK: movi a2, 0 +; CHECK-NEXT: ret + %frameaddr = call ptr @llvm.frameaddress(i32 1) + ret ptr %frameaddr +} + +define ptr @test_returnaddress_1() nounwind { +; CHECK-LABEL: test_returnaddress_1: +; CHECK: movi a2, 0 +; CHECK-NEXT: ret + %retaddr = call ptr @llvm.returnaddress(i32 1) + ret ptr %retaddr } From 0d70d4bedcfd94ba4a1fbd9e9686d8f855fb08b7 Mon Sep 17 00:00:00 2001 From: Andrei Safronov <safronov@espressif.com> Date: Fri, 13 Sep 2024 17:29:49 +0300 Subject: [PATCH 3/3] [Xtensa] Minor fixes in code --- llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp index 1de5e2c1961df..bc1360e212307 100644 --- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp @@ -601,7 +601,7 @@ SDValue XtensaTargetLowering::LowerRETURNADDR(SDValue Op, // An index of zero corresponds to the current function's return address. // An index of one to the parent's return address, and so on. // Depths > 0 not supported yet! - if (Op.getConstantOperandVal(0) > 0) + if (Op.getConstantOperandVal(0) != 0) return SDValue(); MachineFunction &MF = DAG.getMachineFunction(); @@ -750,11 +750,11 @@ SDValue XtensaTargetLowering::LowerFRAMEADDR(SDValue Op, // An index of zero corresponds to the current function's frame address. // An index of one to the parent's frame address, and so on. // Depths > 0 not supported yet! - if (Op.getConstantOperandVal(0) > 0) + if (Op.getConstantOperandVal(0) != 0) return SDValue(); MachineFunction &MF = DAG.getMachineFunction(); - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); + MachineFrameInfo &MFI = MF.getFrameInfo(); MFI.setFrameAddressIsTaken(true); EVT VT = Op.getValueType(); SDLoc DL(Op);