diff options
| author | bors <bors@rust-lang.org> | 2025-07-19 08:03:40 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-07-19 08:03:40 +0000 |
| commit | 83825dd277503edf5d7eda6be8b5fb9896f343f5 (patch) | |
| tree | 5996e9be886f9b180004a171e19d7270026daa79 /tests/codegen | |
| parent | 1079c5edb2bd837e5c4cf8c7db2892db359a3862 (diff) | |
| parent | 4fa23d96bc9334716b8f50511f5a920b46d349dd (diff) | |
| download | rust-83825dd277503edf5d7eda6be8b5fb9896f343f5.tar.gz rust-83825dd277503edf5d7eda6be8b5fb9896f343f5.zip | |
Auto merge of #143784 - scottmcm:enums-again-new-ex2, r=dianqk
Simplify discriminant codegen for niche-encoded variants which don't wrap across an integer boundary Inspired by rust-lang/rust#139729, this attempts to be a much-simpler and more-localized change while still making a difference. (Specifically, this does not try to solve the problem with select-sinking, leaving that to be fixed by https://github.com/llvm/llvm-project/issues/134024 -- once it gets released -- instead of in rustc's codegen.) What this *does* improve is checking for the variant in a 3+ variant enum when that variant is the type providing the niche. Something like `if let Foo::WithBool(_) = ...` previously compiled to `ugt(add(x, -2), 2)`, which is non-trivial to think about because it's depending on the unsigned wrapping to shift the 0/1 up above 2. With this PR it compiles to just `ult(x, 2)`, which is probably what you'd have written yourself if you were doing it by hand to look for "is this byte a bool?". That's done by leaving most of the codegen alone, but adding a couple new special cases to the `is_niche` check. The default looks at the relative discriminant, but in the common cases where there's no wraparound involved, we can just check the original value, rather than the offsetted one. The first commit just adds some tests, so the best way to see the effect of this change is to look at the second commit and how it updates the test expectations.
Diffstat (limited to 'tests/codegen')
| -rw-r--r-- | tests/codegen/enum/enum-discriminant-eq.rs | 223 | ||||
| -rw-r--r-- | tests/codegen/enum/enum-match.rs | 326 |
2 files changed, 539 insertions, 10 deletions
diff --git a/tests/codegen/enum/enum-discriminant-eq.rs b/tests/codegen/enum/enum-discriminant-eq.rs new file mode 100644 index 00000000000..0494c5f551b --- /dev/null +++ b/tests/codegen/enum/enum-discriminant-eq.rs @@ -0,0 +1,223 @@ +//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled +//@ min-llvm-version: 20 +//@ only-64bit + +// The `derive(PartialEq)` on enums with field-less variants compares discriminants, +// so make sure we emit that in some reasonable way. + +#![crate_type = "lib"] +#![feature(ascii_char)] +#![feature(core_intrinsics)] +#![feature(repr128)] + +use std::ascii::Char as AC; +use std::cmp::Ordering; +use std::intrinsics::discriminant_value; +use std::num::NonZero; + +// A type that's bigger than `isize`, unlike the usual cases that have small tags. +#[repr(u128)] +pub enum Giant { + Two = 2, + Three = 3, + Four = 4, +} + +#[unsafe(no_mangle)] +pub fn opt_bool_eq_discr(a: Option<bool>, b: Option<bool>) -> bool { + // CHECK-LABEL: @opt_bool_eq_discr( + // CHECK: %[[A:.+]] = icmp ne i8 %a, 2 + // CHECK: %[[B:.+]] = icmp eq i8 %b, 2 + // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]] + // CHECK: ret i1 %[[R]] + + discriminant_value(&a) == discriminant_value(&b) +} + +#[unsafe(no_mangle)] +pub fn opt_ord_eq_discr(a: Option<Ordering>, b: Option<Ordering>) -> bool { + // CHECK-LABEL: @opt_ord_eq_discr( + // CHECK: %[[A:.+]] = icmp ne i8 %a, 2 + // CHECK: %[[B:.+]] = icmp eq i8 %b, 2 + // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]] + // CHECK: ret i1 %[[R]] + + discriminant_value(&a) == discriminant_value(&b) +} + +#[unsafe(no_mangle)] +pub fn opt_nz32_eq_discr(a: Option<NonZero<u32>>, b: Option<NonZero<u32>>) -> bool { + // CHECK-LABEL: @opt_nz32_eq_discr( + // CHECK: %[[A:.+]] = icmp ne i32 %a, 0 + // CHECK: %[[B:.+]] = icmp eq i32 %b, 0 + // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]] + // CHECK: ret i1 %[[R]] + + discriminant_value(&a) == discriminant_value(&b) +} + +#[unsafe(no_mangle)] +pub fn opt_ac_eq_discr(a: Option<AC>, b: Option<AC>) -> bool { + // CHECK-LABEL: @opt_ac_eq_discr( + // CHECK: %[[A:.+]] = icmp ne i8 %a, -128 + // CHECK: %[[B:.+]] = icmp eq i8 %b, -128 + // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]] + // CHECK: ret i1 %[[R]] + + discriminant_value(&a) == discriminant_value(&b) +} + +#[unsafe(no_mangle)] +pub fn opt_giant_eq_discr(a: Option<Giant>, b: Option<Giant>) -> bool { + // CHECK-LABEL: @opt_giant_eq_discr( + // CHECK: %[[A:.+]] = icmp ne i128 %a, 1 + // CHECK: %[[B:.+]] = icmp eq i128 %b, 1 + // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]] + // CHECK: ret i1 %[[R]] + + discriminant_value(&a) == discriminant_value(&b) +} + +pub enum Mid<T> { + Before, + Thing(T), + After, +} + +#[unsafe(no_mangle)] +pub fn mid_bool_eq_discr(a: Mid<bool>, b: Mid<bool>) -> bool { + // CHECK-LABEL: @mid_bool_eq_discr( + + // CHECK: %[[A_REL_DISCR:.+]] = add nsw i8 %a, -2 + // CHECK: %[[A_IS_NICHE:.+]] = icmp samesign ugt i8 %a, 1 + // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i8 %[[A_REL_DISCR]], 1 + // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]]) + // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %[[A_REL_DISCR]], i8 1 + + // CHECK: %[[B_REL_DISCR:.+]] = add nsw i8 %b, -2 + // CHECK: %[[B_IS_NICHE:.+]] = icmp samesign ugt i8 %b, 1 + // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i8 %[[B_REL_DISCR]], 1 + // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]]) + // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %[[B_REL_DISCR]], i8 1 + + // CHECK: ret i1 %[[R]] + discriminant_value(&a) == discriminant_value(&b) +} + +#[unsafe(no_mangle)] +pub fn mid_ord_eq_discr(a: Mid<Ordering>, b: Mid<Ordering>) -> bool { + // CHECK-LABEL: @mid_ord_eq_discr( + + // CHECK: %[[A_REL_DISCR:.+]] = add nsw i8 %a, -2 + // CHECK: %[[A_IS_NICHE:.+]] = icmp sgt i8 %a, 1 + // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i8 %[[A_REL_DISCR]], 1 + // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]]) + // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %[[A_REL_DISCR]], i8 1 + + // CHECK: %[[B_REL_DISCR:.+]] = add nsw i8 %b, -2 + // CHECK: %[[B_IS_NICHE:.+]] = icmp sgt i8 %b, 1 + // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i8 %[[B_REL_DISCR]], 1 + // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]]) + // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %[[B_REL_DISCR]], i8 1 + + // CHECK: %[[R:.+]] = icmp eq i8 %[[A_DISCR]], %[[B_DISCR]] + // CHECK: ret i1 %[[R]] + discriminant_value(&a) == discriminant_value(&b) +} + +#[unsafe(no_mangle)] +pub fn mid_nz32_eq_discr(a: Mid<NonZero<u32>>, b: Mid<NonZero<u32>>) -> bool { + // CHECK-LABEL: @mid_nz32_eq_discr( + // CHECK: %[[R:.+]] = icmp eq i32 %a.0, %b.0 + // CHECK: ret i1 %[[R]] + discriminant_value(&a) == discriminant_value(&b) +} + +#[unsafe(no_mangle)] +pub fn mid_ac_eq_discr(a: Mid<AC>, b: Mid<AC>) -> bool { + // CHECK-LABEL: @mid_ac_eq_discr( + + // CHECK: %[[A_REL_DISCR:.+]] = xor i8 %a, -128 + // CHECK: %[[A_IS_NICHE:.+]] = icmp slt i8 %a, 0 + // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i8 %a, -127 + // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]]) + // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %[[A_REL_DISCR]], i8 1 + + // CHECK: %[[B_REL_DISCR:.+]] = xor i8 %b, -128 + // CHECK: %[[B_IS_NICHE:.+]] = icmp slt i8 %b, 0 + // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i8 %b, -127 + // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]]) + // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %[[B_REL_DISCR]], i8 1 + + // CHECK: %[[R:.+]] = icmp eq i8 %[[A_DISCR]], %[[B_DISCR]] + // CHECK: ret i1 %[[R]] + discriminant_value(&a) == discriminant_value(&b) +} + +// FIXME: This should be improved once our LLVM fork picks up the fix for +// <https://github.com/llvm/llvm-project/issues/134024> +#[unsafe(no_mangle)] +pub fn mid_giant_eq_discr(a: Mid<Giant>, b: Mid<Giant>) -> bool { + // CHECK-LABEL: @mid_giant_eq_discr( + + // CHECK: %[[A_TRUNC:.+]] = trunc nuw nsw i128 %a to i64 + // CHECK: %[[A_REL_DISCR:.+]] = add nsw i64 %[[A_TRUNC]], -5 + // CHECK: %[[A_IS_NICHE:.+]] = icmp samesign ugt i128 %a, 4 + // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i64 %[[A_REL_DISCR]], 1 + // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]]) + // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i64 %[[A_REL_DISCR]], i64 1 + + // CHECK: %[[B_TRUNC:.+]] = trunc nuw nsw i128 %b to i64 + // CHECK: %[[B_REL_DISCR:.+]] = add nsw i64 %[[B_TRUNC]], -5 + // CHECK: %[[B_IS_NICHE:.+]] = icmp samesign ugt i128 %b, 4 + // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i64 %[[B_REL_DISCR]], 1 + // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]]) + // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i64 %[[B_REL_DISCR]], i64 1 + + // CHECK: %[[R:.+]] = icmp eq i64 %[[A_DISCR]], %[[B_DISCR]] + // CHECK: ret i1 %[[R]] + discriminant_value(&a) == discriminant_value(&b) +} + +// In niche-encoded enums, testing for the untagged variant should optimize to a +// straight-forward comparison looking for the natural range of the payload value. + +#[unsafe(no_mangle)] +pub fn mid_bool_is_thing(a: Mid<bool>) -> bool { + // CHECK-LABEL: @mid_bool_is_thing( + // CHECK: %[[R:.+]] = icmp samesign ult i8 %a, 2 + // CHECK: ret i1 %[[R]] + discriminant_value(&a) == 1 +} + +#[unsafe(no_mangle)] +pub fn mid_ord_is_thing(a: Mid<Ordering>) -> bool { + // CHECK-LABEL: @mid_ord_is_thing( + // CHECK: %[[R:.+]] = icmp slt i8 %a, 2 + // CHECK: ret i1 %[[R]] + discriminant_value(&a) == 1 +} + +#[unsafe(no_mangle)] +pub fn mid_nz32_is_thing(a: Mid<NonZero<u32>>) -> bool { + // CHECK-LABEL: @mid_nz32_is_thing( + // CHECK: %[[R:.+]] = icmp eq i32 %a.0, 1 + // CHECK: ret i1 %[[R]] + discriminant_value(&a) == 1 +} + +#[unsafe(no_mangle)] +pub fn mid_ac_is_thing(a: Mid<AC>) -> bool { + // CHECK-LABEL: @mid_ac_is_thing( + // CHECK: %[[R:.+]] = icmp sgt i8 %a, -1 + // CHECK: ret i1 %[[R]] + discriminant_value(&a) == 1 +} + +#[unsafe(no_mangle)] +pub fn mid_giant_is_thing(a: Mid<Giant>) -> bool { + // CHECK-LABEL: @mid_giant_is_thing( + // CHECK: %[[R:.+]] = icmp samesign ult i128 %a, 5 + // CHECK: ret i1 %[[R]] + discriminant_value(&a) == 1 +} diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs index 98635008d06..57db44ec74e 100644 --- a/tests/codegen/enum/enum-match.rs +++ b/tests/codegen/enum/enum-match.rs @@ -41,7 +41,7 @@ pub enum Enum1 { // 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: %[[IS_NICHE:.+]] = icmp{{( samesign)?}} ugt i8 %0, 1 // 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]] @@ -148,10 +148,10 @@ pub enum MiddleNiche { // 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: %[[NOT_NICHE:.+]] = icmp{{( samesign)?}} ult i8 %0, 2 +// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[NOT_NICHE]], i8 2, i8 %[[REL_VAR]] // CHECK-NEXT: switch i8 %[[DISCR]] #[no_mangle] pub fn match4(e: MiddleNiche) -> u8 { @@ -167,11 +167,10 @@ pub fn match4(e: MiddleNiche) -> u8 { // 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: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %e, 4 // CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]]) -// CHECK-NEXT: ret i1 %[[NOT_NICHE]] +// CHECK-NEXT: %[[IS_C:.+]] = icmp{{( samesign)?}} ult i8 %e, 2 +// CHECK-NEXT: ret i1 %[[IS_C]] #[no_mangle] pub fn match4_is_c(e: MiddleNiche) -> bool { // Before #139098, this couldn't optimize out the `select` because it looked @@ -453,10 +452,10 @@ pub enum HugeVariantIndex { // 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: %[[IS_NICHE:.+]] = icmp{{( samesign)?}} ugt i8 %0, 1 // CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 257 +// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i64 %[[NICHE_DISCR]], 258 +// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]]) // CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 258 // CHECK-NEXT: switch i64 %[[DISCR]], // CHECK-NEXT: i64 257, @@ -471,3 +470,310 @@ pub fn match5(e: HugeVariantIndex) -> u8 { Possible259 => 100, } } + +// Make an enum where the niche tags wrap both as signed and as unsigned, to hit +// the most-fallback case where there's just nothing smart to do. + +pub enum E10Through65 { + D10 = 10, + D11 = 11, + D12 = 12, + D13 = 13, + D14 = 14, + D15 = 15, + D16 = 16, + D17 = 17, + D18 = 18, + D19 = 19, + D20 = 20, + D21 = 21, + D22 = 22, + D23 = 23, + D24 = 24, + D25 = 25, + D26 = 26, + D27 = 27, + D28 = 28, + D29 = 29, + D30 = 30, + D31 = 31, + D32 = 32, + D33 = 33, + D34 = 34, + D35 = 35, + D36 = 36, + D37 = 37, + D38 = 38, + D39 = 39, + D40 = 40, + D41 = 41, + D42 = 42, + D43 = 43, + D44 = 44, + D45 = 45, + D46 = 46, + D47 = 47, + D48 = 48, + D49 = 49, + D50 = 50, + D51 = 51, + D52 = 52, + D53 = 53, + D54 = 54, + D55 = 55, + D56 = 56, + D57 = 57, + D58 = 58, + D59 = 59, + D60 = 60, + D61 = 61, + D62 = 62, + D63 = 63, + D64 = 64, + D65 = 65, +} + +pub enum Tricky { + Untagged(E10Through65), + V001, + V002, + V003, + V004, + V005, + V006, + V007, + V008, + V009, + V010, + V011, + V012, + V013, + V014, + V015, + V016, + V017, + V018, + V019, + V020, + V021, + V022, + V023, + V024, + V025, + V026, + V027, + V028, + V029, + V030, + V031, + V032, + V033, + V034, + V035, + V036, + V037, + V038, + V039, + V040, + V041, + V042, + V043, + V044, + V045, + V046, + V047, + V048, + V049, + V050, + V051, + V052, + V053, + V054, + V055, + V056, + V057, + V058, + V059, + V060, + V061, + V062, + V063, + V064, + V065, + V066, + V067, + V068, + V069, + V070, + V071, + V072, + V073, + V074, + V075, + V076, + V077, + V078, + V079, + V080, + V081, + V082, + V083, + V084, + V085, + V086, + V087, + V088, + V089, + V090, + V091, + V092, + V093, + V094, + V095, + V096, + V097, + V098, + V099, + V100, + V101, + V102, + V103, + V104, + V105, + V106, + V107, + V108, + V109, + V110, + V111, + V112, + V113, + V114, + V115, + V116, + V117, + V118, + V119, + V120, + V121, + V122, + V123, + V124, + V125, + V126, + V127, + V128, + V129, + V130, + V131, + V132, + V133, + V134, + V135, + V136, + V137, + V138, + V139, + V140, + V141, + V142, + V143, + V144, + V145, + V146, + V147, + V148, + V149, + V150, + V151, + V152, + V153, + V154, + V155, + V156, + V157, + V158, + V159, + V160, + V161, + V162, + V163, + V164, + V165, + V166, + V167, + V168, + V169, + V170, + V171, + V172, + V173, + V174, + V175, + V176, + V177, + V178, + V179, + V180, + V181, + V182, + V183, + V184, + V185, + V186, + V187, + V188, + V189, + V190, + V191, + V192, + V193, + V194, + V195, + V196, + V197, + V198, + V199, + V200, +} + +const _: () = assert!(std::intrinsics::discriminant_value(&Tricky::V100) == 100); + +// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @discriminant6(i8 noundef %e) +// CHECK-NEXT: start: +// CHECK-NEXT: %[[REL_VAR:.+]] = add i8 %e, -66 +// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], -56 +// CHECK-NEXT: %[[TAGGED_DISCR:.+]] = add i8 %e, -65 +// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i8 %[[TAGGED_DISCR]], i8 0 +// CHECK-NEXT: ret i8 %[[DISCR]] +#[no_mangle] +pub fn discriminant6(e: Tricky) -> u8 { + std::intrinsics::discriminant_value(&e) as _ +} + +// Case from <https://github.com/rust-lang/rust/issues/104519>, +// where sign-extension is important. + +pub enum OpenResult { + Ok(()), + Err(()), + TransportErr(TransportErr), +} + +#[repr(i32)] +pub enum TransportErr { + UnknownMethod = -2, +} + +#[no_mangle] +pub fn match7(result: OpenResult) -> u8 { + // CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match7(i32{{.+}}%result) + // CHECK-NEXT: start: + // CHECK-NEXT: %[[NOT_OK:.+]] = icmp ne i32 %result, -1 + // CHECK-NEXT: %[[RET:.+]] = zext i1 %[[NOT_OK]] to i8 + // CHECK-NEXT: ret i8 %[[RET]] + match result { + OpenResult::Ok(()) => 0, + _ => 1, + } +} |
