| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 6 | |
| ; RUN: opt -S -passes=lower-ifunc < %s | FileCheck %s | |
| target datalayout = "P1" | |
| ; Currently don't support expanding these uses. | |
| @ifunc_used_in_constantinit_as1 = ifunc i32 (double), ptr addrspace(1) @resolver1_in_1 | |
| @constant_init_user_addrspace1 = global ptr addrspace(1) @ifunc_used_in_constantinit_as1 | |
| @ifunc_used_in_constantinit_as1_cast = ifunc i32 (double), ptr @resolver1_in_0 | |
| @constant_init_user_addrspace1_cast = global ptr addrspace(1) addrspacecast (ptr @ifunc_used_in_constantinit_as1_cast to ptr addrspace(1)) | |
| @ifunc_used_in_constantinit_as0_cast = ifunc i32 (double), ptr addrspace(1) @resolver0_in_1 | |
| @constant_init_user_addrspace0_cast = global ptr addrspacecast (ptr addrspace(1) @ifunc_used_in_constantinit_as0_cast to ptr) | |
| @ifunc_as1_resolver_in_0 = ifunc void (), ptr @resolver1_in_0 | |
| @ifunc_as1_resolver_in_1 = ifunc void (), ptr addrspace(1) @resolver1_in_1 | |
| @ifunc_as1_resolver_casted_in_1 = ifunc void (), ptr addrspace(1) addrspacecast (ptr @resolver1_in_0 to ptr addrspace(1)) | |
| define ptr addrspace(1) @resolver1_in_0() addrspace(0) { | |
| ret ptr addrspace(1) inttoptr (i64 123 to ptr addrspace(1)) | |
| } | |
| define ptr addrspace(1) @resolver1_in_1() addrspace(1) { | |
| ret ptr addrspace(1) inttoptr (i64 456 to ptr addrspace(1)) | |
| } | |
| define ptr addrspace(0) @resolver0_in_1() addrspace(1) { | |
| ret ptr addrspace(0) inttoptr (i64 789 to ptr addrspace(0)) | |
| } | |
| define void @call_ifuncs() addrspace(0) { | |
| call addrspace(0) void @ifunc_as1_resolver_in_0() | |
| call addrspace(1) void @ifunc_as1_resolver_in_1() | |
| call addrspace(1) void @ifunc_as1_resolver_casted_in_1() | |
| ret void | |
| } | |
| define void @load_ifuncs() addrspace(0) { | |
| %load0 = load volatile ptr addrspace(1), ptr @constant_init_user_addrspace1 | |
| %load1 = load volatile ptr addrspace(1), ptr @constant_init_user_addrspace1_cast | |
| %load2 = load volatile ptr, ptr @constant_init_user_addrspace0_cast | |
| ret void | |
| } | |
| ;. | |
| ; CHECK: @constant_init_user_addrspace1 = global ptr addrspace(1) @ifunc_used_in_constantinit_as1 | |
| ; CHECK: @constant_init_user_addrspace1_cast = global ptr addrspace(1) addrspacecast (ptr @ifunc_used_in_constantinit_as1_cast to ptr addrspace(1)) | |
| ; CHECK: @constant_init_user_addrspace0_cast = global ptr addrspacecast (ptr addrspace(1) @ifunc_used_in_constantinit_as0_cast to ptr) | |
| ; CHECK: @[[GLOB0:[0-9]+]] = internal global [6 x ptr addrspace(1)] poison, align 8 | |
| ; CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr addrspace(1), ptr }] [{ i32, ptr addrspace(1), ptr } { i32 10, ptr addrspace(1) @[[GLOB1:[0-9]+]], ptr null }] | |
| ; CHECK: @ifunc_used_in_constantinit_as1 = ifunc i32 (double), ptr addrspace(1) @resolver1_in_1 | |
| ; CHECK: @ifunc_used_in_constantinit_as1_cast = ifunc i32 (double), ptr @resolver1_in_0 | |
| ; CHECK: @ifunc_used_in_constantinit_as0_cast = ifunc i32 (double), ptr addrspace(1) @resolver0_in_1 | |
| ;. | |
| ; CHECK-LABEL: define ptr addrspace(1) @resolver1_in_0() addrspace(0) { | |
| ; CHECK-NEXT: ret ptr addrspace(1) inttoptr (i64 123 to ptr addrspace(1)) | |
| ; | |
| ; | |
| ; CHECK-LABEL: define ptr addrspace(1) @resolver1_in_1() addrspace(1) { | |
| ; CHECK-NEXT: ret ptr addrspace(1) inttoptr (i64 456 to ptr addrspace(1)) | |
| ; | |
| ; | |
| ; CHECK-LABEL: define ptr @resolver0_in_1() addrspace(1) { | |
| ; CHECK-NEXT: ret ptr inttoptr (i64 789 to ptr) | |
| ; | |
| ; | |
| ; CHECK-LABEL: define void @call_ifuncs() addrspace(0) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr getelementptr inbounds (i8, ptr @[[GLOB0]], i64 24), align 8 | |
| ; CHECK-NEXT: [[TMP2:%.*]] = addrspacecast ptr addrspace(1) [[TMP1]] to ptr | |
| ; CHECK-NEXT: call addrspace(0) void [[TMP2]]() | |
| ; CHECK-NEXT: [[TMP3:%.*]] = load ptr addrspace(1), ptr getelementptr inbounds (i8, ptr @[[GLOB0]], i64 32), align 8 | |
| ; CHECK-NEXT: call addrspace(1) void [[TMP3]]() | |
| ; CHECK-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr getelementptr inbounds (i8, ptr @[[GLOB0]], i64 40), align 8 | |
| ; CHECK-NEXT: call addrspace(1) void [[TMP4]]() | |
| ; CHECK-NEXT: ret void | |
| ; | |
| ; | |
| ; CHECK-LABEL: define void @load_ifuncs() addrspace(0) { | |
| ; CHECK-NEXT: [[LOAD0:%.*]] = load volatile ptr addrspace(1), ptr @constant_init_user_addrspace1, align 8 | |
| ; CHECK-NEXT: [[LOAD1:%.*]] = load volatile ptr addrspace(1), ptr @constant_init_user_addrspace1_cast, align 8 | |
| ; CHECK-NEXT: [[LOAD2:%.*]] = load volatile ptr, ptr @constant_init_user_addrspace0_cast, align 8 | |
| ; CHECK-NEXT: ret void | |
| ; | |
| ; | |
| ; CHECK-LABEL: define internal void @1() addrspace(1) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = call addrspace(1) ptr addrspace(1) @resolver1_in_1() | |
| ; CHECK-NEXT: store ptr addrspace(1) [[TMP1]], ptr @[[GLOB0]], align 8 | |
| ; CHECK-NEXT: [[TMP2:%.*]] = call addrspace(0) ptr addrspace(1) @resolver1_in_0() | |
| ; CHECK-NEXT: store ptr addrspace(1) [[TMP2]], ptr getelementptr inbounds (i8, ptr @[[GLOB0]], i64 8), align 8 | |
| ; CHECK-NEXT: [[TMP3:%.*]] = call addrspace(1) ptr @resolver0_in_1() | |
| ; CHECK-NEXT: [[TMP4:%.*]] = addrspacecast ptr [[TMP3]] to ptr addrspace(1) | |
| ; CHECK-NEXT: store ptr addrspace(1) [[TMP4]], ptr getelementptr inbounds (i8, ptr @[[GLOB0]], i64 16), align 8 | |
| ; CHECK-NEXT: [[TMP5:%.*]] = call addrspace(0) ptr addrspace(1) @resolver1_in_0() | |
| ; CHECK-NEXT: store ptr addrspace(1) [[TMP5]], ptr getelementptr inbounds (i8, ptr @[[GLOB0]], i64 24), align 8 | |
| ; CHECK-NEXT: [[TMP6:%.*]] = call addrspace(1) ptr addrspace(1) @resolver1_in_1() | |
| ; CHECK-NEXT: store ptr addrspace(1) [[TMP6]], ptr getelementptr inbounds (i8, ptr @[[GLOB0]], i64 32), align 8 | |
| ; CHECK-NEXT: [[TMP7:%.*]] = call addrspace(0) ptr addrspace(1) @resolver1_in_0() | |
| ; CHECK-NEXT: store ptr addrspace(1) [[TMP7]], ptr getelementptr inbounds (i8, ptr @[[GLOB0]], i64 40), align 8 | |
| ; CHECK-NEXT: ret void | |
| ; |