@@ -1492,6 +1492,198 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
14921492 return Ok ( v) ;
14931493 }
14941494
1495+ if name == sym:: simd_masked_load {
1496+ // simd_masked_load(mask: <N x i{M}>, pointer: *_ T, values: <N x T>) -> <N x T>
1497+ // * N: number of elements in the input vectors
1498+ // * T: type of the element to load
1499+ // * M: any integer width is supported, will be truncated to i1
1500+ // Loads contiguous elements from memory behind `pointer`, but only for
1501+ // those lanes whose `mask` bit is enabled.
1502+ // The memory addresses corresponding to the “off” lanes are not accessed.
1503+
1504+ // The element type of the "mask" argument must be a signed integer type of any width
1505+ let mask_ty = in_ty;
1506+ let ( mask_len, mask_elem) = ( in_len, in_elem) ;
1507+
1508+ // The second argument must be a pointer matching the element type
1509+ let pointer_ty = arg_tys[ 1 ] ;
1510+
1511+ // The last argument is a passthrough vector providing values for disabled lanes
1512+ let values_ty = arg_tys[ 2 ] ;
1513+ let ( values_len, values_elem) = require_simd ! ( values_ty, SimdThird ) ;
1514+
1515+ require_simd ! ( ret_ty, SimdReturn ) ;
1516+
1517+ // Of the same length:
1518+ require ! (
1519+ values_len == mask_len,
1520+ InvalidMonomorphization :: ThirdArgumentLength {
1521+ span,
1522+ name,
1523+ in_len: mask_len,
1524+ in_ty: mask_ty,
1525+ arg_ty: values_ty,
1526+ out_len: values_len
1527+ }
1528+ ) ;
1529+
1530+ // The return type must match the last argument type
1531+ require ! (
1532+ ret_ty == values_ty,
1533+ InvalidMonomorphization :: ExpectedReturnType { span, name, in_ty: values_ty, ret_ty }
1534+ ) ;
1535+
1536+ require ! (
1537+ matches!(
1538+ pointer_ty. kind( ) ,
1539+ ty:: RawPtr ( p) if p. ty == values_elem && p. ty. kind( ) == values_elem. kind( )
1540+ ) ,
1541+ InvalidMonomorphization :: ExpectedElementType {
1542+ span,
1543+ name,
1544+ expected_element: values_elem,
1545+ second_arg: pointer_ty,
1546+ in_elem: values_elem,
1547+ in_ty: values_ty,
1548+ mutability: ExpectedPointerMutability :: Not ,
1549+ }
1550+ ) ;
1551+
1552+ require ! (
1553+ matches!( mask_elem. kind( ) , ty:: Int ( _) ) ,
1554+ InvalidMonomorphization :: ThirdArgElementType {
1555+ span,
1556+ name,
1557+ expected_element: values_elem,
1558+ third_arg: mask_ty,
1559+ }
1560+ ) ;
1561+
1562+ // Alignment of T, must be a constant integer value:
1563+ let alignment_ty = bx. type_i32 ( ) ;
1564+ let alignment = bx. const_i32 ( bx. align_of ( values_ty) . bytes ( ) as i32 ) ;
1565+
1566+ // Truncate the mask vector to a vector of i1s:
1567+ let ( mask, mask_ty) = {
1568+ let i1 = bx. type_i1 ( ) ;
1569+ let i1xn = bx. type_vector ( i1, mask_len) ;
1570+ ( bx. trunc ( args[ 0 ] . immediate ( ) , i1xn) , i1xn)
1571+ } ;
1572+
1573+ let llvm_pointer = bx. type_ptr ( ) ;
1574+
1575+ // Type of the vector of elements:
1576+ let llvm_elem_vec_ty = llvm_vector_ty ( bx, values_elem, values_len) ;
1577+ let llvm_elem_vec_str = llvm_vector_str ( bx, values_elem, values_len) ;
1578+
1579+ let llvm_intrinsic = format ! ( "llvm.masked.load.{llvm_elem_vec_str}.p0" ) ;
1580+ let fn_ty = bx
1581+ . type_func ( & [ llvm_pointer, alignment_ty, mask_ty, llvm_elem_vec_ty] , llvm_elem_vec_ty) ;
1582+ let f = bx. declare_cfn ( & llvm_intrinsic, llvm:: UnnamedAddr :: No , fn_ty) ;
1583+ let v = bx. call (
1584+ fn_ty,
1585+ None ,
1586+ None ,
1587+ f,
1588+ & [ args[ 1 ] . immediate ( ) , alignment, mask, args[ 2 ] . immediate ( ) ] ,
1589+ None ,
1590+ ) ;
1591+ return Ok ( v) ;
1592+ }
1593+
1594+ if name == sym:: simd_masked_store {
1595+ // simd_masked_store(mask: <N x i{M}>, pointer: *mut T, values: <N x T>) -> ()
1596+ // * N: number of elements in the input vectors
1597+ // * T: type of the element to load
1598+ // * M: any integer width is supported, will be truncated to i1
1599+ // Stores contiguous elements to memory behind `pointer`, but only for
1600+ // those lanes whose `mask` bit is enabled.
1601+ // The memory addresses corresponding to the “off” lanes are not accessed.
1602+
1603+ // The element type of the "mask" argument must be a signed integer type of any width
1604+ let mask_ty = in_ty;
1605+ let ( mask_len, mask_elem) = ( in_len, in_elem) ;
1606+
1607+ // The second argument must be a pointer matching the element type
1608+ let pointer_ty = arg_tys[ 1 ] ;
1609+
1610+ // The last argument specifies the values to store to memory
1611+ let values_ty = arg_tys[ 2 ] ;
1612+ let ( values_len, values_elem) = require_simd ! ( values_ty, SimdThird ) ;
1613+
1614+ // Of the same length:
1615+ require ! (
1616+ values_len == mask_len,
1617+ InvalidMonomorphization :: ThirdArgumentLength {
1618+ span,
1619+ name,
1620+ in_len: mask_len,
1621+ in_ty: mask_ty,
1622+ arg_ty: values_ty,
1623+ out_len: values_len
1624+ }
1625+ ) ;
1626+
1627+ // The second argument must be a mutable pointer type matching the element type
1628+ require ! (
1629+ matches!(
1630+ pointer_ty. kind( ) ,
1631+ ty:: RawPtr ( p) if p. ty == values_elem && p. ty. kind( ) == values_elem. kind( ) && p. mutbl. is_mut( )
1632+ ) ,
1633+ InvalidMonomorphization :: ExpectedElementType {
1634+ span,
1635+ name,
1636+ expected_element: values_elem,
1637+ second_arg: pointer_ty,
1638+ in_elem: values_elem,
1639+ in_ty: values_ty,
1640+ mutability: ExpectedPointerMutability :: Mut ,
1641+ }
1642+ ) ;
1643+
1644+ require ! (
1645+ matches!( mask_elem. kind( ) , ty:: Int ( _) ) ,
1646+ InvalidMonomorphization :: ThirdArgElementType {
1647+ span,
1648+ name,
1649+ expected_element: values_elem,
1650+ third_arg: mask_ty,
1651+ }
1652+ ) ;
1653+
1654+ // Alignment of T, must be a constant integer value:
1655+ let alignment_ty = bx. type_i32 ( ) ;
1656+ let alignment = bx. const_i32 ( bx. align_of ( values_elem) . bytes ( ) as i32 ) ;
1657+
1658+ // Truncate the mask vector to a vector of i1s:
1659+ let ( mask, mask_ty) = {
1660+ let i1 = bx. type_i1 ( ) ;
1661+ let i1xn = bx. type_vector ( i1, in_len) ;
1662+ ( bx. trunc ( args[ 0 ] . immediate ( ) , i1xn) , i1xn)
1663+ } ;
1664+
1665+ let ret_t = bx. type_void ( ) ;
1666+
1667+ let llvm_pointer = bx. type_ptr ( ) ;
1668+
1669+ // Type of the vector of elements:
1670+ let llvm_elem_vec_ty = llvm_vector_ty ( bx, values_elem, values_len) ;
1671+ let llvm_elem_vec_str = llvm_vector_str ( bx, values_elem, values_len) ;
1672+
1673+ let llvm_intrinsic = format ! ( "llvm.masked.store.{llvm_elem_vec_str}.p0" ) ;
1674+ let fn_ty = bx. type_func ( & [ llvm_elem_vec_ty, llvm_pointer, alignment_ty, mask_ty] , ret_t) ;
1675+ let f = bx. declare_cfn ( & llvm_intrinsic, llvm:: UnnamedAddr :: No , fn_ty) ;
1676+ let v = bx. call (
1677+ fn_ty,
1678+ None ,
1679+ None ,
1680+ f,
1681+ & [ args[ 2 ] . immediate ( ) , args[ 1 ] . immediate ( ) , alignment, mask] ,
1682+ None ,
1683+ ) ;
1684+ return Ok ( v) ;
1685+ }
1686+
14951687 if name == sym:: simd_scatter {
14961688 // simd_scatter(values: <N x T>, pointers: <N x *mut T>,
14971689 // mask: <N x i{M}>) -> ()
0 commit comments