@@ -945,6 +945,54 @@ define i32 @caller_small_struct_ret() nounwind {
945945 ret i32 %5
946946}
947947
948+ ; Check return of >2x xlen scalars
949+
950+ define fp128 @callee_large_scalar_ret () nounwind {
951+ ; RV32I-LABEL: name: callee_large_scalar_ret
952+ ; RV32I: bb.1 (%ir-block.0):
953+ ; RV32I-NEXT: liveins: $x10
954+ ; RV32I-NEXT: {{ $}}
955+ ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10
956+ ; RV32I-NEXT: [[C:%[0-9]+]]:_(s128) = G_FCONSTANT fp128 0xL00000000000000007FFF000000000000
957+ ; RV32I-NEXT: G_STORE [[C]](s128), [[COPY]](p0) :: (store (s128))
958+ ; RV32I-NEXT: PseudoRET
959+ ret fp128 0xL00000000000000007FFF000000000000
960+ }
961+
962+ define void @caller_large_scalar_ret () nounwind {
963+ ; ILP32-LABEL: name: caller_large_scalar_ret
964+ ; ILP32: bb.1 (%ir-block.0):
965+ ; ILP32-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
966+ ; ILP32-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
967+ ; ILP32-NEXT: $x10 = COPY [[FRAME_INDEX]](p0)
968+ ; ILP32-NEXT: PseudoCALL target-flags(riscv-call) @callee_large_scalar_ret, csr_ilp32_lp64, implicit-def $x1, implicit $x10
969+ ; ILP32-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
970+ ; ILP32-NEXT: [[LOAD:%[0-9]+]]:_(s128) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s128) from %stack.0)
971+ ; ILP32-NEXT: PseudoRET
972+ ;
973+ ; ILP32F-LABEL: name: caller_large_scalar_ret
974+ ; ILP32F: bb.1 (%ir-block.0):
975+ ; ILP32F-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
976+ ; ILP32F-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
977+ ; ILP32F-NEXT: $x10 = COPY [[FRAME_INDEX]](p0)
978+ ; ILP32F-NEXT: PseudoCALL target-flags(riscv-call) @callee_large_scalar_ret, csr_ilp32f_lp64f, implicit-def $x1, implicit $x10
979+ ; ILP32F-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
980+ ; ILP32F-NEXT: [[LOAD:%[0-9]+]]:_(s128) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s128) from %stack.0)
981+ ; ILP32F-NEXT: PseudoRET
982+ ;
983+ ; ILP32D-LABEL: name: caller_large_scalar_ret
984+ ; ILP32D: bb.1 (%ir-block.0):
985+ ; ILP32D-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
986+ ; ILP32D-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
987+ ; ILP32D-NEXT: $x10 = COPY [[FRAME_INDEX]](p0)
988+ ; ILP32D-NEXT: PseudoCALL target-flags(riscv-call) @callee_large_scalar_ret, csr_ilp32d_lp64d, implicit-def $x1, implicit $x10
989+ ; ILP32D-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
990+ ; ILP32D-NEXT: [[LOAD:%[0-9]+]]:_(s128) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s128) from %stack.0)
991+ ; ILP32D-NEXT: PseudoRET
992+ %1 = call fp128 @callee_large_scalar_ret ()
993+ ret void
994+ }
995+
948996; Check return of >2x xlen structs
949997
950998%struct.large = type { i32 , i32 , i32 , i32 }
@@ -1033,3 +1081,106 @@ define i32 @caller_large_struct_ret() nounwind {
10331081 %5 = add i32 %2 , %4
10341082 ret i32 %5
10351083}
1084+
1085+ %struct.large2 = type { i32 , float , i16 , i32 }
1086+
1087+ define %struct.large2 @callee_large_struct_ret2 () nounwind {
1088+ ; RV32I-LABEL: name: callee_large_struct_ret2
1089+ ; RV32I: bb.1 (%ir-block.0):
1090+ ; RV32I-NEXT: liveins: $x10
1091+ ; RV32I-NEXT: {{ $}}
1092+ ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10
1093+ ; RV32I-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
1094+ ; RV32I-NEXT: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
1095+ ; RV32I-NEXT: [[DEF2:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
1096+ ; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
1097+ ; RV32I-NEXT: [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00
1098+ ; RV32I-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 3
1099+ ; RV32I-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
1100+ ; RV32I-NEXT: G_STORE [[C]](s32), [[COPY]](p0) :: (store (s32), align 8)
1101+ ; RV32I-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
1102+ ; RV32I-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C4]](s32)
1103+ ; RV32I-NEXT: G_STORE [[C1]](s32), [[PTR_ADD]](p0) :: (store (s32))
1104+ ; RV32I-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
1105+ ; RV32I-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C5]](s32)
1106+ ; RV32I-NEXT: G_STORE [[C2]](s16), [[PTR_ADD1]](p0) :: (store (s16), align 8)
1107+ ; RV32I-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 12
1108+ ; RV32I-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C6]](s32)
1109+ ; RV32I-NEXT: G_STORE [[C3]](s32), [[PTR_ADD2]](p0) :: (store (s32))
1110+ ; RV32I-NEXT: PseudoRET
1111+ %a = insertvalue %struct.large2 poison, i32 1 , 0
1112+ %b = insertvalue %struct.large2 %a , float 2 .0 , 1
1113+ %c = insertvalue %struct.large2 %b , i16 3 , 2
1114+ %d = insertvalue %struct.large2 %c , i32 4 , 3
1115+ ret %struct.large2 %d
1116+ }
1117+
1118+ define i32 @caller_large_struct_ret2 () nounwind {
1119+ ; ILP32-LABEL: name: caller_large_struct_ret2
1120+ ; ILP32: bb.1 (%ir-block.0):
1121+ ; ILP32-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
1122+ ; ILP32-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
1123+ ; ILP32-NEXT: $x10 = COPY [[FRAME_INDEX]](p0)
1124+ ; ILP32-NEXT: PseudoCALL target-flags(riscv-call) @callee_large_struct_ret, csr_ilp32_lp64, implicit-def $x1, implicit $x10
1125+ ; ILP32-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
1126+ ; ILP32-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %stack.0, align 8)
1127+ ; ILP32-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
1128+ ; ILP32-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[FRAME_INDEX]], [[C]](s32)
1129+ ; ILP32-NEXT: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD]](p0) :: (load (s32) from %stack.0)
1130+ ; ILP32-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
1131+ ; ILP32-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[FRAME_INDEX]], [[C1]](s32)
1132+ ; ILP32-NEXT: [[LOAD2:%[0-9]+]]:_(s16) = G_LOAD [[PTR_ADD1]](p0) :: (load (s16) from %stack.0, align 8)
1133+ ; ILP32-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 12
1134+ ; ILP32-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD [[FRAME_INDEX]], [[C2]](s32)
1135+ ; ILP32-NEXT: [[LOAD3:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD2]](p0) :: (load (s32) from %stack.0)
1136+ ; ILP32-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[LOAD]], [[LOAD3]]
1137+ ; ILP32-NEXT: $x10 = COPY [[ADD]](s32)
1138+ ; ILP32-NEXT: PseudoRET implicit $x10
1139+ ;
1140+ ; ILP32F-LABEL: name: caller_large_struct_ret2
1141+ ; ILP32F: bb.1 (%ir-block.0):
1142+ ; ILP32F-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
1143+ ; ILP32F-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
1144+ ; ILP32F-NEXT: $x10 = COPY [[FRAME_INDEX]](p0)
1145+ ; ILP32F-NEXT: PseudoCALL target-flags(riscv-call) @callee_large_struct_ret, csr_ilp32f_lp64f, implicit-def $x1, implicit $x10
1146+ ; ILP32F-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
1147+ ; ILP32F-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %stack.0, align 8)
1148+ ; ILP32F-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
1149+ ; ILP32F-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[FRAME_INDEX]], [[C]](s32)
1150+ ; ILP32F-NEXT: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD]](p0) :: (load (s32) from %stack.0)
1151+ ; ILP32F-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
1152+ ; ILP32F-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[FRAME_INDEX]], [[C1]](s32)
1153+ ; ILP32F-NEXT: [[LOAD2:%[0-9]+]]:_(s16) = G_LOAD [[PTR_ADD1]](p0) :: (load (s16) from %stack.0, align 8)
1154+ ; ILP32F-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 12
1155+ ; ILP32F-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD [[FRAME_INDEX]], [[C2]](s32)
1156+ ; ILP32F-NEXT: [[LOAD3:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD2]](p0) :: (load (s32) from %stack.0)
1157+ ; ILP32F-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[LOAD]], [[LOAD3]]
1158+ ; ILP32F-NEXT: $x10 = COPY [[ADD]](s32)
1159+ ; ILP32F-NEXT: PseudoRET implicit $x10
1160+ ;
1161+ ; ILP32D-LABEL: name: caller_large_struct_ret2
1162+ ; ILP32D: bb.1 (%ir-block.0):
1163+ ; ILP32D-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
1164+ ; ILP32D-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
1165+ ; ILP32D-NEXT: $x10 = COPY [[FRAME_INDEX]](p0)
1166+ ; ILP32D-NEXT: PseudoCALL target-flags(riscv-call) @callee_large_struct_ret, csr_ilp32d_lp64d, implicit-def $x1, implicit $x10
1167+ ; ILP32D-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
1168+ ; ILP32D-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %stack.0, align 8)
1169+ ; ILP32D-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
1170+ ; ILP32D-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[FRAME_INDEX]], [[C]](s32)
1171+ ; ILP32D-NEXT: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD]](p0) :: (load (s32) from %stack.0)
1172+ ; ILP32D-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
1173+ ; ILP32D-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[FRAME_INDEX]], [[C1]](s32)
1174+ ; ILP32D-NEXT: [[LOAD2:%[0-9]+]]:_(s16) = G_LOAD [[PTR_ADD1]](p0) :: (load (s16) from %stack.0, align 8)
1175+ ; ILP32D-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 12
1176+ ; ILP32D-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD [[FRAME_INDEX]], [[C2]](s32)
1177+ ; ILP32D-NEXT: [[LOAD3:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD2]](p0) :: (load (s32) from %stack.0)
1178+ ; ILP32D-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[LOAD]], [[LOAD3]]
1179+ ; ILP32D-NEXT: $x10 = COPY [[ADD]](s32)
1180+ ; ILP32D-NEXT: PseudoRET implicit $x10
1181+ %1 = call %struct.large2 @callee_large_struct_ret ()
1182+ %2 = extractvalue %struct.large2 %1 , 0
1183+ %3 = extractvalue %struct.large2 %1 , 3
1184+ %4 = add i32 %2 , %3
1185+ ret i32 %4
1186+ }
0 commit comments