; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6 ; RUN: llubi --verbose < %s 2>&1 | FileCheck %s target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" %struct = type { [2 x i16], i64 } %struct.packed = type <{ [2 x i16], i64 }> %struct.vscale = type { , } define void @main() { %alloc = alloca i32 store i32 u0x00010203, ptr %alloc %val1 = load i32, ptr %alloc %val2 = load i32, ptr %alloc, align 2 %gep = getelementptr i8, ptr %alloc, i64 1 %val3 = load i8, ptr %gep %val4 = load <4 x i8>, ptr %alloc store i16 u0x0405, ptr %gep, align 1 %val5 = load <4 x i8>, ptr %alloc store <2 x i16> , ptr %alloc %val6 = load <4 x i8>, ptr %alloc %val7 = load <8 x i4>, ptr %alloc store <3 x i3> , ptr %alloc ; padding bits are undefined. %val8 = load <16 x i1>, ptr %alloc %val9 = load <16 x i1>, ptr %alloc store <8 x i3> , ptr %alloc %val_bitcast = load <3 x i8>, ptr %alloc ; For non-byte-sized types, the padding bits must be zero. store i25 -1, ptr %alloc %val10 = load <4 x i8>, ptr %alloc store i8 -1, ptr %alloc ; If the padding bits were not zero, load yields poison value. %val11 = load i25, ptr %alloc call void @llvm.lifetime.start.p0(ptr poison) call void @llvm.lifetime.end.p0(ptr poison) %alloc_lifetime = alloca i32 ; Load of an dead object yields poison value. %val12 = load i32, ptr %alloc_lifetime call void @llvm.lifetime.start.p0(ptr %alloc_lifetime) ; After lifetime.start, the object is alive but uninitialized. %val13 = load i32, ptr %alloc_lifetime %val14 = load i32, ptr %alloc_lifetime store i32 77, ptr %alloc_lifetime %val15 = load i32, ptr %alloc_lifetime ; Calling lifetime.start on an alive object makes the contents uninitialized again. call void @llvm.lifetime.start.p0(ptr %alloc_lifetime) %val_undef1 = load i32, ptr %alloc_lifetime %val_undef2 = load i32, ptr %alloc_lifetime call void @llvm.lifetime.end.p0(ptr %alloc_lifetime) ; Calling lifetime.end on an already dead object is a no-op. call void @llvm.lifetime.end.p0(ptr %alloc_lifetime) ; Load of an dead object yields poison value. %val16 = load i32, ptr %alloc_lifetime store i32 u0xFFF80000, ptr %alloc %val17 = load float, ptr %alloc %alloc_vscale = alloca %insert = insertelement poison, i32 1, i32 0 %ones = shufflevector %insert, poison, zeroinitializer %twos = add %ones, %ones store %ones, ptr %alloc_vscale %gep3 = getelementptr , ptr %alloc_vscale, i64 1 store %twos, ptr %gep3 %val18 = load , ptr %alloc_vscale %alloc_struct = alloca %struct store %struct { [2 x i16] [i16 1, i16 2], i64 3 }, ptr %alloc_struct %val19 = load %struct, ptr %alloc_struct ; Padding bytes of struct are undefined. %val20 = load i64, ptr %alloc_struct %val21 = load i64, ptr %alloc_struct %alloc_struct_packed = alloca %struct.packed store %struct.packed <{ [2 x i16] [i16 1, i16 2], i64 3 }>, ptr %alloc_struct_packed %val22 = load %struct.packed, ptr %alloc_struct_packed ; No padding bytes. %val23 = load i64, ptr %alloc_struct_packed %val24 = load i64, ptr %alloc_struct_packed %alloc_struct_vscale = alloca %struct.vscale store %struct.vscale zeroinitializer, ptr %alloc_struct_vscale %gep4 = getelementptr , ptr %alloc_struct_vscale, i32 1 store %ones, ptr %gep4 %val25 = load %struct.vscale, ptr %alloc_struct_vscale %alloc_array = alloca [2 x i32] store [2 x i32] [i32 1, i32 2], ptr %alloc_array %val26 = load [2 x i32], ptr %alloc_array %alloc_i1_vec = alloca <4 x i1> store <4 x i1> , ptr %alloc_i1_vec %val27 = load <4 x i1>, ptr %alloc_i1_vec %val28 = load i8, ptr %alloc_i1_vec %alloc_padding = alloca i31 store i32 0, ptr %alloc_padding %alloc_padding_vec = alloca i64 store { <6 x i5>, i32 } { <6 x i5> zeroinitializer, i32 -1}, ptr %alloc_padding_vec %load_agg = load { <6 x i5>, i32 }, ptr %alloc_padding_vec %load_vec = load <6 x i5>, ptr %alloc_padding_vec %load_int_non_zero_padding = load i33, ptr %alloc_padding_vec %load_vec_non_zero_padding = load <3 x i11>, ptr %alloc_padding_vec %alloc_struct_padding = alloca {i8, i32} store {i8, i32} zeroinitializer, ptr %alloc_struct_padding %load_struct_noundef = load {i8, i32}, ptr %alloc_struct_padding, !noundef !{} %alloc_ptr = alloca ptr store ptr %alloc_ptr, ptr %alloc_ptr ; It should recover the provenance. %ptr_with_provenance = load ptr, ptr %alloc_ptr %addr_bits = load i8, ptr %alloc_ptr store i8 %addr_bits, ptr %alloc_ptr ; The first byte is tainted. We cannot recover the provenance. %ptr_without_provenance = load ptr, ptr %alloc_ptr ret void } ; CHECK: Entering function: main ; CHECK-NEXT: %alloc = alloca i32, align 4 => ptr 0x8 [alloc] ; CHECK-NEXT: store i32 66051, ptr %alloc, align 4 ; CHECK-NEXT: %val1 = load i32, ptr %alloc, align 4 => i32 66051 ; CHECK-NEXT: %val2 = load i32, ptr %alloc, align 2 => i32 66051 ; CHECK-NEXT: %gep = getelementptr i8, ptr %alloc, i64 1 => ptr 0x9 [alloc + 1] ; CHECK-NEXT: %val3 = load i8, ptr %gep, align 1 => i8 1 ; CHECK-NEXT: %val4 = load <4 x i8>, ptr %alloc, align 4 => { i8 0, i8 1, i8 2, i8 3 } ; CHECK-NEXT: store i16 1029, ptr %gep, align 1 ; CHECK-NEXT: %val5 = load <4 x i8>, ptr %alloc, align 4 => { i8 0, i8 4, i8 5, i8 3 } ; CHECK-NEXT: store <2 x i16> , ptr %alloc, align 4 ; CHECK-NEXT: %val6 = load <4 x i8>, ptr %alloc, align 4 => { i8 6, i8 7, i8 8, i8 9 } ; CHECK-NEXT: %val7 = load <8 x i4>, ptr %alloc, align 4 => { i4 0, i4 6, i4 0, i4 7, i4 0, i4 -8, i4 0, i4 -7 } ; CHECK-NEXT: store <3 x i3> , ptr %alloc, align 2 ; CHECK-NEXT: %val8 = load <16 x i1>, ptr %alloc, align 2 => { F, F, F, F, F, F, F, F, F, T, F, T, F, F, T, T } ; CHECK-NEXT: %val9 = load <16 x i1>, ptr %alloc, align 2 => { F, F, F, F, F, F, F, F, F, T, F, T, F, F, T, T } ; CHECK-NEXT: store <8 x i3> , ptr %alloc, align 4 ; CHECK-NEXT: %val_bitcast = load <3 x i8>, ptr %alloc, align 4 => { i8 5, i8 57, i8 119 } ; CHECK-NEXT: store i25 -1, ptr %alloc, align 4 ; CHECK-NEXT: %val10 = load <4 x i8>, ptr %alloc, align 4 => { i8 1, i8 -1, i8 -1, i8 -1 } ; CHECK-NEXT: store i8 -1, ptr %alloc, align 1 ; CHECK-NEXT: %val11 = load i25, ptr %alloc, align 4 => poison ; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr poison) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr poison) ; CHECK-NEXT: %alloc_lifetime = alloca i32, align 4 => ptr 0xC [alloc_lifetime (dead)] ; CHECK-NEXT: %val12 = load i32, ptr %alloc_lifetime, align 4 => poison ; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr %alloc_lifetime) ; CHECK-NEXT: %val13 = load i32, ptr %alloc_lifetime, align 4 => i32 -289830082 ; CHECK-NEXT: %val14 = load i32, ptr %alloc_lifetime, align 4 => i32 -399511892 ; CHECK-NEXT: store i32 77, ptr %alloc_lifetime, align 4 ; CHECK-NEXT: %val15 = load i32, ptr %alloc_lifetime, align 4 => i32 77 ; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr %alloc_lifetime) ; CHECK-NEXT: %val_undef1 = load i32, ptr %alloc_lifetime, align 4 => i32 -132966042 ; CHECK-NEXT: %val_undef2 = load i32, ptr %alloc_lifetime, align 4 => i32 1094190734 ; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr %alloc_lifetime) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr %alloc_lifetime) ; CHECK-NEXT: %val16 = load i32, ptr %alloc_lifetime, align 4 => poison ; CHECK-NEXT: store i32 -524288, ptr %alloc, align 4 ; CHECK-NEXT: %val17 = load float, ptr %alloc, align 4 => float 0xFFF80000 ; CHECK-NEXT: %alloc_vscale = alloca , align 8 => ptr 0x10 [alloc_vscale] ; CHECK-NEXT: %insert = insertelement poison, i32 1, i32 0 => { i32 1, poison, poison, poison } ; CHECK-NEXT: %ones = shufflevector %insert, poison, zeroinitializer => { i32 1, i32 1, i32 1, i32 1 } ; CHECK-NEXT: %twos = add %ones, %ones => { i32 2, i32 2, i32 2, i32 2 } ; CHECK-NEXT: store %ones, ptr %alloc_vscale, align 4 ; CHECK-NEXT: %gep3 = getelementptr , ptr %alloc_vscale, i64 1 => ptr 0x20 [alloc_vscale + 16] ; CHECK-NEXT: store %twos, ptr %gep3, align 4 ; CHECK-NEXT: %val18 = load , ptr %alloc_vscale, align 8 => { i32 1, i32 1, i32 1, i32 1, i32 2, i32 2, i32 2, i32 2 } ; CHECK-NEXT: %alloc_struct = alloca %struct, align 8 => ptr 0x30 [alloc_struct] ; CHECK-NEXT: store %struct { [2 x i16] [i16 1, i16 2], i64 3 }, ptr %alloc_struct, align 8 ; CHECK-NEXT: %val19 = load %struct, ptr %alloc_struct, align 8 => { { i16 1, i16 2 }, i64 3 } ; CHECK-NEXT: %val20 = load i64, ptr %alloc_struct, align 8 => i64 281486191577587 ; CHECK-NEXT: %val21 = load i64, ptr %alloc_struct, align 8 => i64 281486962127119 ; CHECK-NEXT: %alloc_struct_packed = alloca %struct.packed, align 8 => ptr 0x40 [alloc_struct_packed] ; CHECK-NEXT: store %struct.packed <{ [2 x i16] [i16 1, i16 2], i64 3 }>, ptr %alloc_struct_packed, align 1 ; CHECK-NEXT: %val22 = load %struct.packed, ptr %alloc_struct_packed, align 1 => { { i16 1, i16 2 }, i64 3 } ; CHECK-NEXT: %val23 = load i64, ptr %alloc_struct_packed, align 8 => i64 281483566645248 ; CHECK-NEXT: %val24 = load i64, ptr %alloc_struct_packed, align 8 => i64 281483566645248 ; CHECK-NEXT: %alloc_struct_vscale = alloca %struct.vscale, align 8 => ptr 0x50 [alloc_struct_vscale] ; CHECK-NEXT: store %struct.vscale zeroinitializer, ptr %alloc_struct_vscale, align 4 ; CHECK-NEXT: %gep4 = getelementptr , ptr %alloc_struct_vscale, i32 1 => ptr 0x60 [alloc_struct_vscale + 16] ; CHECK-NEXT: store %ones, ptr %gep4, align 4 ; CHECK-NEXT: %val25 = load %struct.vscale, ptr %alloc_struct_vscale, align 4 => { { i32 0, i32 0, i32 0, i32 0 }, { i32 1, i32 1, i32 1, i32 1 } } ; CHECK-NEXT: %alloc_array = alloca [2 x i32], align 4 => ptr 0x70 [alloc_array] ; CHECK-NEXT: store [2 x i32] [i32 1, i32 2], ptr %alloc_array, align 4 ; CHECK-NEXT: %val26 = load [2 x i32], ptr %alloc_array, align 4 => { i32 1, i32 2 } ; CHECK-NEXT: %alloc_i1_vec = alloca <4 x i1>, align 1 => ptr 0x78 [alloc_i1_vec] ; CHECK-NEXT: store <4 x i1> , ptr %alloc_i1_vec, align 1 ; CHECK-NEXT: %val27 = load <4 x i1>, ptr %alloc_i1_vec, align 1 => { T, F, poison, F } ; CHECK-NEXT: %val28 = load i8, ptr %alloc_i1_vec, align 1 => poison ; CHECK-NEXT: %alloc_padding = alloca i31, align 4 => ptr 0x7C [alloc_padding] ; CHECK-NEXT: store i32 0, ptr %alloc_padding, align 4 ; CHECK-NEXT: %alloc_padding_vec = alloca i64, align 8 => ptr 0x80 [alloc_padding_vec] ; CHECK-NEXT: store { <6 x i5>, i32 } { <6 x i5> zeroinitializer, i32 -1 }, ptr %alloc_padding_vec, align 4 ; CHECK-NEXT: %load_agg = load { <6 x i5>, i32 }, ptr %alloc_padding_vec, align 4 => { { i5 0, i5 0, i5 0, i5 0, i5 0, i5 0 }, i32 -1 } ; CHECK-NEXT: %load_vec = load <6 x i5>, ptr %alloc_padding_vec, align 4 => { i5 0, i5 0, i5 0, i5 0, i5 0, i5 0 } ; CHECK-NEXT: %load_int_non_zero_padding = load i33, ptr %alloc_padding_vec, align 8 => i33 255 ; CHECK-NEXT: %load_vec_non_zero_padding = load <3 x i11>, ptr %alloc_padding_vec, align 8 => { i11 0, i11 0, i11 255 } ; CHECK-NEXT: %alloc_struct_padding = alloca { i8, i32 }, align 8 => ptr 0x88 [alloc_struct_padding] ; CHECK-NEXT: store { i8, i32 } zeroinitializer, ptr %alloc_struct_padding, align 4 ; CHECK-NEXT: %load_struct_noundef = load { i8, i32 }, ptr %alloc_struct_padding, align 4, !noundef !0 => { i8 0, i32 0 } ; CHECK-NEXT: %alloc_ptr = alloca ptr, align 8 => ptr 0x90 [alloc_ptr] ; CHECK-NEXT: store ptr %alloc_ptr, ptr %alloc_ptr, align 8 ; CHECK-NEXT: %ptr_with_provenance = load ptr, ptr %alloc_ptr, align 8 => ptr 0x90 [alloc_ptr] ; CHECK-NEXT: %addr_bits = load i8, ptr %alloc_ptr, align 1 => i8 0 ; CHECK-NEXT: store i8 %addr_bits, ptr %alloc_ptr, align 1 ; CHECK-NEXT: %ptr_without_provenance = load ptr, ptr %alloc_ptr, align 8 => ptr 0x90 [nullary] ; CHECK-NEXT: ret void ; CHECK-NEXT: Exiting function: main