mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-30 20:44:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			474 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			474 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| //@ compile-flags: -Copt-level=1
 | |
| //@ only-64bit
 | |
| 
 | |
| #![crate_type = "lib"]
 | |
| #![feature(core_intrinsics)]
 | |
| 
 | |
| // Check each of the 3 cases for `codegen_get_discr`.
 | |
| 
 | |
| // FIXME: once our min-bar LLVM has `range` attributes, update the various
 | |
| // tests here to no longer have the `range`s and `nsw`s as optional.
 | |
| 
 | |
| // Case 0: One tagged variant.
 | |
| pub enum Enum0 {
 | |
|     A(bool),
 | |
|     B,
 | |
| }
 | |
| 
 | |
| // CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match0(i8{{.+}}%0)
 | |
| // CHECK-NEXT: start:
 | |
| // CHECK-NEXT: %[[IS_B:.+]] = icmp eq i8 %0, 2
 | |
| // CHECK-NEXT: %[[TRUNC:.+]] = and i8 %0, 1
 | |
| // CHECK-NEXT: %[[R:.+]] = select i1 %[[IS_B]], i8 13, i8 %[[TRUNC]]
 | |
| // CHECK-NEXT: ret i8 %[[R]]
 | |
| #[no_mangle]
 | |
| pub fn match0(e: Enum0) -> u8 {
 | |
|     use Enum0::*;
 | |
|     match e {
 | |
|         A(b) => b as u8,
 | |
|         B => 13,
 | |
|     }
 | |
| }
 | |
| 
 | |
| // Case 1: Niche values are on a boundary for `range`.
 | |
| pub enum Enum1 {
 | |
|     A(bool),
 | |
|     B,
 | |
|     C,
 | |
| }
 | |
| 
 | |
| // CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1(i8{{.+}}%0)
 | |
| // CHECK-NEXT: start:
 | |
| // CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
 | |
| // CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
 | |
| // CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 2
 | |
| // CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 1
 | |
| // CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 0
 | |
| // CHECK-NEXT: switch i64 %[[DISCR]]
 | |
| #[no_mangle]
 | |
| pub fn match1(e: Enum1) -> u8 {
 | |
|     use Enum1::*;
 | |
|     match e {
 | |
|         A(b) => b as u8,
 | |
|         B => 13,
 | |
|         C => 100,
 | |
|     }
 | |
| }
 | |
| 
 | |
| // Case 2: Special cases don't apply.
 | |
| #[rustfmt::skip]
 | |
| pub enum X {
 | |
|     _2=2, _3, _4, _5, _6, _7, _8, _9, _10, _11,
 | |
|     _12, _13, _14, _15, _16, _17, _18, _19, _20,
 | |
|     _21, _22, _23, _24, _25, _26, _27, _28, _29,
 | |
|     _30, _31, _32, _33, _34, _35, _36, _37, _38,
 | |
|     _39, _40, _41, _42, _43, _44, _45, _46, _47,
 | |
|     _48, _49, _50, _51, _52, _53, _54, _55, _56,
 | |
|     _57, _58, _59, _60, _61, _62, _63, _64, _65,
 | |
|     _66, _67, _68, _69, _70, _71, _72, _73, _74,
 | |
|     _75, _76, _77, _78, _79, _80, _81, _82, _83,
 | |
|     _84, _85, _86, _87, _88, _89, _90, _91, _92,
 | |
|     _93, _94, _95, _96, _97, _98, _99, _100, _101,
 | |
|     _102, _103, _104, _105, _106, _107, _108, _109,
 | |
|     _110, _111, _112, _113, _114, _115, _116, _117,
 | |
|     _118, _119, _120, _121, _122, _123, _124, _125,
 | |
|     _126, _127, _128, _129, _130, _131, _132, _133,
 | |
|     _134, _135, _136, _137, _138, _139, _140, _141,
 | |
|     _142, _143, _144, _145, _146, _147, _148, _149,
 | |
|     _150, _151, _152, _153, _154, _155, _156, _157,
 | |
|     _158, _159, _160, _161, _162, _163, _164, _165,
 | |
|     _166, _167, _168, _169, _170, _171, _172, _173,
 | |
|     _174, _175, _176, _177, _178, _179, _180, _181,
 | |
|     _182, _183, _184, _185, _186, _187, _188, _189,
 | |
|     _190, _191, _192, _193, _194, _195, _196, _197,
 | |
|     _198, _199, _200, _201, _202, _203, _204, _205,
 | |
|     _206, _207, _208, _209, _210, _211, _212, _213,
 | |
|     _214, _215, _216, _217, _218, _219, _220, _221,
 | |
|     _222, _223, _224, _225, _226, _227, _228, _229,
 | |
|     _230, _231, _232, _233, _234, _235, _236, _237,
 | |
|     _238, _239, _240, _241, _242, _243, _244, _245,
 | |
|     _246, _247, _248, _249, _250, _251, _252, _253,
 | |
| }
 | |
