; This file is a part of Julia. License is MIT: https://julialang.org/license ; RUN: opt -enable-new-pm=1 --opaque-pointers=0 --load-pass-plugin=libjulia-codegen%shlibext -passes='function(LateLowerGCFrame,FinalLowerGC)' -S %s | FileCheck %s --check-prefixes=CHECK,TYPED ; RUN: opt -enable-new-pm=1 --opaque-pointers=1 --load-pass-plugin=libjulia-codegen%shlibext -passes='function(LateLowerGCFrame,FinalLowerGC)' -S %s | FileCheck %s --check-prefixes=CHECK,OPAQUE declare void @boxed_simple({} addrspace(10)*, {} addrspace(10)*) declare {} addrspace(10)* @jl_box_int64(i64) declare {}*** @julia.ptls_states() declare {}*** @julia.get_pgcstack() declare void @jl_safepoint() declare {} addrspace(10)* @jl_apply_generic({} addrspace(10)*, {} addrspace(10)**, i32) define void @simple(i64 %a, i64 %b) { top: ; CHECK-LABEL: @simple %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 ; TYPED: call {} addrspace(10)* @jl_box_int64 ; OPAQUE: call ptr addrspace(10) @jl_box_int64 %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) ; TYPED: [[GEP0:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 [[GEPSLOT0:[0-9]+]] ; TYPED-NEXT: store {} addrspace(10)* %aboxed, {} addrspace(10)** [[GEP0]] ; OPAQUE: [[GEP0:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 [[GEPSLOT0:[0-9]+]] ; OPAQUE-NEXT: store ptr addrspace(10) %aboxed, ptr [[GEP0]] %bboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %b) ; CHECK-NEXT: %bboxed = ; Make sure the same gc slot isn't re-used ; TYPED-NOT: getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 [[GEPSLOT0]] ; TYPED: [[GEP1:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 [[GEPSLOT1:[0-9]+]] ; TYPED-NEXT: store {} addrspace(10)* %bboxed, {} addrspace(10)** [[GEP1]] ; OPAQUE-NOT: getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 [[GEPSLOT0]] ; OPAQUE: [[GEP1:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 [[GEPSLOT1:[0-9]+]] ; OPAQUE-NEXT: store ptr addrspace(10) %bboxed, ptr [[GEP1]] ; CHECK-NEXT: call void @boxed_simple call void @boxed_simple({} addrspace(10)* %aboxed, {} addrspace(10)* %bboxed) ret void } define void @leftover_alloca({} addrspace(10)* %a) { ; If this pass encounters an alloca, it'll just sink it into the gcframe, ; relying on mem2reg to catch simple cases such as this earlier ; CHECK-LABEL: @leftover_alloca ; TYPED: %var = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe ; OPAQUE: %var = getelementptr inbounds ptr addrspace(10), ptr %gcframe %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %var = alloca {} addrspace(10)* store {} addrspace(10)* %a, {} addrspace(10)** %var %b = load {} addrspace(10)*, {} addrspace(10)** %var call void @boxed_simple({} addrspace(10)* %a, {} addrspace(10)* %b) ret void } declare {{} addrspace(10)*, i8} @union_ret() declare void @union_arg({{} addrspace(10)*, i8}) define void @simple_union() { ; CHECK-LABEL: @simple_union %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() ; TYPED: %a = call { {} addrspace(10)*, i8 } @union_ret() ; OPAQUE: %a = call { ptr addrspace(10), i8 } @union_ret() %a = call { {} addrspace(10)*, i8 } @union_ret() ; TYPED: [[GEP0:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 [[GEPSLOT0:[0-9]+]] ; TYPED-NEXT: [[EXTRACT:%.*]] = extractvalue { {} addrspace(10)*, i8 } %a, 0 ; TYPED-NEXT: store {} addrspace(10)* [[EXTRACT]], {} addrspace(10)** [[GEP0]] ; OPAQUE: [[GEP0:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 [[GEPSLOT0:[0-9]+]] ; OPAQUE-NEXT: [[EXTRACT:%.*]] = extractvalue { ptr addrspace(10), i8 } %a, 0 ; OPAQUE-NEXT: store ptr addrspace(10) [[EXTRACT]], ptr [[GEP0]] call void @union_arg({{} addrspace(10)*, i8} %a) ret void } declare void @one_arg_boxed({} addrspace(10)*) define void @select_simple(i64 %a, i64 %b) { ; CHECK-LABEL: @select_simple %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) %bboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %b) %cmp = icmp eq i64 %a, %b %selectb = select i1 %cmp, {} addrspace(10)* %aboxed, {} addrspace(10)* %bboxed call void @one_arg_boxed({} addrspace(10)* %selectb) ret void } define void @phi_simple(i64 %a, i64 %b) { top: ; CHECK-LABEL: @phi_simple ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %cmp = icmp eq i64 %a, %b br i1 %cmp, label %alabel, label %blabel alabel: %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) br label %common blabel: %bboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %b) br label %common common: %phi = phi {} addrspace(10)* [ %aboxed, %alabel ], [ %bboxed, %blabel ] ; TYPED: [[GEP:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 2 ; TYPED: store {} addrspace(10)* %phi, {} addrspace(10)** [[GEP]] ; OPAQUE: [[GEP:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 2 ; OPAQUE: store ptr addrspace(10) %phi, ptr [[GEP]] call void @one_arg_boxed({} addrspace(10)* %phi) ret void } declare void @one_arg_decayed(i64 addrspace(12)*) define void @select_lift(i64 %a, i64 %b) { ; CHECK-LABEL: @select_lift ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) %adecayed = addrspacecast {} addrspace(10)* %aboxed to i64 addrspace(12)* %bboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %b) %bdecayed = addrspacecast {} addrspace(10)* %bboxed to i64 addrspace(12)* %cmp = icmp eq i64 %a, %b ; TYPED: %gclift = select i1 %cmp, {} addrspace(10)* %aboxed, {} addrspace(10)* %bboxed ; OPAQUE: %gclift = select i1 %cmp, ptr addrspace(10) %aboxed, ptr addrspace(10) %bboxed %selectb = select i1 %cmp, i64 addrspace(12)* %adecayed, i64 addrspace(12)* %bdecayed call void @one_arg_decayed(i64 addrspace(12)* %selectb) ret void } define void @phi_lift(i64 %a, i64 %b) { top: ; CHECK-LABEL: @phi_lift ; TYPED: %gclift = phi {} addrspace(10)* [ %aboxed, %alabel ], [ %bboxed, %blabel ], [ %gclift, %common ] ; OPAQUE: %gclift = phi ptr addrspace(10) [ %aboxed, %alabel ], [ %bboxed, %blabel ], [ %gclift, %common ] %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %cmp = icmp eq i64 %a, %b br i1 %cmp, label %alabel, label %blabel alabel: %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) %adecayed = addrspacecast {} addrspace(10)* %aboxed to i64 addrspace(12)* br label %common blabel: %bboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %b) %bdecayed = addrspacecast {} addrspace(10)* %bboxed to i64 addrspace(12)* br label %common common: %phi = phi i64 addrspace(12)* [ %adecayed, %alabel ], [ %bdecayed, %blabel ], [ %phi, %common ] call void @one_arg_decayed(i64 addrspace(12)* %phi) br label %common } define void @phi_lift_union(i64 %a, i64 %b) { top: ; CHECK-LABEL: @phi_lift_union %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %cmp = icmp eq i64 %a, %b br i1 %cmp, label %alabel, label %blabel alabel: %u = call { {} addrspace(10)*, i8 } @union_ret() ; TYPED: %aboxed = extractvalue { {} addrspace(10)*, i8 } %u, 0 ; OPAQUE: %aboxed = extractvalue { ptr addrspace(10), i8 } %u, 0 %aboxed = extractvalue { {} addrspace(10)*, i8 } %u, 0 %adecayed = addrspacecast {} addrspace(10)* %aboxed to i64 addrspace(12)* ; CHECK: br label %common br label %common blabel: %bboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %b) %bdecayed = addrspacecast {} addrspace(10)* %bboxed to i64 addrspace(12)* br label %common common: ; TYPED: %gclift = phi {} addrspace(10)* [ %aboxed, %alabel ], [ %bboxed, %blabel ] ; OPAQUE: %gclift = phi ptr addrspace(10) [ %aboxed, %alabel ], [ %bboxed, %blabel ] %phi = phi i64 addrspace(12)* [ %adecayed, %alabel ], [ %bdecayed, %blabel ] call void @one_arg_decayed(i64 addrspace(12)* %phi) ret void } define void @live_if_live_out(i64 %a, i64 %b) { ; CHECK-LABEL: @live_if_live_out top: ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() ; The failure case is failing to realize that `aboxed` is live across the first ; one_arg_boxed safepoint and putting bboxed in the same root slot %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) %bboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %b) call void @one_arg_boxed({} addrspace(10)* %bboxed) br label %succ succ: call void @one_arg_boxed({} addrspace(10)* %aboxed) ret void } ; A ret is a use - make sure the value is kept alive for any intervening ; safepoint define {} addrspace(10)* @ret_use(i64 %a, i64 %b) { ; CHECK-LABEL: @ret_use ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) ; TYPED: store {} addrspace(10)* %aboxed ; OPAQUE: store ptr addrspace(10) %aboxed %bboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %b) ret {} addrspace(10)* %aboxed } define {{} addrspace(10)*, i8} @ret_use_struct() { ; CHECK-LABEL: @ret_use_struct ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() ; TYPED: %aunion = call { {} addrspace(10)*, i8 } @union_ret() ; OPAQUE: %aunion = call { ptr addrspace(10), i8 } @union_ret() %aunion = call { {} addrspace(10)*, i8 } @union_ret() ; TYPED-DAG: [[GEP0:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 [[GEPSLOT0:[0-9]+]] ; TYPED-DAG: [[EXTRACT:%.*]] = extractvalue { {} addrspace(10)*, i8 } %aunion, 0 ; TYPED-NEXT: store {} addrspace(10)* [[EXTRACT]], {} addrspace(10)** [[GEP0]] ; OPAQUE-DAG: [[GEP0:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 [[GEPSLOT0:[0-9]+]] ; OPAQUE-DAG: [[EXTRACT:%.*]] = extractvalue { ptr addrspace(10), i8 } %aunion, 0 ; OPAQUE-NEXT: store ptr addrspace(10) [[EXTRACT]], ptr [[GEP0]] ; CHECK-NEXT: call void @jl_safepoint() call void @jl_safepoint() ret {{} addrspace(10)*, i8} %aunion } define i8 @nosafepoint({} addrspace(10)* dereferenceable(16)) { ; CHECK-LABEL: @nosafepoint ; CHECK-NOT: %gcframe top: %pgcstack = call {}*** @julia.get_pgcstack() %1 = call {}*** @julia.ptls_states() %2 = bitcast {}*** %1 to {} addrspace(10)** %3 = getelementptr {} addrspace(10)*, {} addrspace(10)** %2, i64 3 %4 = bitcast {} addrspace(10)** %3 to i64** %5 = load i64*, i64** %4 %6 = bitcast {} addrspace(10)* %0 to i8 addrspace(10)* %7 = addrspacecast i8 addrspace(10)* %6 to i8 addrspace(11)* %8 = getelementptr i8, i8 addrspace(11)* %7, i64 0 %9 = load i8, i8 addrspace(11)* %8 %10 = trunc i8 %9 to i1 %11 = zext i1 %10 to i8 %12 = xor i8 %11, 1 ret i8 %12 } define void @global_ref() { ; CHECK-LABEL: @global_ref ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %loaded = load {} addrspace(10)*, {} addrspace(10)** getelementptr ({} addrspace(10)*, {} addrspace(10)** inttoptr (i64 140540744325952 to {} addrspace(10)**), i64 1) ; TYPED: store {} addrspace(10)* %loaded, {} addrspace(10)** ; OPAQUE: store ptr addrspace(10) %loaded, ptr call void @one_arg_boxed({} addrspace(10)* %loaded) ret void } define {} addrspace(10)* @no_redundant_rerooting(i64 %a, i1 %cond) { ; CHECK-LABEL: @no_redundant_rerooting ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) ; TYPED: store {} addrspace(10)* %aboxed ; OPAQUE: store ptr addrspace(10) %aboxed ; CHECK-NEXT: call void @jl_safepoint() call void @jl_safepoint() br i1 %cond, label %blocka, label %blockb blocka: ; CHECK-NOT: call void @jl_safepoint() ; CHECK: call void @jl_safepoint() call void @jl_safepoint() ret {} addrspace(10)* %aboxed blockb: ; CHECK-NOT: call void @jl_safepoint() ; CHECK: call void @jl_safepoint() call void @jl_safepoint() ret {} addrspace(10)* %aboxed } declare void @llvm.memcpy.p064.p10i8.i64(i64*, i8 addrspace(10)*, i64, i32, i1) define void @memcpy_use(i64 %a, i64 *%aptr) { ; CHECK-LABEL: @memcpy_use ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) ; TYPED: store {} addrspace(10)* %aboxed ; OPAQUE: store ptr addrspace(10) %aboxed call void @jl_safepoint() %acast = bitcast {} addrspace(10)* %aboxed to i8 addrspace(10)* call void @llvm.memcpy.p064.p10i8.i64(i64* %aptr, i8 addrspace(10)* %acast, i64 8, i32 1, i1 false) ret void } declare token @llvm.julia.gc_preserve_begin(...) declare void @llvm.julia.gc_preserve_end(token) define void @gc_preserve(i64 %a) { ; CHECK-LABEL: @gc_preserve ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) ; TYPED: store {} addrspace(10)* %aboxed ; OPAQUE: store ptr addrspace(10) %aboxed call void @jl_safepoint() %tok = call token (...) @llvm.julia.gc_preserve_begin({} addrspace(10)* %aboxed) %aboxed2 = call {} addrspace(10)* @jl_box_int64(i64 signext %a) ; TYPED: store {} addrspace(10)* %aboxed2 ; OPAQUE: store ptr addrspace(10) %aboxed2 call void @jl_safepoint() call void @llvm.julia.gc_preserve_end(token %tok) %aboxed3 = call {} addrspace(10)* @jl_box_int64(i64 signext %a) ; TYPED: store {} addrspace(10)* %aboxed3 ; OPAQUE: store ptr addrspace(10) %aboxed3 call void @jl_safepoint() call void @one_arg_boxed({} addrspace(10)* %aboxed2) call void @one_arg_boxed({} addrspace(10)* %aboxed3) ret void } define void @gc_preserve_vec([2 x <2 x {} addrspace(10)*>] addrspace(11)* nocapture nonnull readonly dereferenceable(16)) { ; CHECK-LABEL: @gc_preserve_vec ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 6 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 6 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %v = load [2 x <2 x {} addrspace(10)*>], [2 x <2 x {} addrspace(10)*>] addrspace(11)* %0, align 8 ; TYPED-DAG: [[EXTRACT11:%.*]] = extractvalue [2 x <2 x {} addrspace(10)*>] %v, 0 ; TYPED-DAG: [[EXTRACT12:%.*]] = extractvalue [2 x <2 x {} addrspace(10)*>] %v, 0 ; TYPED-DAG: [[EXTRACT21:%.*]] = extractvalue [2 x <2 x {} addrspace(10)*>] %v, 1 ; TYPED-DAG: [[EXTRACT22:%.*]] = extractvalue [2 x <2 x {} addrspace(10)*>] %v, 1 ; TYPED-DAG: [[V11:%.*]] = extractelement <2 x {} addrspace(10)*> [[EXTRACT11]], i32 0 ; TYPED-DAG: [[V12:%.*]] = extractelement <2 x {} addrspace(10)*> [[EXTRACT12]], i32 1 ; TYPED-DAG: [[V21:%.*]] = extractelement <2 x {} addrspace(10)*> [[EXTRACT21]], i32 0 ; TYPED-DAG: [[V22:%.*]] = extractelement <2 x {} addrspace(10)*> [[EXTRACT22]], i32 1 ; TYPED-DAG: store {} addrspace(10)* [[V11]] ; TYPED-DAG: store {} addrspace(10)* [[V12]] ; TYPED-DAG: store {} addrspace(10)* [[V21]] ; TYPED-DAG: store {} addrspace(10)* [[V22]] ; OPAQUE-DAG: [[EXTRACT11:%.*]] = extractvalue [2 x <2 x ptr addrspace(10)>] %v, 0 ; OPAQUE-DAG: [[EXTRACT12:%.*]] = extractvalue [2 x <2 x ptr addrspace(10)>] %v, 0 ; OPAQUE-DAG: [[EXTRACT21:%.*]] = extractvalue [2 x <2 x ptr addrspace(10)>] %v, 1 ; OPAQUE-DAG: [[EXTRACT22:%.*]] = extractvalue [2 x <2 x ptr addrspace(10)>] %v, 1 ; OPAQUE-DAG: [[V11:%.*]] = extractelement <2 x ptr addrspace(10)> [[EXTRACT11]], i32 0 ; OPAQUE-DAG: [[V12:%.*]] = extractelement <2 x ptr addrspace(10)> [[EXTRACT12]], i32 1 ; OPAQUE-DAG: [[V21:%.*]] = extractelement <2 x ptr addrspace(10)> [[EXTRACT21]], i32 0 ; OPAQUE-DAG: [[V22:%.*]] = extractelement <2 x ptr addrspace(10)> [[EXTRACT22]], i32 1 ; OPAQUE-DAG: store ptr addrspace(10) [[V11]] ; OPAQUE-DAG: store ptr addrspace(10) [[V12]] ; OPAQUE-DAG: store ptr addrspace(10) [[V21]] ; OPAQUE-DAG: store ptr addrspace(10) [[V22]] %tok = call token (...) @llvm.julia.gc_preserve_begin([2 x <2 x {} addrspace(10)*>] %v, i64 addrspace(10)* null, {}*** %ptls) call void @jl_safepoint() ret void } @gv1 = external global {}* @gv2 = external global {} addrspace(10)* define {} addrspace(10)* @gv_const() { ; CHECK-LABEL: @gv_const ; CHECK-NOT: %gcframe top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %v10 = load {}*, {}** @gv1, !tbaa !2 %v1 = addrspacecast {}* %v10 to {} addrspace(10)* %v2 = load {} addrspace(10)*, {} addrspace(10)** @gv2, !tbaa !2 call void @jl_safepoint() call void @one_arg_boxed({} addrspace(10)* %v1) call void @one_arg_boxed({} addrspace(10)* %v2) ret {} addrspace(10)* %v1 } define {} addrspace(10)* @vec_jlcallarg({} addrspace(10)*, {} addrspace(10)**, i32) { ; CHECK-LABEL: @vec_jlcallarg ; CHECK-NOT: %gcframe %pgcstack = call {}*** @julia.get_pgcstack() %v4 = call {}*** @julia.ptls_states() %v5 = bitcast {} addrspace(10)** %1 to <2 x {} addrspace(10)*>* %v6 = load <2 x {} addrspace(10)*>, <2 x {} addrspace(10)*>* %v5, align 8 %v7 = extractelement <2 x {} addrspace(10)*> %v6, i32 0 ret {} addrspace(10)* %v7 } declare {} addrspace(10) *@alloc() define {} addrspace(10)* @vec_loadobj() { ; CHECK-LABEL: @vec_loadobj ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 %pgcstack = call {}*** @julia.get_pgcstack() %v4 = call {}*** @julia.ptls_states() %obj = call {} addrspace(10) *@alloc() %v1 = bitcast {} addrspace(10) * %obj to {} addrspace(10)* addrspace(10)* %v5 = bitcast {} addrspace(10)* addrspace(10)* %v1 to <2 x {} addrspace(10)*> addrspace(10)* %v6 = load <2 x {} addrspace(10)*>, <2 x {} addrspace(10)*> addrspace(10)* %v5, align 8 %obj2 = call {} addrspace(10) *@alloc() %v7 = extractelement <2 x {} addrspace(10)*> %v6, i32 0 ret {} addrspace(10)* %v7 } define {} addrspace(10)* @vec_gep() { ; CHECK-LABEL: @vec_gep ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 %pgcstack = call {}*** @julia.get_pgcstack() %v4 = call {}*** @julia.ptls_states() %obj = call {} addrspace(10) *@alloc() %obj1 = bitcast {} addrspace(10) * %obj to {} addrspace(10)* addrspace(10)* %v1 = getelementptr {} addrspace(10)*, {} addrspace(10)* addrspace(10)* %obj1, <2 x i32> < i32 0, i32 0 > call void @jl_safepoint() %obj2 = extractelement <2 x {} addrspace(10)* addrspace(10)*> %v1, i32 0 %obj3 = bitcast {} addrspace(10)* addrspace(10)* %obj2 to {} addrspace(10)* ret {} addrspace(10)* %obj3 } declare i1 @check_property({} addrspace(10)* %val) define void @loopyness(i1 %cond1, {} addrspace(10) *%arg) { ; CHECK-LABEL: @loopyness ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() br label %header header: %phi = phi {} addrspace(10)* [null, %top], [%obj, %latch] br i1 %cond1, label %a, label %latch a: ; This needs a store ; CHECK-LABEL: a: ; TYPED: [[GEP1:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 [[GEPSLOT0:[0-9]+]] ; TYPED: store {} addrspace(10)* %phi, {} addrspace(10)** [[GEP1]] ; OPAQUE: [[GEP1:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 [[GEPSLOT0:[0-9]+]] ; OPAQUE: store ptr addrspace(10) %phi, ptr [[GEP1]] call void @one_arg_boxed({} addrspace(10)* %phi) br label %latch latch: ; This as well in case we went the other path ; TYPED: [[GEP2:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 [[GEPSLOT0]] ; TYPED: store {} addrspace(10)* %phi, {} addrspace(10)** [[GEP2]] ; OPAQUE: [[GEP2:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 [[GEPSLOT0]] ; OPAQUE: store ptr addrspace(10) %phi, ptr [[GEP2]] %obj = call {} addrspace(10)* @alloc() %cond = call i1 @check_property({} addrspace(10)* %phi) br i1 %cond, label %exit, label %header exit: ret void } define {} addrspace(10)* @phi_union(i1 %cond) { ; CHECK-LABEL: @phi_union ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() br i1 %cond, label %a, label %b a: %obj = call {} addrspace(10) *@alloc() %aobj = insertvalue {{} addrspace(10)*, i8} undef, {} addrspace(10)* %obj, 0 %aunion = insertvalue {{} addrspace(10)*, i8} undef, i8 -126, 1 br label %join b: %bunion = call {{} addrspace(10)*, i8} @union_ret() br label %join join: %phi = phi {{} addrspace(10)*, i8} [%aunion, %a], [%bunion, %b] call void @jl_safepoint() %rval = extractvalue { {} addrspace(10)*, i8 } %phi, 0 ret {} addrspace(10)* %rval } define {} addrspace(10)* @select_union(i1 %cond) { ; CHECK-LABEL: @select_union ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %obj = call {} addrspace(10) *@alloc() %aobj = insertvalue {{} addrspace(10)*, i8} undef, {} addrspace(10)* %obj, 0 %aunion = insertvalue {{} addrspace(10)*, i8} undef, i8 -126, 1 %bunion = call {{} addrspace(10)*, i8} @union_ret() %select = select i1 %cond, {{} addrspace(10)*, i8} %aunion, {{} addrspace(10)*, i8} %bunion call void @jl_safepoint() %rval = extractvalue { {} addrspace(10)*, i8 } %select, 0 ret {} addrspace(10)* %rval } define i8 @simple_arrayptr() { ; CHECK-LABEL: @simple_arrayptr ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %obj1 = call {} addrspace(10) *@alloc() %obj2 = call {} addrspace(10) *@alloc() %decayed = addrspacecast {} addrspace(10) *%obj1 to {} addrspace(11) * %arrayptrptr = bitcast {} addrspace(11) *%decayed to i8 addrspace(13)* addrspace(11)* %arrayptr = load i8 addrspace(13)*, i8 addrspace(13)* addrspace(11)* %arrayptrptr call void @jl_safepoint() call void @one_arg_boxed({} addrspace(10) *%obj2) %val = load i8, i8 addrspace(13)* %arrayptr ret i8 %val } define {} addrspace(10)* @vecstoreload(<2 x {} addrspace(10)*> *%arg) { ; CHECK-LABEL: @vecstoreload ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %loaded = load <2 x {} addrspace(10)*>, <2 x {} addrspace(10)*> *%arg call void @jl_safepoint() %obj = call {} addrspace(10) *@alloc() %casted = bitcast {} addrspace(10)* %obj to <2 x {} addrspace(10)*> addrspace(10)* store <2 x {} addrspace(10)*> %loaded, <2 x {} addrspace(10)*> addrspace(10)* %casted ret {} addrspace(10)* %obj } define void @vecphi(i1 %cond, <2 x {} addrspace(10)*> *%arg) { ; CHECK-LABEL: @vecphi ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() br i1 %cond, label %A, label %B A: br label %common B: %loaded = load <2 x {} addrspace(10)*>, <2 x {} addrspace(10)*> *%arg call void @jl_safepoint() br label %common common: %phi = phi <2 x {} addrspace(10)*> [ zeroinitializer, %A ], [ %loaded, %B ] call void @jl_safepoint() %el1 = extractelement <2 x {} addrspace(10)*> %phi, i32 0 %el2 = extractelement <2 x {} addrspace(10)*> %phi, i32 1 call void @one_arg_boxed({} addrspace(10)* %el1) call void @one_arg_boxed({} addrspace(10)* %el2) unreachable } define i8 @phi_arrayptr(i1 %cond) { ; CHECK-LABEL: @phi_arrayptr ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() br i1 %cond, label %A, label %B A: %obj1 = call {} addrspace(10) *@alloc() %obj2 = call {} addrspace(10) *@alloc() %decayed1 = addrspacecast {} addrspace(10) *%obj1 to {} addrspace(11) * %arrayptrptr1 = bitcast {} addrspace(11) *%decayed1 to i8 addrspace(13)* addrspace(11)* %arrayptr1 = load i8 addrspace(13)*, i8 addrspace(13)* addrspace(11)* %arrayptrptr1 %decayed2 = addrspacecast {} addrspace(10) *%obj2 to {} addrspace(11) * %arrayptrptr2 = bitcast {} addrspace(11) *%decayed2 to i8 addrspace(13)* addrspace(11)* %arrayptr2 = load i8 addrspace(13)*, i8 addrspace(13)* addrspace(11)* %arrayptrptr2 %insert1 = insertelement <2 x i8 addrspace(13)*> undef, i8 addrspace(13)* %arrayptr1, i32 0 %insert2 = insertelement <2 x i8 addrspace(13)*> %insert1, i8 addrspace(13)* %arrayptr2, i32 1 call void @jl_safepoint() br label %common B: br label %common common: ; CHECK: %gclift ; CHECK: %gclift1 ; CHECK-NOT: %gclift2 %phi = phi <2 x i8 addrspace(13)*> [ %insert2, %A ], [ zeroinitializer, %B ] call void @jl_safepoint() %el1 = extractelement <2 x i8 addrspace(13)*> %phi, i32 0 %el2 = extractelement <2 x i8 addrspace(13)*> %phi, i32 1 %l1 = load i8, i8 addrspace(13)* %el1 %l2 = load i8, i8 addrspace(13)* %el2 %add = add i8 %l1, %l2 ret i8 %add } define void @vecselect(i1 %cond, <2 x {} addrspace(10)*> *%arg) { ; CHECK-LABEL: @vecselect ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %loaded = load <2 x {} addrspace(10)*>, <2 x {} addrspace(10)*> *%arg call void @jl_safepoint() %select = select i1 %cond, <2 x {} addrspace(10)*> zeroinitializer, <2 x {} addrspace(10)*> %loaded call void @jl_safepoint() %el1 = extractelement <2 x {} addrspace(10)*> %select, i32 0 %el2 = extractelement <2 x {} addrspace(10)*> %select, i32 1 call void @one_arg_boxed({} addrspace(10)* %el1) call void @one_arg_boxed({} addrspace(10)* %el2) unreachable } define void @vecselect_lift(i1 %cond, <2 x {} addrspace(10)*> *%arg) { ; CHECK-LABEL: @vecselect_lift ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %loaded = load <2 x {} addrspace(10)*>, <2 x {} addrspace(10)*> *%arg %decayed = addrspacecast <2 x {} addrspace(10)*> %loaded to <2 x i64 addrspace(12)*> call void @jl_safepoint() ; TYPED: %gclift = select i1 %cond, {} addrspace(10)* null, {} addrspace(10)* %{{[0-9]+}} ; OPAQUE: %gclift = select i1 %cond, ptr addrspace(10) null, ptr addrspace(10) %{{[0-9]+}} %select = select i1 %cond, <2 x i64 addrspace(12)*> zeroinitializer, <2 x i64 addrspace(12)*> %decayed call void @jl_safepoint() %el1 = extractelement <2 x i64 addrspace(12)*> %select, i32 0 %el2 = extractelement <2 x i64 addrspace(12)*> %select, i32 1 call void @one_arg_decayed(i64 addrspace(12)* %el1) call void @one_arg_decayed(i64 addrspace(12)* %el2) unreachable } define void @vecvecselect_lift(<2 x i1> %cond, <2 x {} addrspace(10)*> *%arg) { ; CHECK-LABEL: @vecvecselect_lift ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %loaded = load <2 x {} addrspace(10)*>, <2 x {} addrspace(10)*> *%arg %decayed = addrspacecast <2 x {} addrspace(10)*> %loaded to <2 x i64 addrspace(12)*> call void @jl_safepoint() ; TYPED: %gclift = select i1 %{{[0-9]+}}, {} addrspace(10)* null, {} addrspace(10)* %{{[0-9]+}} ; OPAQUE: %gclift = select i1 %{{[0-9]+}}, ptr addrspace(10) null, ptr addrspace(10) %{{[0-9]+}} %select = select <2 x i1> %cond, <2 x i64 addrspace(12)*> zeroinitializer, <2 x i64 addrspace(12)*> %decayed call void @jl_safepoint() %el1 = extractelement <2 x i64 addrspace(12)*> %select, i32 0 %el2 = extractelement <2 x i64 addrspace(12)*> %select, i32 1 call void @one_arg_decayed(i64 addrspace(12)* %el1) call void @one_arg_decayed(i64 addrspace(12)* %el2) unreachable } define void @vecscalarselect_lift(<2 x i1> %cond, i64 %a) { ; CHECK-LABEL: @vecscalarselect_lift ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) %adecayed = addrspacecast {} addrspace(10)* %aboxed to i64 addrspace(12)* %avec = getelementptr i64, i64 addrspace(12)* %adecayed, <2 x i32> zeroinitializer call void @jl_safepoint() ; TYPED: %gclift = select i1 %{{[0-9]+}}, {} addrspace(10)* null, {} addrspace(10)* %aboxed ; OPAQUE: %gclift = select i1 %{{[0-9]+}}, ptr addrspace(10) null, ptr addrspace(10) %aboxed %select = select <2 x i1> %cond, <2 x i64 addrspace(12)*> zeroinitializer, <2 x i64 addrspace(12)*> %avec call void @jl_safepoint() %el1 = extractelement <2 x i64 addrspace(12)*> %select, i32 0 %el2 = extractelement <2 x i64 addrspace(12)*> %select, i32 1 call void @one_arg_decayed(i64 addrspace(12)* %el1) call void @one_arg_decayed(i64 addrspace(12)* %el2) unreachable } define void @scalarvecselect_lift(i1 %cond, i64 %a) { ; CHECK-LABEL: @scalarvecselect_lift ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %aboxed = call {} addrspace(10)* @jl_box_int64(i64 signext %a) %adecayed = addrspacecast {} addrspace(10)* %aboxed to i64 addrspace(12)* %avec = getelementptr i64, i64 addrspace(12)* %adecayed, <2 x i32> zeroinitializer call void @jl_safepoint() ; TYPED: %gclift = select i1 %cond, {} addrspace(10)* null, {} addrspace(10)* %aboxed ; OPAQUE: %gclift = select i1 %cond, ptr addrspace(10) null, ptr addrspace(10) %aboxed %select = select i1 %cond, <2 x i64 addrspace(12)*> zeroinitializer, <2 x i64 addrspace(12)*> %avec call void @jl_safepoint() %el1 = extractelement <2 x i64 addrspace(12)*> %select, i32 0 %el2 = extractelement <2 x i64 addrspace(12)*> %select, i32 1 call void @one_arg_decayed(i64 addrspace(12)* %el1) call void @one_arg_decayed(i64 addrspace(12)* %el2) unreachable } define i8 @select_arrayptr(i1 %cond) { ; CHECK-LABEL: @select_arrayptr ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 4 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 4 top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %obj1 = call {} addrspace(10) *@alloc() %obj2 = call {} addrspace(10) *@alloc() %decayed1 = addrspacecast {} addrspace(10) *%obj1 to {} addrspace(11) * %arrayptrptr1 = bitcast {} addrspace(11) *%decayed1 to i8 addrspace(13)* addrspace(11)* %arrayptr1 = load i8 addrspace(13)*, i8 addrspace(13)* addrspace(11)* %arrayptrptr1 %decayed2 = addrspacecast {} addrspace(10) *%obj2 to {} addrspace(11) * %arrayptrptr2 = bitcast {} addrspace(11) *%decayed2 to i8 addrspace(13)* addrspace(11)* %arrayptr2 = load i8 addrspace(13)*, i8 addrspace(13)* addrspace(11)* %arrayptrptr2 %insert1 = insertelement <2 x i8 addrspace(13)*> undef, i8 addrspace(13)* %arrayptr1, i32 0 %insert2 = insertelement <2 x i8 addrspace(13)*> %insert1, i8 addrspace(13)* %arrayptr2, i32 1 call void @jl_safepoint() %select = select i1 %cond, <2 x i8 addrspace(13)*> %insert2, <2 x i8 addrspace(13)*> zeroinitializer call void @jl_safepoint() %el1 = extractelement <2 x i8 addrspace(13)*> %select, i32 0 %el2 = extractelement <2 x i8 addrspace(13)*> %select, i32 1 %l1 = load i8, i8 addrspace(13)* %el1 %l2 = load i8, i8 addrspace(13)* %el2 %add = add i8 %l1, %l2 ret i8 %add } define i8 @vector_arrayptrs() { ; CHECK-LABEL: @vector_arrayptrs ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 ; TYPED: [[GEP0:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 2 ; TYPED: store {} addrspace(10)* %obj1, {} addrspace(10)** [[GEP0]] ; OPAQUE: [[GEP0:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 2 ; OPAQUE: store ptr addrspace(10) %obj1, ptr [[GEP0]] ; top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %obj1 = call {} addrspace(10) *@alloc() %decayed = addrspacecast {} addrspace(10) *%obj1 to {} addrspace(11) * %arrayptrptr = bitcast {} addrspace(11) *%decayed to <2 x i8 addrspace(13)*> addrspace(11)* %arrayptrs = load <2 x i8 addrspace(13)*>, <2 x i8 addrspace(13)*> addrspace(11)* %arrayptrptr, align 16 %arrayptr = extractelement <2 x i8 addrspace(13)*> %arrayptrs, i32 0 call void @jl_safepoint() %val = load i8, i8 addrspace(13)* %arrayptr ret i8 %val } declare <2 x i8 addrspace(13)*> @llvm.masked.load.v2p13i8.p11v2p13i8 (<2 x i8 addrspace(13)*> addrspace(11)*, i32, <2 x i1>, <2 x i8 addrspace(13)*>) define i8 @masked_arrayptrs() { ; CHECK-LABEL: @masked_arrayptrs ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 ; TYPED: %arrayptrs = call <2 x i8 addrspace(13)*> @llvm.masked.load.v2p13i8.p11v2p13i8(<2 x i8 addrspace(13)*> addrspace(11)* %arrayptrptr, i32 16, <2 x i1> , <2 x i8 addrspace(13)*> zeroinitializer) ; TYPED: [[GEP0:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 2 ; TYPED: store {} addrspace(10)* %obj1, {} addrspace(10)** [[GEP0]] ; OPAQUE: %arrayptrs = call <2 x ptr addrspace(13)> @llvm.masked.load.v2p13.p11(ptr addrspace(11) %arrayptrptr, i32 16, <2 x i1> , <2 x ptr addrspace(13)> zeroinitializer) ; OPAQUE: [[GEP0:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 2 ; OPAQUE: store ptr addrspace(10) %obj1, ptr [[GEP0]] ; top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %obj1 = call {} addrspace(10) *@alloc() %decayed = addrspacecast {} addrspace(10) *%obj1 to {} addrspace(11) * %arrayptrptr = bitcast {} addrspace(11) *%decayed to <2 x i8 addrspace(13)*> addrspace(11)* %arrayptrs = call <2 x i8 addrspace(13)*> @llvm.masked.load.v2p13i8.p11v2p13i8(<2 x i8 addrspace(13)*> addrspace(11)* %arrayptrptr, i32 16, <2 x i1> , <2 x i8 addrspace(13)*> undef) %arrayptr = extractelement <2 x i8 addrspace(13)*> %arrayptrs, i32 0 call void @jl_safepoint() %val = load i8, i8 addrspace(13)* %arrayptr ret i8 %val } declare <2 x i8 addrspace(13)*> @llvm.masked.gather.v2p13i8.v2p11p13i8 (<2 x i8 addrspace(13)* addrspace(11)*>, i32, <2 x i1>, <2 x i8 addrspace(13)*>) define i8 @gather_arrayptrs() { ; CHECK-LABEL: @gather_arrayptrs ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 ; TYPED: %arrayptrs = call <2 x i8 addrspace(13)*> @llvm.masked.gather.v2p13i8.v2p11p13i8(<2 x i8 addrspace(13)* addrspace(11)*> %arrayptrptrs, i32 16, <2 x i1> , <2 x i8 addrspace(13)*> zeroinitializer) ; TYPED: [[GEP0:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 2 ; TYPED: store {} addrspace(10)* %obj1, {} addrspace(10)** [[GEP0]] ; OPAQUE: %arrayptrs = call <2 x ptr addrspace(13)> @llvm.masked.gather.v2p13.v2p11(<2 x ptr addrspace(11)> %arrayptrptrs, i32 16, <2 x i1> , <2 x ptr addrspace(13)> zeroinitializer) ; OPAQUE: [[GEP0:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 2 ; OPAQUE: store ptr addrspace(10) %obj1, ptr [[GEP0]] ; top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %obj1 = call {} addrspace(10) *@alloc() %decayed = addrspacecast {} addrspace(10) *%obj1 to {} addrspace(11)* %arrayptrptr = bitcast {} addrspace(11) *%decayed to i8 addrspace(13)* addrspace(11)* %arrayptrptrs = insertelement <2 x i8 addrspace(13)* addrspace(11)*> zeroinitializer, i8 addrspace(13)* addrspace(11)* %arrayptrptr, i32 0 %arrayptrs = call <2 x i8 addrspace(13)*> @llvm.masked.gather.v2p13i8.v2p11p13i8(<2 x i8 addrspace(13)* addrspace(11)*> %arrayptrptrs, i32 16, <2 x i1> , <2 x i8 addrspace(13)*> undef) %arrayptr = extractelement <2 x i8 addrspace(13)*> %arrayptrs, i32 0 call void @jl_safepoint() %val = load i8, i8 addrspace(13)* %arrayptr ret i8 %val } define i8 @gather_arrayptrs_alltrue() { ; CHECK-LABEL: @gather_arrayptrs ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 ; TYPED: %arrayptrs = call <2 x i8 addrspace(13)*> @llvm.masked.gather.v2p13i8.v2p11p13i8(<2 x i8 addrspace(13)* addrspace(11)*> %arrayptrptrs, i32 16, <2 x i1> , <2 x i8 addrspace(13)*> zeroinitializer) ; TYPED: [[GEP0:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 2 ; TYPED: store {} addrspace(10)* %obj1, {} addrspace(10)** [[GEP0]] ; OPAQUE: %arrayptrs = call <2 x ptr addrspace(13)> @llvm.masked.gather.v2p13.v2p11(<2 x ptr addrspace(11)> %arrayptrptrs, i32 16, <2 x i1> , <2 x ptr addrspace(13)> zeroinitializer) ; OPAQUE: [[GEP0:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 2 ; OPAQUE: store ptr addrspace(10) %obj1, ptr [[GEP0]] ; top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %obj1 = call {} addrspace(10) *@alloc() %decayed = addrspacecast {} addrspace(10) *%obj1 to {} addrspace(11)* %arrayptrptr = bitcast {} addrspace(11) *%decayed to i8 addrspace(13)* addrspace(11)* %arrayptrptrs = insertelement <2 x i8 addrspace(13)* addrspace(11)*> zeroinitializer, i8 addrspace(13)* addrspace(11)* %arrayptrptr, i32 0 %arrayptrs = call <2 x i8 addrspace(13)*> @llvm.masked.gather.v2p13i8.v2p11p13i8(<2 x i8 addrspace(13)* addrspace(11)*> %arrayptrptrs, i32 16, <2 x i1> , <2 x i8 addrspace(13)*> zeroinitializer) %arrayptr = extractelement <2 x i8 addrspace(13)*> %arrayptrs, i32 0 call void @jl_safepoint() %val = load i8, i8 addrspace(13)* %arrayptr ret i8 %val } define i8 @lost_select_decayed(i1 %arg1) { ; CHECK-LABEL: @lost_select_decayed ; TYPED: %gcframe = alloca {} addrspace(10)*, i32 3 ; OPAQUE: %gcframe = alloca ptr addrspace(10), i32 3 ; TYPED: [[GEP0:%.*]] = getelementptr inbounds {} addrspace(10)*, {} addrspace(10)** %gcframe, i32 2 ; TYPED: store {} addrspace(10)* [[SOMETHING:%.*]], {} addrspace(10)** [[GEP0]] ; OPAQUE: [[GEP0:%.*]] = getelementptr inbounds ptr addrspace(10), ptr %gcframe, i32 2 ; OPAQUE: store ptr addrspace(10) [[SOMETHING:%.*]], ptr [[GEP0]] top: %pgcstack = call {}*** @julia.get_pgcstack() %ptls = call {}*** @julia.ptls_states() %obj1 = call {} addrspace(10) *@alloc() %decayed = addrspacecast {} addrspace(10) *%obj1 to {} addrspace(11)* %selected = select i1 %arg1, {} addrspace(11)* null, {} addrspace(11)* %decayed %casted = bitcast {} addrspace(11)* %selected to i8 addrspace(11)* call void @jl_safepoint() %val = load i8, i8 addrspace(11)* %casted ret i8 %val } !0 = !{!"jtbaa"} !1 = !{!"jtbaa_const", !0, i64 0} !2 = !{!1, !1, i64 0, i64 1}