@@ -1018,14 +1018,22 @@ fn generic_simd_intrinsic<'a, 'tcx>(
10181018 name, $( $fmt) * ) ) ;
10191019 }
10201020 }
1021- macro_rules! require {
1022- ( $cond : expr , $ ( $fmt: tt) * ) => {
1023- if !$cond {
1021+ macro_rules! return_error {
1022+ ( $( $fmt: tt) * ) => {
1023+ {
10241024 emit_error!( $( $fmt) * ) ;
10251025 return Err ( ( ) ) ;
10261026 }
10271027 }
10281028 }
1029+
1030+ macro_rules! require {
1031+ ( $cond: expr, $( $fmt: tt) * ) => {
1032+ if !$cond {
1033+ return_error!( $( $fmt) * ) ;
1034+ }
1035+ } ;
1036+ }
10291037 macro_rules! require_simd {
10301038 ( $ty: expr, $position: expr) => {
10311039 require!( $ty. is_simd( ) , "expected SIMD {} type, found non-SIMD `{}`" , $position, $ty)
@@ -1142,6 +1150,211 @@ fn generic_simd_intrinsic<'a, 'tcx>(
11421150 return Ok ( bx. extract_element ( args[ 0 ] . immediate ( ) , args[ 1 ] . immediate ( ) ) )
11431151 }
11441152
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+
11451358 if name == "simd_cast" {
11461359 require_simd ! ( ret_ty, "return" ) ;
11471360 let out_len = ret_ty. simd_size ( tcx) ;
0 commit comments