@@ -3193,6 +3193,8 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
31933193 . and_then ( |def_id| self . buffer_store_intrinsics . borrow ( ) . get ( & def_id) . copied ( ) ) ;
31943194 let is_panic_entry_point = instance_def_id
31953195 . 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 ( ) ) ;
31963198
31973199 if let Some ( libm_intrinsic) = libm_intrinsic {
31983200 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> {
32043206 self . debug_type( result. ty) ,
32053207 ) ;
32063208 }
3207- result
3208- } else if is_panic_entry_point {
3209+ return result;
3210+ }
3211+
3212+ if is_panic_entry_point {
32093213 // HACK(eddyb) Rust 2021 `panic!` always uses `format_args!`, even
32103214 // in the simple case that used to pass a `&str` constant, which
32113215 // would not remain reachable in the SPIR-V - but `format_args!` is
@@ -3678,24 +3682,78 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
36783682 // HACK(eddyb) redirect any possible panic call to an abort, to avoid
36793683 // needing to materialize `&core::panic::Location` or `format_args!`.
36803684 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 {
36853693 self . codegen_buffer_store_intrinsic ( args, mode) ;
36863694
36873695 let void_ty = SpirvType :: Void . def ( rustc_span:: DUMMY_SP , self ) ;
3688- SpirvValue {
3696+ return SpirvValue {
36893697 kind : SpirvValueKind :: IllegalTypeUsed ( void_ty) ,
36903698 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+ Some ( self . constant_int ( result_type, const_val) )
3721+ }
3722+
3723+ // Signed integer widening conversions
3724+ (
3725+ ty:: Int ( IntTy :: I8 ) ,
3726+ ty:: Int ( IntTy :: I16 | IntTy :: I32 | IntTy :: I64 | IntTy :: I128 ) ,
3727+ )
3728+ | ( ty:: Int ( IntTy :: I16 ) , ty:: Int ( IntTy :: I32 | IntTy :: I64 | IntTy :: I128 ) )
3729+ | ( ty:: Int ( IntTy :: I32 ) , ty:: Int ( IntTy :: I64 | IntTy :: I128 ) )
3730+ | ( ty:: Int ( IntTy :: I64 ) , ty:: Int ( IntTy :: I128 ) ) => {
3731+ Some ( self . constant_int ( result_type, const_val) )
3732+ }
3733+
3734+ // Float widening conversions: f32->f64
3735+ ( ty:: Float ( FloatTy :: F32 ) , ty:: Float ( FloatTy :: F64 ) ) => {
3736+ let float_val = f32:: from_bits ( const_val as u32 ) as f64 ;
3737+ Some ( self . constant_float ( result_type, float_val) )
3738+ }
3739+
3740+ // No optimization for narrowing conversions or unsupported types
3741+ _ => None ,
3742+ } ;
3743+
3744+ if let Some ( result) = optimized_result {
3745+ return result;
3746+ }
3747+ }
36913748 }
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)
36983749 }
3750+
3751+ // Default: emit a regular function call
3752+ let args = args. iter ( ) . map ( |arg| arg. def ( self ) ) . collect :: < Vec < _ > > ( ) ;
3753+ self . emit ( )
3754+ . function_call ( result_type, None , callee_val, args)
3755+ . unwrap ( )
3756+ . with_type ( result_type)
36993757 }
37003758
37013759 fn zext ( & mut self , val : Self :: Value , dest_ty : Self :: Type ) -> Self :: Value {
0 commit comments