diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index b55a73253c7..6779a5a8cd2 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1042,6 +1042,9 @@ bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) { case ISD::ADDCARRY: case ISD::SUBCARRY: Res = PromoteIntOp_ADDSUBCARRY(N, OpNo); break; + + case ISD::FRAMEADDR: + case ISD::RETURNADDR: Res = PromoteIntOp_FRAMERETURNADDR(N); break; } // If the result is null, the sub-method took care of registering results etc. @@ -1401,6 +1404,12 @@ SDValue DAGTypeLegalizer::PromoteIntOp_ADDSUBCARRY(SDNode *N, unsigned OpNo) { return SDValue(DAG.UpdateNodeOperands(N, LHS, RHS, Carry), 0); } +SDValue DAGTypeLegalizer::PromoteIntOp_FRAMERETURNADDR(SDNode *N) { + // Promote the RETURNADDR/FRAMEADDR argument to a supported integer width. + SDValue Op = ZExtPromotedInteger(N->getOperand(0)); + return SDValue(DAG.UpdateNodeOperands(N, Op), 0); +} + //===----------------------------------------------------------------------===// // Integer Result Expansion //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 5bb5995e35c..903573956f9 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -375,6 +375,7 @@ private: SDValue PromoteIntOp_MSCATTER(MaskedScatterSDNode *N, unsigned OpNo); SDValue PromoteIntOp_MGATHER(MaskedGatherSDNode *N, unsigned OpNo); SDValue PromoteIntOp_ADDSUBCARRY(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_FRAMERETURNADDR(SDNode *N); void PromoteSetCCOperands(SDValue &LHS,SDValue &RHS, ISD::CondCode Code); diff --git a/test/CodeGen/RISCV/frameaddr-returnaddr.ll b/test/CodeGen/RISCV/frameaddr-returnaddr.ll index 967f2246e56..255bf715539 100644 --- a/test/CodeGen/RISCV/frameaddr-returnaddr.ll +++ b/test/CodeGen/RISCV/frameaddr-returnaddr.ll @@ -1,6 +1,8 @@ ; 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 +; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64I %s declare void @notdead(i8*) declare i8* @llvm.frameaddress(i32) @@ -18,6 +20,18 @@ define i8* @test_frameaddress_0() nounwind { ; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: addi sp, sp, 16 ; RV32I-NEXT: ret +; +; RV64I-LABEL: test_frameaddress_0: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: sd s0, 0(sp) +; RV64I-NEXT: addi s0, sp, 16 +; RV64I-NEXT: mv a0, s0 +; RV64I-NEXT: ld s0, 0(sp) +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret %1 = call i8* @llvm.frameaddress(i32 0) ret i8* %1 } @@ -35,6 +49,19 @@ define i8* @test_frameaddress_2() nounwind { ; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: addi sp, sp, 16 ; RV32I-NEXT: ret +; +; RV64I-LABEL: test_frameaddress_2: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: sd s0, 0(sp) +; RV64I-NEXT: addi s0, sp, 16 +; RV64I-NEXT: ld a0, -16(s0) +; RV64I-NEXT: ld a0, -16(a0) +; RV64I-NEXT: ld s0, 0(sp) +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret %1 = call i8* @llvm.frameaddress(i32 2) ret i8* %1 } @@ -55,6 +82,22 @@ define i8* @test_frameaddress_3_alloca() nounwind { ; RV32I-NEXT: lw ra, 108(sp) ; RV32I-NEXT: addi sp, sp, 112 ; RV32I-NEXT: ret +; +; RV64I-LABEL: test_frameaddress_3_alloca: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -128 +; RV64I-NEXT: sd ra, 120(sp) +; RV64I-NEXT: sd s0, 112(sp) +; RV64I-NEXT: addi s0, sp, 128 +; RV64I-NEXT: addi a0, s0, -116 +; RV64I-NEXT: call notdead +; RV64I-NEXT: ld a0, -16(s0) +; RV64I-NEXT: ld a0, -16(a0) +; RV64I-NEXT: ld a0, -16(a0) +; RV64I-NEXT: ld s0, 112(sp) +; RV64I-NEXT: ld ra, 120(sp) +; RV64I-NEXT: addi sp, sp, 128 +; RV64I-NEXT: ret %1 = alloca [100 x i8] %2 = bitcast [100 x i8]* %1 to i8* call void @notdead(i8* %2) @@ -67,6 +110,11 @@ define i8* @test_returnaddress_0() nounwind { ; RV32I: # %bb.0: ; RV32I-NEXT: mv a0, ra ; RV32I-NEXT: ret +; +; RV64I-LABEL: test_returnaddress_0: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a0, ra +; RV64I-NEXT: ret %1 = call i8* @llvm.returnaddress(i32 0) ret i8* %1 } @@ -85,6 +133,20 @@ define i8* @test_returnaddress_2() nounwind { ; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: addi sp, sp, 16 ; RV32I-NEXT: ret +; +; RV64I-LABEL: test_returnaddress_2: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: sd s0, 0(sp) +; RV64I-NEXT: addi s0, sp, 16 +; RV64I-NEXT: ld a0, -16(s0) +; RV64I-NEXT: ld a0, -16(a0) +; RV64I-NEXT: ld a0, -8(a0) +; RV64I-NEXT: ld s0, 0(sp) +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret %1 = call i8* @llvm.returnaddress(i32 2) ret i8* %1 }