@@ -1492,6 +1492,198 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
1492
1492
return Ok ( v) ;
1493
1493
}
1494
1494
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
+
1495
1687
if name == sym:: simd_scatter {
1496
1688
// simd_scatter(values: <N x T>, pointers: <N x *mut T>,
1497
1689
// mask: <N x i{M}>) -> ()
0 commit comments