@@ -567,6 +567,130 @@ fn codegen_regular_intrinsic_call<'tcx>(
567
567
// FIXME use emit_small_memset
568
568
fx. bcx . call_memset ( fx. target_config , dst_ptr, val, count) ;
569
569
}
570
+
571
+ sym:: swap_nonoverlapping_single => {
572
+ intrinsic_args ! ( fx, args => ( x_ptr, y_ptr) ; intrinsic) ;
573
+ let pointee_ty = x_ptr. layout ( ) . ty . builtin_deref ( true ) . unwrap ( ) . ty ;
574
+ let pointee_layout = fx. layout_of ( pointee_ty) ;
575
+
576
+ // ZSTs swap is noop.
577
+ if pointee_layout. size != Size :: ZERO {
578
+ // Probably, it would be better to have dedicated method for this in
579
+ // `cranelift_frontend::FunctionBuilder`
580
+ // with optimizations based on size and alignment of values.
581
+
582
+ let x_ptr_val = x_ptr. load_scalar ( fx) ;
583
+ let y_ptr_val = y_ptr. load_scalar ( fx) ;
584
+
585
+ let tmp_place = CPlace :: new_stack_slot ( fx, pointee_layout) ;
586
+ let tmp_ptr_val = tmp_place. to_ptr ( ) . get_addr ( fx) ;
587
+
588
+ let size_bytes = pointee_layout. size . bytes ( ) ;
589
+ let align_bytes: u8 = pointee_layout. align . abi . bytes ( ) . try_into ( ) . unwrap ( ) ;
590
+ fx. bcx . emit_small_memory_copy (
591
+ fx. target_config ,
592
+ tmp_ptr_val,
593
+ x_ptr_val,
594
+ size_bytes,
595
+ align_bytes,
596
+ align_bytes,
597
+ true ,
598
+ MemFlags :: trusted ( ) ,
599
+ ) ;
600
+ fx. bcx . emit_small_memory_copy (
601
+ fx. target_config ,
602
+ x_ptr_val,
603
+ y_ptr_val,
604
+ size_bytes,
605
+ align_bytes,
606
+ align_bytes,
607
+ true ,
608
+ MemFlags :: trusted ( ) ,
609
+ ) ;
610
+ fx. bcx . emit_small_memory_copy (
611
+ fx. target_config ,
612
+ y_ptr_val,
613
+ tmp_ptr_val,
614
+ size_bytes,
615
+ align_bytes,
616
+ align_bytes,
617
+ true ,
618
+ MemFlags :: trusted ( ) ,
619
+ ) ;
620
+ }
621
+ }
622
+
623
+ sym:: swap_nonoverlapping_many => {
624
+ intrinsic_args ! ( fx, args => ( x_ptr, y_ptr, count) ; intrinsic) ;
625
+ let pointee_ty = x_ptr. layout ( ) . ty . builtin_deref ( true ) . unwrap ( ) . ty ;
626
+ let pointee_layout = fx. layout_of ( pointee_ty) ;
627
+
628
+ // ZSTs swap is noop.
629
+ if pointee_layout. size != Size :: ZERO {
630
+ let x_ptr_val = x_ptr. load_scalar ( fx) ;
631
+ let y_ptr_val = y_ptr. load_scalar ( fx) ;
632
+
633
+ let count = count. load_scalar ( fx) ;
634
+
635
+ let tmp_place = CPlace :: new_stack_slot ( fx, pointee_layout) ;
636
+ let tmp_ptr_val = tmp_place. to_ptr ( ) . get_addr ( fx) ;
637
+
638
+ let elem_size_bytes = pointee_layout. size . bytes ( ) ;
639
+ let align_bytes: u8 = pointee_layout. align . abi . bytes ( ) . try_into ( ) . unwrap ( ) ;
640
+
641
+ let loop_header = fx. bcx . create_block ( ) ;
642
+ let loop_body = fx. bcx . create_block ( ) ;
643
+ let loop_done = fx. bcx . create_block ( ) ;
644
+
645
+ let index = fx. bcx . append_block_param ( loop_header, fx. pointer_type ) ;
646
+ let zero = fx. bcx . ins ( ) . iconst ( fx. pointer_type , 0 ) ;
647
+ fx. bcx . ins ( ) . jump ( loop_header, & [ zero] ) ;
648
+
649
+ fx. bcx . switch_to_block ( loop_header) ;
650
+ let is_done = fx. bcx . ins ( ) . icmp ( IntCC :: Equal , index, count) ;
651
+ fx. bcx . ins ( ) . brif ( is_done, loop_done, & [ ] , loop_body, & [ ] ) ;
652
+
653
+ fx. bcx . switch_to_block ( loop_body) ;
654
+ let curr_x_ptr_val = fx. bcx . ins ( ) . iadd ( x_ptr_val, index) ;
655
+ let curr_y_ptr_val = fx. bcx . ins ( ) . iadd ( y_ptr_val, index) ;
656
+ fx. bcx . emit_small_memory_copy (
657
+ fx. target_config ,
658
+ tmp_ptr_val,
659
+ curr_x_ptr_val,
660
+ elem_size_bytes,
661
+ align_bytes,
662
+ align_bytes,
663
+ true ,
664
+ MemFlags :: trusted ( ) ,
665
+ ) ;
666
+ fx. bcx . emit_small_memory_copy (
667
+ fx. target_config ,
668
+ curr_x_ptr_val,
669
+ curr_y_ptr_val,
670
+ elem_size_bytes,
671
+ align_bytes,
672
+ align_bytes,
673
+ true ,
674
+ MemFlags :: trusted ( ) ,
675
+ ) ;
676
+ fx. bcx . emit_small_memory_copy (
677
+ fx. target_config ,
678
+ curr_y_ptr_val,
679
+ tmp_ptr_val,
680
+ elem_size_bytes,
681
+ align_bytes,
682
+ align_bytes,
683
+ true ,
684
+ MemFlags :: trusted ( ) ,
685
+ ) ;
686
+ let next_index = fx. bcx . ins ( ) . iadd_imm ( index, 1 ) ;
687
+ fx. bcx . ins ( ) . jump ( loop_header, & [ next_index] ) ;
688
+
689
+ fx. bcx . switch_to_block ( loop_done) ;
690
+ fx. bcx . ins ( ) . nop ( ) ;
691
+ }
692
+ }
693
+
570
694
sym:: ctlz | sym:: ctlz_nonzero => {
571
695
intrinsic_args ! ( fx, args => ( arg) ; intrinsic) ;
572
696
let val = arg. load_scalar ( fx) ;
0 commit comments