@@ -567,6 +567,130 @@ fn codegen_regular_intrinsic_call<'tcx>(
567567 // FIXME use emit_small_memset
568568 fx. bcx . call_memset ( fx. target_config , dst_ptr, val, count) ;
569569 }
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+
570694 sym:: ctlz | sym:: ctlz_nonzero => {
571695 intrinsic_args ! ( fx, args => ( arg) ; intrinsic) ;
572696 let val = arg. load_scalar ( fx) ;
0 commit comments