| 
 | |
| pub enum Enum2 {
 | |
|     A(X),
 | |
|     B,
 | |
|     C,
 | |
|     D,
 | |
|     E,
 | |
| }
 | |
| 
 | |
| // CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match2(i8{{.+}}%0)
 | |
| // CHECK-NEXT: start:
 | |
| // CHECK-NEXT: %[[REL_VAR:.+]] = add i8 %0, 2
 | |
| // CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
 | |
| // CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 4
 | |
| // CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 1
 | |
| // CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 0
 | |
| // CHECK-NEXT: switch i64 %[[DISCR]]
 | |
| #[no_mangle]
 | |
| pub fn match2(e: Enum2) -> u8 {
 | |
|     use Enum2::*;
 | |
|     match e {
 | |
|         A(b) => b as u8,
 | |
|         B => 13,
 | |
|         C => 100,
 | |
|         D => 200,
 | |
|         E => 250,
 | |
|     }
 | |
| }
 | |
| 
 | |
| // And make sure it works even if the niched scalar is a pointer.
 | |
| // (For example, that we don't try to `sub` on pointers.)
 | |
| 
 | |
| // CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i16 -?[0-9]+, -?[0-9]+\))?}} i16 @match3(ptr{{.+}}%0)
 | |
| // CHECK-NEXT: start:
 | |
| // CHECK-NEXT: %[[IS_NULL:.+]] = icmp eq ptr %0, null
 | |
| // CHECK-NEXT: br i1 %[[IS_NULL]]
 | |
| #[no_mangle]
 | |
| pub fn match3(e: Option<&u8>) -> i16 {
 | |
|     match e {
 | |
|         Some(r) => *r as _,
 | |
|         None => -1,
 | |
|     }
 | |
| }
 | |
| 
 | |
| // If the untagged variant is in the middle, there's an impossible value that's
 | |
| // not reflected in the `range` parameter attribute, so we assume it away.
 | |
| 
 | |
| #[derive(PartialEq)]
 | |
| pub enum MiddleNiche {
 | |
|     A,
 | |
|     B,
 | |
|     C(bool),
 | |
|     D,
 | |
|     E,
 | |
| }
 | |
| 
 | |
| // CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 -?[0-9]+, -?[0-9]+\))?}} i8 @match4(i8{{.+}}%0)
 | |
| // CHECK-NEXT: start:
 | |
| // CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
 | |
| // CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 5
 | |
| // CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2
 | |
| // CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
 | |
| // CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i8 %[[REL_VAR]], i8 2
 | |
| // CHECK-NEXT: switch i8 %[[DISCR]]
 | |
| #[no_mangle]
 | |
| pub fn match4(e: MiddleNiche) -> u8 {
 | |
|     use MiddleNiche::*;
 | |
|     match e {
 | |
|         A => 13,
 | |
|         B => 100,
 | |
|         C(b) => b as u8,
 | |
|         D => 200,
 | |
|         E => 250,
 | |
|     }
 | |
| }
 | |
| 
 | |
| // CHECK-LABEL: define{{.+}}i1 @match4_is_c(i8{{.+}}%e)
 | |
| // CHECK-NEXT: start
 | |
| // CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %e, -2
 | |
| // CHECK-NEXT: %[[NOT_NICHE:.+]] = icmp ugt i8 %[[REL_VAR]], 4
 | |
| // CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2
 | |
| // CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
 | |
| // CHECK-NEXT: ret i1 %[[NOT_NICHE]]
 | |
| #[no_mangle]
 | |
| pub fn match4_is_c(e: MiddleNiche) -> bool {
 | |
|     // Before #139098, this couldn't optimize out the `select` because it looked
 | |
|     // like it was possible for a `2` to be produced on both sides.
 | |
| 
 | |
|     std::intrinsics::discriminant_value(&e) == 2
 | |
| }
 | |
| 
 | |
| // You have to do something pretty obnoxious to get a variant index that doesn't
 | |
| // fit in the tag size, but it's possible
 | |
| 
 | |
| pub enum Never {}
 | |
| 
 | |
