@@ -3193,6 +3193,8 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
3193
3193
. and_then ( |def_id| self . buffer_store_intrinsics . borrow ( ) . get ( & def_id) . copied ( ) ) ;
3194
3194
let is_panic_entry_point = instance_def_id
3195
3195
. is_some_and ( |def_id| self . panic_entry_points . borrow ( ) . contains ( & def_id) ) ;
3196
+ let from_trait_impl =
3197
+ instance_def_id. and_then ( |def_id| self . from_trait_impls . borrow ( ) . get ( & def_id) . copied ( ) ) ;
3196
3198
3197
3199
if let Some ( libm_intrinsic) = libm_intrinsic {
3198
3200
let result = self . call_libm_intrinsic ( libm_intrinsic, result_type, args) ;
@@ -3204,8 +3206,10 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
3204
3206
self . debug_type( result. ty) ,
3205
3207
) ;
3206
3208
}
3207
- result
3208
- } else if is_panic_entry_point {
3209
+ return result;
3210
+ }
3211
+
3212
+ if is_panic_entry_point {
3209
3213
// HACK(eddyb) Rust 2021 `panic!` always uses `format_args!`, even
3210
3214
// in the simple case that used to pass a `&str` constant, which
3211
3215
// would not remain reachable in the SPIR-V - but `format_args!` is
@@ -3678,24 +3682,75 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
3678
3682
// HACK(eddyb) redirect any possible panic call to an abort, to avoid
3679
3683
// needing to materialize `&core::panic::Location` or `format_args!`.
3680
3684
self . abort_with_kind_and_message_debug_printf ( "panic" , message, debug_printf_args) ;
3681
- self . undef ( result_type)
3682
- } else if let Some ( mode) = buffer_load_intrinsic {
3683
- self . codegen_buffer_load_intrinsic ( result_type, args, mode)
3684
- } else if let Some ( mode) = buffer_store_intrinsic {
3685
+ return self . undef ( result_type) ;
3686
+ }
3687
+
3688
+ if let Some ( mode) = buffer_load_intrinsic {
3689
+ return self . codegen_buffer_load_intrinsic ( result_type, args, mode) ;
3690
+ }
3691
+
3692
+ if let Some ( mode) = buffer_store_intrinsic {
3685
3693
self . codegen_buffer_store_intrinsic ( args, mode) ;
3686
3694
3687
3695
let void_ty = SpirvType :: Void . def ( rustc_span:: DUMMY_SP , self ) ;
3688
- SpirvValue {
3696
+ return SpirvValue {
3689
3697
kind : SpirvValueKind :: IllegalTypeUsed ( void_ty) ,
3690
3698
ty : void_ty,
3699
+ } ;
3700
+ }
3701
+
3702
+ if let Some ( ( source_ty, target_ty) ) = from_trait_impl {
3703
+ // Optimize From::from calls with constant arguments to avoid creating intermediate types.
3704
+ if let [ arg] = args {
3705
+ if let Some ( const_val) = self . builder . lookup_const_scalar ( * arg) {
3706
+ use rustc_middle:: ty:: { FloatTy , IntTy , UintTy } ;
3707
+
3708
+ let optimized_result = match ( source_ty. kind ( ) , target_ty. kind ( ) ) {
3709
+ // Unsigned integer widening conversions
3710
+ (
3711
+ ty:: Uint ( UintTy :: U8 ) ,
3712
+ ty:: Uint ( UintTy :: U16 | UintTy :: U32 | UintTy :: U64 | UintTy :: U128 ) ,
3713
+ )
3714
+ | (
3715
+ ty:: Uint ( UintTy :: U16 ) ,
3716
+ ty:: Uint ( UintTy :: U32 | UintTy :: U64 | UintTy :: U128 ) ,
3717
+ )
3718
+ | ( ty:: Uint ( UintTy :: U32 ) , ty:: Uint ( UintTy :: U64 | UintTy :: U128 ) )
3719
+ | ( ty:: Uint ( UintTy :: U64 ) , ty:: Uint ( UintTy :: U128 ) )
3720
+ // Signed integer widening conversions
3721
+ | (
3722
+ ty:: Int ( IntTy :: I8 ) ,
3723
+ ty:: Int ( IntTy :: I16 | IntTy :: I32 | IntTy :: I64 | IntTy :: I128 ) ,
3724
+ )
3725
+ | ( ty:: Int ( IntTy :: I16 ) , ty:: Int ( IntTy :: I32 | IntTy :: I64 | IntTy :: I128 ) )
3726
+ | ( ty:: Int ( IntTy :: I32 ) , ty:: Int ( IntTy :: I64 | IntTy :: I128 ) )
3727
+ | ( ty:: Int ( IntTy :: I64 ) , ty:: Int ( IntTy :: I128 ) ) => {
3728
+ Some ( self . constant_int ( result_type, const_val) )
3729
+ }
3730
+
3731
+ // Float widening conversions: f32->f64
3732
+ ( ty:: Float ( FloatTy :: F32 ) , ty:: Float ( FloatTy :: F64 ) ) => {
3733
+ let float_val = f32:: from_bits ( const_val as u32 ) as f64 ;
3734
+ Some ( self . constant_float ( result_type, float_val) )
3735
+ }
3736
+
3737
+ // No optimization for narrowing conversions or unsupported types
3738
+ _ => None ,
3739
+ } ;
3740
+
3741
+ if let Some ( result) = optimized_result {
3742
+ return result;
3743
+ }
3744
+ }
3691
3745
}
3692
- } else {
3693
- let args = args. iter ( ) . map ( |arg| arg. def ( self ) ) . collect :: < Vec < _ > > ( ) ;
3694
- self . emit ( )
3695
- . function_call ( result_type, None , callee_val, args)
3696
- . unwrap ( )
3697
- . with_type ( result_type)
3698
3746
}
3747
+
3748
+ // Default: emit a regular function call
3749
+ let args = args. iter ( ) . map ( |arg| arg. def ( self ) ) . collect :: < Vec < _ > > ( ) ;
3750
+ self . emit ( )
3751
+ . function_call ( result_type, None , callee_val, args)
3752
+ . unwrap ( )
3753
+ . with_type ( result_type)
3699
3754
}
3700
3755
3701
3756
fn zext ( & mut self , val : Self :: Value , dest_ty : Self :: Type ) -> Self :: Value {
0 commit comments