198 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 32; RUN: opt -S -mtriple=amdgcn-- -passes=amdgpu-lower-module-lds < %s | FileCheck %s3 4; Not reached by a non-kernel function and therefore not changed by this pass5@dynamic_kernel_only = external addrspace(3) global [0 x double]6 7; shared8 is used directly by a kernel so remains in the outbout8; the other three are only used by functions and will be replaced with9; table lookups and dropped from the IR10@dynamic_shared1 = external addrspace(3) global [0 x i8], align 111@dynamic_shared2 = external addrspace(3) global [0 x i16], align 212@dynamic_shared4 = external addrspace(3) global [0 x i32], align 413@dynamic_shared8 = external addrspace(3) global [0 x i64], align 814 15; CHECK: %llvm.amdgcn.module.lds.t = type { i32 }16; CHECK: @dynamic_kernel_only = external addrspace(3) global [0 x double]17; CHECK: @dynamic_shared8 = external addrspace(3) global [0 x i64], align 818; CHECK: @llvm.amdgcn.module.lds = internal addrspace(3) global %llvm.amdgcn.module.lds.t poison, align 4, !absolute_symbol !019; CHECK: @llvm.compiler.used = appending addrspace(1) global [1 x ptr] [ptr addrspacecast (ptr addrspace(3) @llvm.amdgcn.module.lds to ptr)], section "llvm.metadata"20 21; Alignment of these must be the maximum of the alignment of the reachable symbols22; CHECK: @llvm.amdgcn.expect_align1.dynlds = external addrspace(3) global [0 x i8], align 1, !absolute_symbol !023; CHECK: @llvm.amdgcn.expect_align2.dynlds = external addrspace(3) global [0 x i8], align 2, !absolute_symbol !024; CHECK: @llvm.amdgcn.expect_align4.dynlds = external addrspace(3) global [0 x i8], align 4, !absolute_symbol !125; CHECK: @llvm.amdgcn.expect_align8.dynlds = external addrspace(3) global [0 x i8], align 8, !absolute_symbol !026 27; Align 4 and symbol at address [4 5) as module.lds is reachable28; CHECK: @llvm.amdgcn.expect_max_of_2_and_4.dynlds = external addrspace(3) global [0 x i8], align 4, !absolute_symbol !129 30; Builds a lookup table out of the newly created (suffixed .dynlds) variables in kernel.id order31; CHECK: @llvm.amdgcn.dynlds.offset.table = internal addrspace(4) constant [5 x i32] [i32 ptrtoint (ptr addrspace(3) @llvm.amdgcn.expect_align1.dynlds to i32), i32 ptrtoint (ptr addrspace(3) @llvm.amdgcn.expect_align2.dynlds to i32), i32 ptrtoint (ptr addrspace(3) @llvm.amdgcn.expect_align4.dynlds to i32), i32 ptrtoint (ptr addrspace(3) @llvm.amdgcn.expect_align8.dynlds to i32), i32 ptrtoint (ptr addrspace(3) @llvm.amdgcn.expect_max_of_2_and_4.dynlds to i32)]32 33 34 35define amdgpu_kernel void @kernel_only() {36; CHECK-LABEL: define amdgpu_kernel void @kernel_only() {37; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x double], ptr addrspace(3) @dynamic_kernel_only, i32 0, i32 038; CHECK-NEXT: store double 3.140000e+00, ptr addrspace(3) [[ARRAYIDX]], align 839; CHECK-NEXT: ret void40;41 %arrayidx = getelementptr inbounds [0 x double], ptr addrspace(3) @dynamic_kernel_only, i32 0, i32 042 store double 3.140000e+00, ptr addrspace(3) %arrayidx43 ret void44}45 46; The accesses from functions are rewritten to go through the llvm.amdgcn.dynlds.offset.table47define void @use_shared1() {48; CHECK-LABEL: define void @use_shared1() {49; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.amdgcn.lds.kernel.id()50; CHECK-NEXT: [[DYNAMIC_SHARED1:%.*]] = getelementptr inbounds [5 x i32], ptr addrspace(4) @llvm.amdgcn.dynlds.offset.table, i32 0, i32 [[TMP1]]51; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(4) [[DYNAMIC_SHARED1]], align 452; CHECK-NEXT: [[DYNAMIC_SHARED11:%.*]] = inttoptr i32 [[TMP2]] to ptr addrspace(3)53; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr addrspace(3) [[DYNAMIC_SHARED11]], i32 0, i32 154; CHECK-NEXT: store i8 0, ptr addrspace(3) [[ARRAYIDX]], align 155; CHECK-NEXT: ret void56;57 %arrayidx = getelementptr inbounds [0 x i8], ptr addrspace(3) @dynamic_shared1, i32 0, i32 158 store i8 0, ptr addrspace(3) %arrayidx59 ret void60}61 62define void @use_shared2() #0 {63; CHECK-LABEL: define void @use_shared2(64; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {65; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.amdgcn.lds.kernel.id()66; CHECK-NEXT: [[DYNAMIC_SHARED2:%.*]] = getelementptr inbounds [5 x i32], ptr addrspace(4) @llvm.amdgcn.dynlds.offset.table, i32 0, i32 [[TMP1]]67; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(4) [[DYNAMIC_SHARED2]], align 468; CHECK-NEXT: [[DYNAMIC_SHARED21:%.*]] = inttoptr i32 [[TMP2]] to ptr addrspace(3)69; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i16], ptr addrspace(3) [[DYNAMIC_SHARED21]], i32 0, i32 370; CHECK-NEXT: store i16 1, ptr addrspace(3) [[ARRAYIDX]], align 271; CHECK-NEXT: ret void72;73 %arrayidx = getelementptr inbounds [0 x i16], ptr addrspace(3) @dynamic_shared2, i32 0, i32 374 store i16 1, ptr addrspace(3) %arrayidx75 ret void76}77 78; Include a normal variable so that the new variables aren't all at the same absolute_symbol79@static_shared = addrspace(3) global i32 poison80define void @use_shared4() #0 {81; CHECK-LABEL: define void @use_shared4(82; CHECK-SAME: ) #[[ATTR0]] {83; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.amdgcn.lds.kernel.id()84; CHECK-NEXT: store i32 4, ptr addrspace(3) @llvm.amdgcn.module.lds, align 485; CHECK-NEXT: [[DYNAMIC_SHARED4:%.*]] = getelementptr inbounds [5 x i32], ptr addrspace(4) @llvm.amdgcn.dynlds.offset.table, i32 0, i32 [[TMP1]]86; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(4) [[DYNAMIC_SHARED4]], align 487; CHECK-NEXT: [[DYNAMIC_SHARED41:%.*]] = inttoptr i32 [[TMP2]] to ptr addrspace(3)88; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr addrspace(3) [[DYNAMIC_SHARED41]], i32 0, i32 589; CHECK-NEXT: store i32 2, ptr addrspace(3) [[ARRAYIDX]], align 490; CHECK-NEXT: ret void91;92 store i32 4, ptr addrspace(3) @static_shared93 %arrayidx = getelementptr inbounds [0 x i32], ptr addrspace(3) @dynamic_shared4, i32 0, i32 594 store i32 2, ptr addrspace(3) %arrayidx95 ret void96}97 98define void @use_shared8() #0 {99; CHECK-LABEL: define void @use_shared8(100; CHECK-SAME: ) #[[ATTR0]] {101; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.amdgcn.lds.kernel.id()102; CHECK-NEXT: [[DYNAMIC_SHARED8:%.*]] = getelementptr inbounds [5 x i32], ptr addrspace(4) @llvm.amdgcn.dynlds.offset.table, i32 0, i32 [[TMP1]]103; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(4) [[DYNAMIC_SHARED8]], align 4104; CHECK-NEXT: [[DYNAMIC_SHARED81:%.*]] = inttoptr i32 [[TMP2]] to ptr addrspace(3)105; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i64], ptr addrspace(3) [[DYNAMIC_SHARED81]], i32 0, i32 7106; CHECK-NEXT: store i64 3, ptr addrspace(3) [[ARRAYIDX]], align 8107; CHECK-NEXT: ret void108;109 %arrayidx = getelementptr inbounds [0 x i64], ptr addrspace(3) @dynamic_shared8, i32 0, i32 7110 store i64 3, ptr addrspace(3) %arrayidx111 ret void112}113 114; The kernels are annotated with kernel.id and llvm.donothing use of the corresponding variable115define amdgpu_kernel void @expect_align1() {116; CHECK-LABEL: define amdgpu_kernel void @expect_align1() !llvm.amdgcn.lds.kernel.id !2 {117; CHECK-NEXT: call void @llvm.donothing() [ "ExplicitUse"(ptr addrspace(3) @llvm.amdgcn.expect_align1.dynlds) ]118; CHECK-NEXT: call void @use_shared1()119; CHECK-NEXT: ret void120;121 call void @use_shared1()122 ret void123}124 125define amdgpu_kernel void @expect_align2() {126; CHECK-LABEL: define amdgpu_kernel void @expect_align2() !llvm.amdgcn.lds.kernel.id !3 {127; CHECK-NEXT: call void @llvm.donothing() [ "ExplicitUse"(ptr addrspace(3) @llvm.amdgcn.expect_align2.dynlds) ]128; CHECK-NEXT: call void @use_shared2()129; CHECK-NEXT: ret void130;131 call void @use_shared2()132 ret void133}134 135define amdgpu_kernel void @expect_align4() {136; CHECK-LABEL: define amdgpu_kernel void @expect_align4(137; CHECK-SAME: ) #[[ATTR1:[0-9]+]] !llvm.amdgcn.lds.kernel.id !4 {138; CHECK-NEXT: call void @llvm.donothing() [ "ExplicitUse"(ptr addrspace(3) @llvm.amdgcn.expect_align4.dynlds) ]139; CHECK-NEXT: call void @llvm.donothing() [ "ExplicitUse"(ptr addrspace(3) @llvm.amdgcn.module.lds) ]140; CHECK-NEXT: call void @use_shared4()141; CHECK-NEXT: ret void142;143 call void @use_shared4()144 ret void145}146 147; Use dynamic_shared directly too.148define amdgpu_kernel void @expect_align8() {149; CHECK-LABEL: define amdgpu_kernel void @expect_align8() !llvm.amdgcn.lds.kernel.id !5 {150; CHECK-NEXT: call void @llvm.donothing() [ "ExplicitUse"(ptr addrspace(3) @llvm.amdgcn.expect_align8.dynlds) ]151; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i64], ptr addrspace(3) @dynamic_shared8, i32 0, i32 9152; CHECK-NEXT: store i64 3, ptr addrspace(3) [[ARRAYIDX]], align 8153; CHECK-NEXT: call void @use_shared8()154; CHECK-NEXT: ret void155;156 %arrayidx = getelementptr inbounds [0 x i64], ptr addrspace(3) @dynamic_shared8, i32 0, i32 9157 store i64 3, ptr addrspace(3) %arrayidx158 call void @use_shared8()159 ret void160}161 162; Note: use_shared4 uses module.lds so this will allocate at offset 4163define amdgpu_kernel void @expect_max_of_2_and_4() {164; CHECK-LABEL: define amdgpu_kernel void @expect_max_of_2_and_4(165; CHECK-SAME: ) #[[ATTR1]] !llvm.amdgcn.lds.kernel.id !6 {166; CHECK-NEXT: call void @llvm.donothing() [ "ExplicitUse"(ptr addrspace(3) @llvm.amdgcn.expect_max_of_2_and_4.dynlds) ]167; CHECK-NEXT: call void @llvm.donothing() [ "ExplicitUse"(ptr addrspace(3) @llvm.amdgcn.module.lds) ]168; CHECK-NEXT: call void @use_shared2()169; CHECK-NEXT: call void @use_shared4()170; CHECK-NEXT: ret void171;172 call void @use_shared2()173 call void @use_shared4()174 ret void175}176 177 178attributes #0 = { noinline }179 180; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none)181; CHECK: declare void @llvm.donothing() #2182 183; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)184; CHECK: declare noundef i32 @llvm.amdgcn.lds.kernel.id() #3185 186; CHECK: attributes #0 = { noinline }187; CHECK: attributes #1 = { "amdgpu-lds-size"="4,4" }188; CHECK: attributes #2 = { nocallback nofree nosync nounwind willreturn memory(none) }189; CHECK: attributes #3 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }190 191; CHECK: !0 = !{i32 0, i32 1}192; CHECK: !1 = !{i32 4, i32 5}193; CHECK: !2 = !{i32 0}194; CHECK: !3 = !{i32 1}195; CHECK: !4 = !{i32 2}196; CHECK: !5 = !{i32 3}197; CHECK: !6 = !{i32 4}198