@@ -945,6 +945,54 @@ define i32 @caller_small_struct_ret() nounwind {
945
945
ret i32 %5
946
946
}
947
947
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
+
948
996
; Check return of >2x xlen structs
949
997
950
998
%struct.large = type { i32 , i32 , i32 , i32 }
@@ -1033,3 +1081,106 @@ define i32 @caller_large_struct_ret() nounwind {
1033
1081
%5 = add i32 %2 , %4
1034
1082
ret i32 %5
1035
1083
}
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