| pub enum HugeVariantIndex {
 | |
|     V000(Never),
 | |
|     V001(Never),
 | |
|     V002(Never),
 | |
|     V003(Never),
 | |
|     V004(Never),
 | |
|     V005(Never),
 | |
|     V006(Never),
 | |
|     V007(Never),
 | |
|     V008(Never),
 | |
|     V009(Never),
 | |
|     V010(Never),
 | |
|     V011(Never),
 | |
|     V012(Never),
 | |
|     V013(Never),
 | |
|     V014(Never),
 | |
|     V015(Never),
 | |
|     V016(Never),
 | |
|     V017(Never),
 | |
|     V018(Never),
 | |
|     V019(Never),
 | |
|     V020(Never),
 | |
|     V021(Never),
 | |
|     V022(Never),
 | |
|     V023(Never),
 | |
|     V024(Never),
 | |
|     V025(Never),
 | |
|     V026(Never),
 | |
|     V027(Never),
 | |
|     V028(Never),
 | |
|     V029(Never),
 | |
|     V030(Never),
 | |
|     V031(Never),
 | |
|     V032(Never),
 | |
|     V033(Never),
 | |
|     V034(Never),
 | |
|     V035(Never),
 | |
|     V036(Never),
 | |
|     V037(Never),
 | |
|     V038(Never),
 | |
|     V039(Never),
 | |
|     V040(Never),
 | |
|     V041(Never),
 | |
|     V042(Never),
 | |
|     V043(Never),
 | |
|     V044(Never),
 | |
|     V045(Never),
 | |
|     V046(Never),
 | |
|     V047(Never),
 | |
|     V048(Never),
 | |
|     V049(Never),
 | |
|     V050(Never),
 | |
|     V051(Never),
 | |
|     V052(Never),
 | |
|     V053(Never),
 | |
|     V054(Never),
 | |
|     V055(Never),
 | |
|     V056(Never),
 | |
|     V057(Never),
 | |
|     V058(Never),
 | |
|     V059(Never),
 | |
|     V060(Never),
 | |
|     V061(Never),
 | |
|     V062(Never),
 | |
|     V063(Never),
 | |
|     V064(Never),
 | |
|     V065(Never),
 | |
|     V066(Never),
 | |
|     V067(Never),
 | |
|     V068(Never),
 | |
|     V069(Never),
 | |
|     V070(Never),
 | |
|     V071(Never),
 | |
|     V072(Never),
 | |
|     V073(Never),
 | |
|     V074(Never),
 | |
|     V075(Never),
 | |
|     V076(Never),
 | |
|     V077(Never),
 | |
|     V078(Never),
 | |
|     V079(Never),
 | |
|     V080(Never),
 | |
|     V081(Never),
 | |
|     V082(Never),
 | |
|     V083(Never),
 | |
|     V084(Never),
 | |
|     V085(Never),
 | |
|     V086(Never),
 | |
|     V087(Never),
 | |
|     V088(Never),
 | |
|     V089(Never),
 | |
|     V090(Never),
 | |
|     V091(Never),
 | |
|     V092(Never),
 | |
|     V093(Never),
 | |
|     V094(Never),
 | |
|     V095(Never),
 | |
|     V096(Never),
 | |
|     V097(Never),
 | |
|     V098(Never),
 | |
|     V099(Never),
 | |
|     V100(Never),
 | |
|     V101(Never),
 | |
|     V102(Never),
 | |
|     V103(Never),
 | |
|     V104(Never),
 | |
|     V105(Never),
 | |
|     V106(Never),
 | |
|     V107(Never),
 | |
|     V108(Never),
 | |
|     V109(Never),
 | |
|     V110(Never),
 | |
|     V111(Never),
 | |
|     V112(Never),
 | |
|     V113(Never),
 | |
|     V114(Never),
 | |
|     V115(Never),
 | |
|     V116(Never),
 | |
|     V117(Never),
 | |
|     V118(Never),
 | |
|     V119(Never),
 | |
|     V120(Never),
 | |
|     V121(Never),
 | |
|     V122(Never),
 | |
|     V123(Never),
 | |
|     V124(Never),
 | |
|     V125(Never),
 | |
|     V126(Never),
 | |
|     V127(Never),
 | |
|     V128(Never),
 | |
|     V129(Never),
 | |
|     V130(Never),
 | |
|     V131(Never),
 | |
|     V132(Never),
 | |
|     V133(Never),
 | |
|     V134(Never),
 | |
|     V135(Never),
 | |
|     V136(Never),
 | |
|     V137(Never),
 | |
|     V138(Never),
 | |
|     V139(Never),
 | |
|     V140(Never),
 | |
|     V141(Never),
 | |
|     V142(Never),
 | |
|     V143(Never),
 | |
|     V144(Never),
 | |
|     V145(Never),
 | |
|     V146(Never),
 | |
|     V147(Never),
 | |
|     V148(Never),
 | |
|     V149(Never),
 | |
|     V150(Never),
 | |
|     V151(Never),
 | |
|     V152(Never),
 | |
|     V153(Never),
 | |
|     V154(Never),
 | |
|     V155(Never),
 | |
|     V156(Never),
 | |
|     V157(Never),
 | |
|     V158(Never),
 | |
|     V159(Never),
 | |
|     V160(Never),
 | |
|     V161(Never),
 | |
|     V162(Never),
 | |
|     V163(Never),
 | |
|     V164(Never),
 | |
|     V165(Never),
 | |
|     V166(Never),
 | |
|     V167(Never),
 | |
|     V168(Never),
 | |
|     V169(Never),
 | |
|     V170(Never),
 | |
|     V171(Never),
 | |
|     V172(Never),
 | |
|     V173(Never),
 | |
|     V174(Never),
 | |
|     V175(Never),
 | |
|     V176(Never),
 | |
|     V177(Never),
 | |
|     V178(Never),
 | |
|     V179(Never),
 | |
|     V180(Never),
 | |
|     V181(Never),
 | |
|     V182(Never),
 | |
|     V183(Never),
 | |
|     V184(Never),
 | |
|     V185(Never),
 | |
|     V186(Never),
 | |
|     V187(Never),
 | |
|     V188(Never),
 | |
|     V189(Never),
 | |
|     V190(Never),
 | |
|     V191(Never),
 | |
|     V192(Never),
 | |
|     V193(Never),
 | |
|     V194(Never),
 | |
|     V195(Never),
 | |
|     V196(Never),
 | |
|     V197(Never),
 | |
|     V198(Never),
 | |
|     V199(Never),
 | |
|     V200(Never),
 | |
|     V201(Never),
 | |
|     V202(Never),
 | |
|     V203(Never),
 | |
|     V204(Never),
 | |
|     V205(Never),
 | |
|     V206(Never),
 | |
|     V207(Never),
 | |
|     V208(Never),
 | |
|     V209(Never),
 | |
|     V210(Never),
 | |
|     V211(Never),
 | |
|     V212(Never),
 | |
|     V213(Never),
 | |
|     V214(Never),
 | |
|     V215(Never),
 | |
|     V216(Never),
 | |
|     V217(Never),
 | |
|     V218(Never),
 | |
|     V219(Never),
 | |
|     V220(Never),
 | |
|     V221(Never),
 | |
|     V222(Never),
 | |
|     V223(Never),
 | |
|     V224(Never),
 | |
|     V225(Never),
 | |
|     V226(Never),
 | |
|     V227(Never),
 | |
|     V228(Never),
 | |
|     V229(Never),
 | |
|     V230(Never),
 | |
|     V231(Never),
 | |
|     V232(Never),
 | |
|     V233(Never),
 | |
|     V234(Never),
 | |
|     V235(Never),
 | |
|     V236(Never),
 | |
|     V237(Never),
 | |
|     V238(Never),
 | |
|     V239(Never),
 | |
|     V240(Never),
 | |
|     V241(Never),
 | |
|     V242(Never),
 | |
|     V243(Never),
 | |
|     V244(Never),
 | |
|     V245(Never),
 | |
|     V246(Never),
 | |
|     V247(Never),
 | |
|     V248(Never),
 | |
|     V249(Never),
 | |
|     V250(Never),
 | |
|     V251(Never),
 | |
|     V252(Never),
 | |
|     V253(Never),
 | |
|     V254(Never),
 | |
|     V255(Never),
 | |
|     V256(Never),
 | |
| 
 | |
|     Possible257,
 | |
|     Bool258(bool),
 | |
|     Possible259,
 | |
| }
 | |
| 
 | |
| // CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match5(i8{{.+}}%0)
 | |
| // CHECK-NEXT: start:
 | |
| // CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
 | |
| // CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
 | |
| // CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 3
 | |
| // CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 1
 | |
| // CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
 | |
| // CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 257
 | |
| // CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 258
 | |
| // CHECK-NEXT: switch i64 %[[DISCR]],
 | |
| // CHECK-NEXT:   i64 257,
 | |
| // CHECK-NEXT:   i64 258,
 | |
| // CHECK-NEXT:   i64 259,
 | |
| #[no_mangle]
 | |
| pub fn match5(e: HugeVariantIndex) -> u8 {
 | |
|     use HugeVariantIndex::*;
 | |
|     match e {
 | |
|         Possible257 => 13,
 | |
|         Bool258(b) => b as u8,
 | |
|         Possible259 => 100,
 | |
|     }
 | |
| }
 | 
