@@ -9,6 +9,7 @@ use rustc_middle::mir::{self, ConstValue};
99use rustc_middle:: ty:: Ty ;
1010use rustc_middle:: ty:: layout:: { LayoutOf , TyAndLayout } ;
1111use rustc_middle:: { bug, span_bug} ;
12+ use rustc_session:: config:: OptLevel ;
1213use tracing:: { debug, instrument} ;
1314
1415use super :: place:: { PlaceRef , PlaceValue } ;
@@ -496,6 +497,18 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
496497 _ => ( tag_imm, bx. cx ( ) . immediate_backend_type ( tag_op. layout ) ) ,
497498 } ;
498499
500+ // Layout ensures that we only get here for cases where the discriminant
501+ // value and the variant index match, since that's all `Niche` can encode.
502+ // But for emphasis and debugging, let's double-check one anyway.
503+ debug_assert_eq ! (
504+ self . layout
505+ . ty
506+ . discriminant_for_variant( bx. tcx( ) , untagged_variant)
507+ . unwrap( )
508+ . val,
509+ u128 :: from( untagged_variant. as_u32( ) ) ,
510+ ) ;
511+
499512 let relative_max = niche_variants. end ( ) . as_u32 ( ) - niche_variants. start ( ) . as_u32 ( ) ;
500513
501514 // We have a subrange `niche_start..=niche_end` inside `range`.
@@ -537,6 +550,21 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
537550 relative_discr,
538551 bx. cx ( ) . const_uint ( tag_llty, relative_max as u64 ) ,
539552 ) ;
553+
554+ // Thanks to parameter attributes and load metadata, LLVM already knows
555+ // the general valid range of the tag. It's possible, though, for there
556+ // to be an impossible value *in the middle*, which those ranges don't
557+ // communicate, so it's worth an `assume` to let the optimizer know.
558+ if niche_variants. contains ( & untagged_variant)
559+ && bx. cx ( ) . sess ( ) . opts . optimize != OptLevel :: No
560+ {
561+ let impossible =
562+ u64:: from ( untagged_variant. as_u32 ( ) - niche_variants. start ( ) . as_u32 ( ) ) ;
563+ let impossible = bx. cx ( ) . const_uint ( tag_llty, impossible) ;
564+ let ne = bx. icmp ( IntPredicate :: IntNE , relative_discr, impossible) ;
565+ bx. assume ( ne) ;
566+ }
567+
540568 ( is_niche, cast_tag, niche_variants. start ( ) . as_u32 ( ) as u128 )
541569 } ;
542570
0 commit comments