201 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 52; RUN: llc -mcpu=v2 -mtriple=bpf < %s | FileCheck %s --check-prefixes=CHECK-V23; RUN: llc -mcpu=v4 -mtriple=bpf < %s | FileCheck %s --check-prefixes=CHECK-V44 5; Zero extension instructions should be eliminated at instruction6; selection phase for all test cases below.7 8; In BPF zero extension is implemented as &= or a pair of <<=/>>=9; instructions, hence simply check that &= and >>= do not exist in10; generated code (<<= remains because %c is used by both call and11; lshr in a few test cases).12 13define void @shl_lshr_same_bb(ptr %p) {14; CHECK-V2-LABEL: shl_lshr_same_bb:15; CHECK-V2: # %bb.0: # %entry16; CHECK-V2-NEXT: r1 = *(u8 *)(r1 + 0)17; CHECK-V2-NEXT: r5 = 118; CHECK-V2-NEXT: if r1 == 0 goto LBB0_219; CHECK-V2-NEXT: # %bb.1: # %entry20; CHECK-V2-NEXT: r5 = 021; CHECK-V2-NEXT: LBB0_2: # %entry22; CHECK-V2-NEXT: r3 = r123; CHECK-V2-NEXT: r3 <<= 5624; CHECK-V2-NEXT: r2 = r125; CHECK-V2-NEXT: r4 = r126; CHECK-V2-NEXT: call sink127; CHECK-V2-NEXT: exit28;29; CHECK-V4-LABEL: shl_lshr_same_bb:30; CHECK-V4: # %bb.0: # %entry31; CHECK-V4-NEXT: w1 = *(u8 *)(r1 + 0)32; CHECK-V4-NEXT: w5 = 133; CHECK-V4-NEXT: if w1 == 0 goto LBB0_234; CHECK-V4-NEXT: # %bb.1: # %entry35; CHECK-V4-NEXT: w5 = 036; CHECK-V4-NEXT: LBB0_2: # %entry37; CHECK-V4-NEXT: r3 = r138; CHECK-V4-NEXT: r3 <<= 5639; CHECK-V4-NEXT: r2 = r140; CHECK-V4-NEXT: r4 = r141; CHECK-V4-NEXT: call sink142; CHECK-V4-NEXT: exit43entry:44 %a = load i8, ptr %p, align 145 %b = zext i8 %a to i6446 %c = shl i64 %b, 5647 %d = lshr i64 %c, 5648 %e = icmp eq i64 %d, 049 ; hasOneUse() is a common requirement for many CombineDAG50 ; transofmations, make sure that it does not matter in this case.51 call void @sink1(i8 %a, i64 %b, i64 %c, i64 %d, i1 %e)52 ret void53}54 55define void @shl_lshr_diff_bb(ptr %p) {56; CHECK-V2-LABEL: shl_lshr_diff_bb:57; CHECK-V2: # %bb.0: # %entry58; CHECK-V2-NEXT: r1 = *(u16 *)(r1 + 0)59; CHECK-V2-NEXT: r5 = 160; CHECK-V2-NEXT: if r1 == 0 goto LBB1_261; CHECK-V2-NEXT: # %bb.1: # %entry62; CHECK-V2-NEXT: r5 = 063; CHECK-V2-NEXT: LBB1_2: # %entry64; CHECK-V2-NEXT: r3 = r165; CHECK-V2-NEXT: r3 <<= 4866; CHECK-V2-NEXT: r2 = r167; CHECK-V2-NEXT: r4 = r168; CHECK-V2-NEXT: call sink269; CHECK-V2-NEXT: exit70;71; CHECK-V4-LABEL: shl_lshr_diff_bb:72; CHECK-V4: # %bb.0: # %entry73; CHECK-V4-NEXT: w1 = *(u16 *)(r1 + 0)74; CHECK-V4-NEXT: w5 = 175; CHECK-V4-NEXT: if w1 == 0 goto LBB1_276; CHECK-V4-NEXT: # %bb.1: # %entry77; CHECK-V4-NEXT: w5 = 078; CHECK-V4-NEXT: LBB1_2: # %entry79; CHECK-V4-NEXT: r3 = r180; CHECK-V4-NEXT: r3 <<= 4881; CHECK-V4-NEXT: r2 = r182; CHECK-V4-NEXT: r4 = r183; CHECK-V4-NEXT: call sink284; CHECK-V4-NEXT: exit85entry:86 %a = load i16, ptr %p, align 287 %b = zext i16 %a to i6488 %c = shl i64 %b, 4889 %d = lshr i64 %c, 4890 br label %next91 92; Jump to the new basic block creates a COPY instruction for %d, which93; might be materialized as noop or as AND_ri (zero extension) at the94; start of the basic block. The decision depends on TLI.isZExtFree()95; results, see RegsForValue::getCopyToRegs(). Check below verifies96; that COPY is materialized as noop.97next:98 %e = icmp eq i64 %d, 099 call void @sink2(i16 %a, i64 %b, i64 %c, i64 %d, i1 %e)100 ret void101}102 103define void @load_zext_same_bb(ptr %p) {104; CHECK-V2-LABEL: load_zext_same_bb:105; CHECK-V2: # %bb.0: # %entry106; CHECK-V2-NEXT: r1 = *(u8 *)(r1 + 0)107; CHECK-V2-NEXT: r2 = 1108; CHECK-V2-NEXT: if r1 == 0 goto LBB2_2109; CHECK-V2-NEXT: # %bb.1: # %entry110; CHECK-V2-NEXT: r2 = 0111; CHECK-V2-NEXT: LBB2_2: # %entry112; CHECK-V2-NEXT: call sink3113; CHECK-V2-NEXT: exit114;115; CHECK-V4-LABEL: load_zext_same_bb:116; CHECK-V4: # %bb.0: # %entry117; CHECK-V4-NEXT: w1 = *(u8 *)(r1 + 0)118; CHECK-V4-NEXT: w2 = 1119; CHECK-V4-NEXT: if w1 == 0 goto LBB2_2120; CHECK-V4-NEXT: # %bb.1: # %entry121; CHECK-V4-NEXT: w2 = 0122; CHECK-V4-NEXT: LBB2_2: # %entry123; CHECK-V4-NEXT: call sink3124; CHECK-V4-NEXT: exit125entry:126 %a = load i8, ptr %p, align 1127 ; zext is implicit in this context128 %b = icmp eq i8 %a, 0129 call void @sink3(i8 %a, i1 %b)130 ret void131}132 133define void @load_zext_diff_bb(ptr %p) {134; CHECK-V2-LABEL: load_zext_diff_bb:135; CHECK-V2: # %bb.0: # %entry136; CHECK-V2-NEXT: r1 = *(u8 *)(r1 + 0)137; CHECK-V2-NEXT: r2 = 1138; CHECK-V2-NEXT: if r1 == 0 goto LBB3_2139; CHECK-V2-NEXT: # %bb.1: # %next140; CHECK-V2-NEXT: r2 = 0141; CHECK-V2-NEXT: LBB3_2: # %next142; CHECK-V2-NEXT: call sink3143; CHECK-V2-NEXT: exit144;145; CHECK-V4-LABEL: load_zext_diff_bb:146; CHECK-V4: # %bb.0: # %entry147; CHECK-V4-NEXT: w1 = *(u8 *)(r1 + 0)148; CHECK-V4-NEXT: w2 = 1149; CHECK-V4-NEXT: if w1 == 0 goto LBB3_2150; CHECK-V4-NEXT: # %bb.1: # %next151; CHECK-V4-NEXT: w2 = 0152; CHECK-V4-NEXT: LBB3_2: # %next153; CHECK-V4-NEXT: call sink3154; CHECK-V4-NEXT: exit155entry:156 %a = load i8, ptr %p, align 1157 br label %next158 159next:160 %b = icmp eq i8 %a, 0161 call void @sink3(i8 %a, i1 %b)162 ret void163}164 165define void @load_zext_diff_bb_2(ptr %p) {166; CHECK-V2-LABEL: load_zext_diff_bb_2:167; CHECK-V2: # %bb.0: # %entry168; CHECK-V2-NEXT: r1 = *(u32 *)(r1 + 0)169; CHECK-V2-NEXT: r2 = 1170; CHECK-V2-NEXT: if r1 == 0 goto LBB4_2171; CHECK-V2-NEXT: # %bb.1: # %next172; CHECK-V2-NEXT: r2 = 0173; CHECK-V2-NEXT: LBB4_2: # %next174; CHECK-V2-NEXT: call sink4175; CHECK-V2-NEXT: exit176;177; CHECK-V4-LABEL: load_zext_diff_bb_2:178; CHECK-V4: # %bb.0: # %entry179; CHECK-V4-NEXT: w1 = *(u32 *)(r1 + 0)180; CHECK-V4-NEXT: w2 = 1181; CHECK-V4-NEXT: if w1 == 0 goto LBB4_2182; CHECK-V4-NEXT: # %bb.1: # %next183; CHECK-V4-NEXT: w2 = 0184; CHECK-V4-NEXT: LBB4_2: # %next185; CHECK-V4-NEXT: call sink4186; CHECK-V4-NEXT: exit187entry:188 %a = load i32, ptr %p, align 4189 br label %next190 191next:192 %b = icmp eq i32 %a, 0193 call void @sink4(i32 %a, i1 %b)194 ret void195}196 197declare void @sink1(i8, i64, i64, i64, i1);198declare void @sink2(i16, i64, i64, i64, i1);199declare void @sink3(i8, i1);200declare void @sink4(i32, i1);201