@@ -1018,14 +1018,22 @@ fn generic_simd_intrinsic<'a, 'tcx>(
1018
1018
name, $( $fmt) * ) ) ;
1019
1019
}
1020
1020
}
1021
- macro_rules! require {
1022
- ( $cond : expr , $ ( $fmt: tt) * ) => {
1023
- if !$cond {
1021
+ macro_rules! return_error {
1022
+ ( $( $fmt: tt) * ) => {
1023
+ {
1024
1024
emit_error!( $( $fmt) * ) ;
1025
1025
return Err ( ( ) ) ;
1026
1026
}
1027
1027
}
1028
1028
}
1029
+
1030
+ macro_rules! require {
1031
+ ( $cond: expr, $( $fmt: tt) * ) => {
1032
+ if !$cond {
1033
+ return_error!( $( $fmt) * ) ;
1034
+ }
1035
+ } ;
1036
+ }
1029
1037
macro_rules! require_simd {
1030
1038
( $ty: expr, $position: expr) => {
1031
1039
require!( $ty. is_simd( ) , "expected SIMD {} type, found non-SIMD `{}`" , $position, $ty)
@@ -1142,6 +1150,211 @@ fn generic_simd_intrinsic<'a, 'tcx>(
1142
1150
return Ok ( bx. extract_element ( args[ 0 ] . immediate ( ) , args[ 1 ] . immediate ( ) ) )
1143
1151
}
1144
1152
1153
+ if name == "simd_reduce_add" {
1154
+ require ! ( ret_ty == in_elem,
1155
+ "expected return type `{}` (element of input `{}`), found `{}`" ,
1156
+ in_elem, in_ty, ret_ty) ;
1157
+ return match in_elem. sty {
1158
+ ty:: TyInt ( _i) => {
1159
+ Ok ( bx. vector_reduce_add ( args[ 0 ] . immediate ( ) ) )
1160
+ } ,
1161
+ ty:: TyUint ( _u) => {
1162
+ Ok ( bx. vector_reduce_add ( args[ 0 ] . immediate ( ) ) )
1163
+ } ,
1164
+ ty:: TyFloat ( f) => {
1165
+ // undef as accumulator makes the reduction unordered:
1166
+ let acc = match f. bit_width ( ) {
1167
+ 32 => C_undef ( Type :: f32 ( bx. cx ) ) ,
1168
+ 64 => C_undef ( Type :: f64 ( bx. cx ) ) ,
1169
+ v => {
1170
+ return_error ! (
1171
+ "unsupported {} from `{}` with element `{}` of size `{}` to `{}`" ,
1172
+ "simd_reduce_add" , in_ty, in_elem, v, ret_ty)
1173
+ }
1174
+ } ;
1175
+ Ok ( bx. vector_reduce_fadd_fast ( acc, args[ 0 ] . immediate ( ) ) )
1176
+ }
1177
+ _ => {
1178
+ return_error ! ( "unsupported {} from `{}` with element `{}` to `{}`" ,
1179
+ "simd_reduce_add" , in_ty, in_elem, ret_ty)
1180
+ } ,
1181
+ }
1182
+ }
1183
+
1184
+ if name == "simd_reduce_mul" {
1185
+ require ! ( ret_ty == in_elem,
1186
+ "expected return type `{}` (element of input `{}`), found `{}`" ,
1187
+ in_elem, in_ty, ret_ty) ;
1188
+ return match in_elem. sty {
1189
+ ty:: TyInt ( _i) => {
1190
+ Ok ( bx. vector_reduce_mul ( args[ 0 ] . immediate ( ) ) )
1191
+ } ,
1192
+ ty:: TyUint ( _u) => {
1193
+ Ok ( bx. vector_reduce_mul ( args[ 0 ] . immediate ( ) ) )
1194
+ } ,
1195
+ ty:: TyFloat ( f) => {
1196
+ // undef as accumulator makes the reduction unordered:
1197
+ let acc = match f. bit_width ( ) {
1198
+ 32 => C_undef ( Type :: f32 ( bx. cx ) ) ,
1199
+ 64 => C_undef ( Type :: f64 ( bx. cx ) ) ,
1200
+ v => {
1201
+ return_error ! (
1202
+ "unsupported {} from `{}` with element `{}` of size `{}` to `{}`" ,
1203
+ "simd_reduce_mul" , in_ty, in_elem, v, ret_ty)
1204
+ }
1205
+ } ;
1206
+ Ok ( bx. vector_reduce_fmul_fast ( acc, args[ 0 ] . immediate ( ) ) )
1207
+ }
1208
+ _ => {
1209
+ return_error ! ( "unsupported {} from `{}` with element `{}` to `{}`" ,
1210
+ "simd_reduce_mul" , in_ty, in_elem, ret_ty)
1211
+ } ,
1212
+ }
1213
+ }
1214
+
1215
+ if name == "simd_reduce_min" {
1216
+ require ! ( ret_ty == in_elem,
1217
+ "expected return type `{}` (element of input `{}`), found `{}`" ,
1218
+ in_elem, in_ty, ret_ty) ;
1219
+ return match in_elem. sty {
1220
+ ty:: TyInt ( _i) => {
1221
+ Ok ( bx. vector_reduce_min ( args[ 0 ] . immediate ( ) , true ) )
1222
+ } ,
1223
+ ty:: TyUint ( _u) => {
1224
+ Ok ( bx. vector_reduce_min ( args[ 0 ] . immediate ( ) , false ) )
1225
+ } ,
1226
+ ty:: TyFloat ( _f) => {
1227
+ Ok ( bx. vector_reduce_fmin_fast ( args[ 0 ] . immediate ( ) ) )
1228
+ }
1229
+ _ => {
1230
+ return_error ! ( "unsupported {} from `{}` with element `{}` to `{}`" ,
1231
+ "simd_reduce_min" , in_ty, in_elem, ret_ty)
1232
+ } ,
1233
+ }
1234
+ }
1235
+
1236
+ if name == "simd_reduce_max" {
1237
+ require ! ( ret_ty == in_elem,
1238
+ "expected return type `{}` (element of input `{}`), found `{}`" ,
1239
+ in_elem, in_ty, ret_ty) ;
1240
+ return match in_elem. sty {
1241
+ ty:: TyInt ( _i) => {
1242
+ Ok ( bx. vector_reduce_max ( args[ 0 ] . immediate ( ) , true ) )
1243
+ } ,
1244
+ ty:: TyUint ( _u) => {
1245
+ Ok ( bx. vector_reduce_max ( args[ 0 ] . immediate ( ) , false ) )
1246
+ } ,
1247
+ ty:: TyFloat ( _f) => {
1248
+ Ok ( bx. vector_reduce_fmax_fast ( args[ 0 ] . immediate ( ) ) )
1249
+ }
1250
+ _ => {
1251
+ return_error ! ( "unsupported {} from `{}` with element `{}` to `{}`" ,
1252
+ "simd_reduce_max" , in_ty, in_elem, ret_ty)
1253
+ } ,
1254
+ }
1255
+ }
1256
+
1257
+ if name == "simd_reduce_and" {
1258
+ require ! ( ret_ty == in_elem,
1259
+ "expected return type `{}` (element of input `{}`), found `{}`" ,
1260
+ in_elem, in_ty, ret_ty) ;
1261
+ return match in_elem. sty {
1262
+ ty:: TyInt ( _i) => {
1263
+ Ok ( bx. vector_reduce_and ( args[ 0 ] . immediate ( ) ) )
1264
+ } ,
1265
+ ty:: TyUint ( _u) => {
1266
+ Ok ( bx. vector_reduce_and ( args[ 0 ] . immediate ( ) ) )
1267
+ } ,
1268
+ _ => {
1269
+ return_error ! ( "unsupported {} from `{}` with element `{}` to `{}`" ,
1270
+ "simd_reduce_and" , in_ty, in_elem, ret_ty)
1271
+ } ,
1272
+ }
1273
+ }
1274
+
1275
+ if name == "simd_reduce_or" {
1276
+ require ! ( ret_ty == in_elem,
1277
+ "expected return type `{}` (element of input `{}`), found `{}`" ,
1278
+ in_elem, in_ty, ret_ty) ;
1279
+ return match in_elem. sty {
1280
+ ty:: TyInt ( _i) => {
1281
+ Ok ( bx. vector_reduce_or ( args[ 0 ] . immediate ( ) ) )
1282
+ } ,
1283
+ ty:: TyUint ( _u) => {
1284
+ Ok ( bx. vector_reduce_or ( args[ 0 ] . immediate ( ) ) )
1285
+ } ,
1286
+ _ => {
1287
+ return_error ! ( "unsupported {} from `{}` with element `{}` to `{}`" ,
1288
+ "simd_reduce_or" , in_ty, in_elem, ret_ty)
1289
+ } ,
1290
+ }
1291
+ }
1292
+
1293
+ if name == "simd_reduce_xor" {
1294
+ require ! ( ret_ty == in_elem,
1295
+ "expected return type `{}` (element of input `{}`), found `{}`" ,
1296
+ in_elem, in_ty, ret_ty) ;
1297
+ return match in_elem. sty {
1298
+ ty:: TyInt ( _i) => {
1299
+ Ok ( bx. vector_reduce_xor ( args[ 0 ] . immediate ( ) ) )
1300
+ } ,
1301
+ ty:: TyUint ( _u) => {
1302
+ Ok ( bx. vector_reduce_xor ( args[ 0 ] . immediate ( ) ) )
1303
+ } ,
1304
+ _ => {
1305
+ return_error ! ( "unsupported {} from `{}` with element `{}` to `{}`" ,
1306
+ "simd_reduce_xor" , in_ty, in_elem, ret_ty)
1307
+ } ,
1308
+ }
1309
+ }
1310
+
1311
+ if name == "simd_reduce_all" {
1312
+ //require!(ret_ty == in_elem,
1313
+ // "expected return type `{}` (element of input `{}`), found `{}`",
1314
+ // in_elem, in_ty, ret_ty);
1315
+ let i1 = Type :: i1 ( bx. cx ) ;
1316
+ let i1xn = Type :: vector ( & i1, in_len as u64 ) ;
1317
+ let v = bx. trunc ( args[ 0 ] . immediate ( ) , i1xn) ;
1318
+
1319
+ let red = match in_elem. sty {
1320
+ ty:: TyInt ( _i) => {
1321
+ bx. vector_reduce_and ( v)
1322
+ } ,
1323
+ ty:: TyUint ( _u) => {
1324
+ bx. vector_reduce_and ( v)
1325
+ } ,
1326
+ _ => {
1327
+ return_error ! ( "unsupported {} from `{}` with element `{}` to `{}`" ,
1328
+ "simd_reduce_and" , in_ty, in_elem, ret_ty)
1329
+ } ,
1330
+ } ;
1331
+ return Ok ( bx. zext ( red, Type :: bool ( bx. cx ) ) ) ;
1332
+ }
1333
+
1334
+ if name == "simd_reduce_any" {
1335
+ //require!(ret_ty == in_elem,
1336
+ // "expected return type `{}` (element of input `{}`), found `{}`",
1337
+ // in_elem, in_ty, ret_ty);
1338
+ let i1 = Type :: i1 ( bx. cx ) ;
1339
+ let i1xn = Type :: vector ( & i1, in_len as u64 ) ;
1340
+ let v = bx. trunc ( args[ 0 ] . immediate ( ) , i1xn) ;
1341
+
1342
+ let red = match in_elem. sty {
1343
+ ty:: TyInt ( _i) => {
1344
+ bx. vector_reduce_or ( v)
1345
+ } ,
1346
+ ty:: TyUint ( _u) => {
1347
+ bx. vector_reduce_or ( v)
1348
+ } ,
1349
+ _ => {
1350
+ return_error ! ( "unsupported {} from `{}` with element `{}` to `{}`" ,
1351
+ "simd_reduce_and" , in_ty, in_elem, ret_ty)
1352
+ } ,
1353
+ } ;
1354
+ return Ok ( bx. zext ( red, Type :: bool ( bx. cx ) ) ) ;
1355
+ }
1356
+
1357
+
1145
1358
if name == "simd_cast" {
1146
1359
require_simd ! ( ret_ty, "return" ) ;
1147
1360
let out_len = ret_ty. simd_size ( tcx) ;
0 commit comments