1; RUN: llc -mcpu=v2 -mtriple=bpf < %s | FileCheck %s 2; RUN: llc -mcpu=v4 -mtriple=bpf < %s | FileCheck %s 3 4; Zero extension instructions should be eliminated at instruction 5; selection phase for all test cases below. 6 7; In BPF zero extension is implemented as &= or a pair of <<=/>>= 8; instructions, hence simply check that &= and >>= do not exist in 9; generated code (<<= remains because %c is used by both call and 10; lshr in a few test cases). 11 12; CHECK-NOT: &= 13; CHECK-NOT: >>= 14 15define void @shl_lshr_same_bb(ptr %p) { 16entry: 17 %a = load i8, ptr %p, align 1 18 %b = zext i8 %a to i64 19 %c = shl i64 %b, 56 20 %d = lshr i64 %c, 56 21 %e = icmp eq i64 %d, 0 22 ; hasOneUse() is a common requirement for many CombineDAG 23 ; transofmations, make sure that it does not matter in this case. 24 call void @sink1(i8 %a, i64 %b, i64 %c, i64 %d, i1 %e) 25 ret void 26} 27 28define void @shl_lshr_diff_bb(ptr %p) { 29entry: 30 %a = load i16, ptr %p, align 2 31 %b = zext i16 %a to i64 32 %c = shl i64 %b, 48 33 %d = lshr i64 %c, 48 34 br label %next 35 36; Jump to the new basic block creates a COPY instruction for %d, which 37; might be materialized as noop or as AND_ri (zero extension) at the 38; start of the basic block. The decision depends on TLI.isZExtFree() 39; results, see RegsForValue::getCopyToRegs(). Check below verifies 40; that COPY is materialized as noop. 41next: 42 %e = icmp eq i64 %d, 0 43 call void @sink2(i16 %a, i64 %b, i64 %c, i64 %d, i1 %e) 44 ret void 45} 46 47define void @load_zext_same_bb(ptr %p) { 48entry: 49 %a = load i8, ptr %p, align 1 50 ; zext is implicit in this context 51 %b = icmp eq i8 %a, 0 52 call void @sink3(i8 %a, i1 %b) 53 ret void 54} 55 56define void @load_zext_diff_bb(ptr %p) { 57entry: 58 %a = load i8, ptr %p, align 1 59 br label %next 60 61next: 62 %b = icmp eq i8 %a, 0 63 call void @sink3(i8 %a, i1 %b) 64 ret void 65} 66 67define void @load_zext_diff_bb_2(ptr %p) { 68entry: 69 %a = load i32, ptr %p, align 4 70 br label %next 71 72next: 73 %b = icmp eq i32 %a, 0 74 call void @sink4(i32 %a, i1 %b) 75 ret void 76} 77 78declare void @sink1(i8, i64, i64, i64, i1); 79declare void @sink2(i16, i64, i64, i64, i1); 80declare void @sink3(i8, i1); 81declare void @sink4(i32, i1); 82