Repository: rust-lang/rust
File: tests/codegen-llvm/issues/multiple-option-or-permutations.rs (Rust)

Code before:
    opta.or(optb)
}

// CHECK-LABEL: @if_some_u8
// CHECK-SAME: (i1{{.+}}%opta.0, i8 %opta.1, i1{{.+}}%optb.0, i8 %optb.1)
#[no_mangle]
pub fn if_some_u8(opta: Option<u8>, optb: Option<u8>) -> Option<u8> {
    // CHECK: start:
    // CHECK-DAG: [[A_OR_B:%.+]] = select i1 %opta.0, i8 %opta.1, i8 %optb.1
    // CHECK-DAG: [[IS_SOME:%.+]] = or i1 {{%opta.0, %optb.0|%optb.0, %opta.0}}
    // CHECK-NEXT: [[FLAG:%.+]] = insertvalue { i1, i8 } poison, i1 [[IS_SOME]], 0
    // CHECK-NEXT: [[R:%.+]] = insertvalue { i1, i8 } [[FLAG]], i8 [[A_OR_B]], 1
    // CHECK: ret { i1, i8 } [[R]]
    if opta.is_some() { opta } else { optb }
}

// Tests a case where an input is a type that is represented as `BackendRepr::Memory`

// CHECK-LABEL: @or_match_slice_u8
// CHECK-SAME: (i16 %0, i16 %1)
#[no_mangle]
pub fn or_match_slice_u8(opta: Option<[u8; 1]>, optb: Option<[u8; 1]>) -> Option<[u8; 1]> {
    // CHECK: start:
    // CHECK-DAG: [[SOME_A:%.+]] = trunc i16 {{.*}} to i1
    // CHECK-DAG: select i1 [[SOME_A]], i16 %0, i16 %1
    // CHECK: ret i16 {{.*}}
    match opta {
        Some(x) => Some(x),
        None => optb,
    }
}

// CHECK-LABEL: @or_match_slice_alt_u8
// CHECK-SAME: (i16 %0, i16 %1)
#[no_mangle]
pub fn or_match_slice_alt_u8(opta: Option<[u8; 1]>, optb: Option<[u8; 1]>) -> Option<[u8; 1]> {
    // CHECK: start:
    // CHECK-DAG: [[SOME_A:%.+]] = trunc i16 {{.*}} to i1
    // CHECK-DAG: select i1 [[SOME_A]], i16 %0, i16 %1
    // CHECK: ret i16 {{.*}}
    match opta {
        Some(_) => opta,
        None => optb,
    }
}

// CHECK-LABEL: @option_or_slice_u8
// CHECK-SAME: (i16 %0, i16 %1)
#[no_mangle]
pub fn option_or_slice_u8(opta: Option<[u8; 1]>, optb: Option<[u8; 1]>) -> Option<[u8; 1]> {
    // CHECK: start:

Review comment (bug):
This change to not say what's being returned feels like it's just making it a worse test.  Notably, sure it's passing, but you needed to do this because there's *two* selects in the BE version, and failing if the LE version started doing that is *good* if you ask me.

I think it'd be better to use revisions to make these `LITTLE-NEXT` and add separate `BIG-WHATEVER` checks for the big-endian versions if they're this different.

Code after:
    // CHECK-NEXT: [[FLAG:%.+]] = insertvalue { i1, i8 } poison, i1 [[IS_SOME]], 0
    // CHECK-NEXT: [[R:%.+]] = insertvalue { i1, i8 } [[FLAG]], i8 [[A_OR_B]], 1
    // CHECK: ret { i1, i8 } [[R]]
    opta.or(optb)
}

// CHECK-LABEL: @if_some_u8
// CHECK-SAME: (i1{{.+}}%opta.0, i8 %opta.1, i1{{.+}}%optb.0, i8 %optb.1)
#[no_mangle]
pub fn if_some_u8(opta: Option<u8>, optb: Option<u8>) -> Option<u8> {
    // CHECK: start:
    // CHECK-DAG: [[A_OR_B:%.+]] = select i1 %opta.0, i8 %opta.1, i8 %optb.1
    // CHECK-DAG: [[IS_SOME:%.+]] = or i1 {{%opta.0, %optb.0|%optb.0, %opta.0}}
    // CHECK-NEXT: [[FLAG:%.+]] = insertvalue { i1, i8 } poison, i1 [[IS_SOME]], 0
    // CHECK-NEXT: [[R:%.+]] = insertvalue { i1, i8 } [[FLAG]], i8 [[A_OR_B]], 1
    // CHECK: ret { i1, i8 } [[R]]
    if opta.is_some() { opta } else { optb }
}

// Tests a case where an input is a type that is represented as `BackendRepr::Memory`

// CHECK-LABEL: @or_match_slice_u8
// CHECK-SAME: (i16 %0, i16 %1)
#[no_mangle]
pub fn or_match_slice_u8(opta: Option<[u8; 1]>, optb: Option<[u8; 1]>) -> Option<[u8; 1]> {
    // CHECK: start:
    // LITTLE-NEXT: [[SOME_A:%.+]] = trunc i16 %0 to i1
    // LITTLE-NEXT: [[R:%.+]] = select i1 [[SOME_A]], i16 %0, i16 %1
    // BIG-NEXT: [[OPT_A:%.+]] = lshr i16 %0, 8
    // BIG-NEXT: [[SOME_A:%.+]] = trunc i16 [[OPT_A]] to i1
    // BIG-NEXT: [[OPT_B:%.+]] = lshr i16 %1, 8
    // BIG-NEXT: [[A_OR_B:%.+]] = select i1 [[SOME_A]], i16 [[OPT_A]], i16 [[OPT_B]]
    // BIG-NEXT: [[AGGREGATE:%.+]] = select i1 [[SOME_A]], i16 %0, i16 %1
    // BIG-NEXT: [[R_LOWER:%.+]] = and i16 [[AGGREGATE]], 255
    // BIG-NEXT: [[R_UPPER:%.+]] = shl nuw i16 [[A_OR_B]], 8
    // BIG-NEXT: [[R:%.+]] = or disjoint i16 [[R_UPPER]], [[R_LOWER]]
    // CHECK: ret i16 [[R]]
    match opta {
        Some(x) => Some(x),
        None => optb,
    }
}

// CHECK-LABEL: @or_match_slice_alt_u8
// CHECK-SAME: (i16 %0, i16 %1)
#[no_mangle]
pub fn or_match_slice_alt_u8(opta: Option<[u8; 1]>, optb: Option<[u8; 1]>) -> Option<[u8; 1]> {
    // CHECK: start:
    // LITTLE-NEXT: [[SOME_A:%.+]] = trunc i16 %0 to i1
    // LITTLE-NEXT: [[R:%.+]] = select i1 [[SOME_A]], i16 %0, i16 %1
    // BIG-NEXT: [[OPT_A:%.+]] = lshr i16 %0, 8