314 lines · plain
1// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s2 3llvm.func @foo()4 5// CHECK-LABEL: @omp_teams_simple6// CHECK: call void {{.*}} @__kmpc_fork_teams(ptr @{{.+}}, i32 0, ptr [[OUTLINED_FN:.+]])7// CHECK: ret void8llvm.func @omp_teams_simple() {9 omp.teams {10 llvm.call @foo() : () -> ()11 omp.terminator12 }13 llvm.return14}15 16// CHECK: define internal void @[[OUTLINED_FN:.+]](ptr {{.+}}, ptr {{.+}})17// CHECK: call void @foo()18// CHECK: ret void19 20// -----21 22llvm.func @foo()23 24// CHECK-LABEL: @omp_teams_func_attrs25// CHECK: call void {{.*}} @__kmpc_fork_teams(ptr @{{.+}}, i32 0, ptr @[[OUTLINED_FN:.+]])26llvm.func @omp_teams_func_attrs() attributes {27 target_cpu = "x86-64",28 target_features = #llvm.target_features<["+mmx", "+sse"]>29} {30 omp.teams {31 llvm.call @foo() : () -> ()32 omp.terminator33 }34 llvm.return35}36 37// CHECK: define internal void @[[OUTLINED_FN]](ptr {{.+}}, ptr {{.+}})38// CHECK-SAME: #[[ATTR:[0-9]+]]39// CHECK: call void @foo()40 41// CHECK: attributes #[[ATTR]] = {42// CHECK-SAME: "target-cpu"="x86-64"43// CHECK-SAME: "target-features"="+mmx,+sse"44 45// -----46 47llvm.func @foo(i32) -> ()48 49// CHECK-LABEL: @omp_teams_shared_simple50// CHECK-SAME: (i32 [[ARG0:%.+]])51// CHECK: [[STRUCT_ARG:%.+]] = alloca { i32 }52// CHECK: br53// CHECK: [[GEP:%.+]] = getelementptr { i32 }, ptr [[STRUCT_ARG]], i32 0, i32 054// CHECK: store i32 [[ARG0]], ptr [[GEP]]55// CHECK: call void {{.+}} @__kmpc_fork_teams(ptr @{{.+}}, i32 1, ptr [[OUTLINED_FN:.+]], ptr [[STRUCT_ARG]])56// CHECK: ret void57llvm.func @omp_teams_shared_simple(%arg0: i32) {58 omp.teams {59 llvm.call @foo(%arg0) : (i32) -> ()60 omp.terminator61 }62 llvm.return63}64 65// CHECK: define internal void [[OUTLINED_FN:@.+]](ptr {{.+}}, ptr {{.+}}, ptr [[STRUCT_ARG:%.+]])66// CHECK: [[GEP:%.+]] = getelementptr { i32 }, ptr [[STRUCT_ARG]], i32 0, i32 067// CHECK: [[LOAD_GEP:%.+]] = load i32, ptr [[GEP]]68// CHECK: call void @foo(i32 [[LOAD_GEP]])69// CHECK: ret void70 71// -----72 73llvm.func @my_alloca_fn() -> !llvm.ptr74llvm.func @foo(i32, f32, !llvm.ptr, f128, !llvm.ptr, i32) -> ()75llvm.func @bar()76 77// CHECK-LABEL: @omp_teams_branching_shared78// CHECK-SAME: (i1 [[CONDITION:%.+]], i32 [[ARG0:%.+]], float [[ARG1:%.+]], ptr [[ARG2:%.+]], fp128 [[ARG3:%.+]])79 80// Checking that the allocation for struct argument happens in the alloca block.81// CHECK: [[STRUCT_ARG:%.+]] = alloca { i1, i32, float, ptr, fp128, ptr, i32 }82// CHECK: [[ALLOCATED:%.+]] = call ptr @my_alloca_fn()83// CHECK: [[LOADED:%.+]] = load i32, ptr [[ALLOCATED]]84// CHECK: br label85 86// Checking that the shared values are stored properly in the struct arg.87// CHECK: [[CONDITION_PTR:%.+]] = getelementptr {{.+}}, ptr [[STRUCT_ARG]]88// CHECK: store i1 [[CONDITION]], ptr [[CONDITION_PTR]]89// CHECK: [[ARG0_PTR:%.+]] = getelementptr {{.+}}, ptr [[STRUCT_ARG]], i32 0, i32 190// CHECK: store i32 [[ARG0]], ptr [[ARG0_PTR]]91// CHECK: [[ARG1_PTR:%.+]] = getelementptr {{.+}}, ptr [[STRUCT_ARG]], i32 0, i32 292// CHECK: store float [[ARG1]], ptr [[ARG1_PTR]]93// CHECK: [[ARG2_PTR:%.+]] = getelementptr {{.+}}, ptr [[STRUCT_ARG]], i32 0, i32 394// CHECK: store ptr [[ARG2]], ptr [[ARG2_PTR]]95// CHECK: [[ARG3_PTR:%.+]] = getelementptr {{.+}}, ptr [[STRUCT_ARG]], i32 0, i32 496// CHECK: store fp128 [[ARG3]], ptr [[ARG3_PTR]]97// CHECK: [[ALLOCATED_PTR:%.+]] = getelementptr {{.+}}, ptr [[STRUCT_ARG]], i32 0, i32 598// CHECK: store ptr [[ALLOCATED]], ptr [[ALLOCATED_PTR]]99// CHECK: [[LOADED_PTR:%.+]] = getelementptr {{.+}}, ptr [[STRUCT_ARG]], i32 0, i32 6100// CHECK: store i32 [[LOADED]], ptr [[LOADED_PTR]]101 102// Runtime call.103// CHECK: call void {{.+}} @__kmpc_fork_teams(ptr @{{.+}}, i32 1, ptr [[OUTLINED_FN:@.+]], ptr [[STRUCT_ARG]])104// CHECK: br label105// CHECK: call void @bar()106// CHECK: ret void107llvm.func @omp_teams_branching_shared(%condition: i1, %arg0: i32, %arg1: f32, %arg2: !llvm.ptr, %arg3: f128) {108 %allocated = llvm.call @my_alloca_fn(): () -> !llvm.ptr109 %loaded = llvm.load %allocated : !llvm.ptr -> i32110 llvm.br ^codegenBlock111^codegenBlock:112 omp.teams {113 llvm.cond_br %condition, ^true_block, ^false_block114 ^true_block:115 llvm.call @foo(%arg0, %arg1, %arg2, %arg3, %allocated, %loaded) : (i32, f32, !llvm.ptr, f128, !llvm.ptr, i32) -> ()116 llvm.br ^exit117 ^false_block:118 llvm.br ^exit119 ^exit:120 omp.terminator121 }122 llvm.call @bar() : () -> ()123 llvm.return124}125 126// Check the outlined function.127// CHECK: define internal void [[OUTLINED_FN:@.+]](ptr {{.+}}, ptr {{.+}}, ptr [[DATA:%.+]])128// CHECK: [[CONDITION_PTR:%.+]] = getelementptr {{.+}}, ptr [[DATA]]129// CHECK: [[CONDITION:%.+]] = load i1, ptr [[CONDITION_PTR]]130// CHECK: [[ARG0_PTR:%.+]] = getelementptr {{.+}}, ptr [[DATA]], i32 0, i32 1131// CHECK: [[ARG0:%.+]] = load i32, ptr [[ARG0_PTR]]132// CHECK: [[ARG1_PTR:%.+]] = getelementptr {{.+}}, ptr [[DATA]], i32 0, i32 2133// CHECK: [[ARG1:%.+]] = load float, ptr [[ARG1_PTR]]134// CHECK: [[ARG2_PTR:%.+]] = getelementptr {{.+}}, ptr [[DATA]], i32 0, i32 3135// CHECK: [[ARG2:%.+]] = load ptr, ptr [[ARG2_PTR]]136// CHECK: [[ARG3_PTR:%.+]] = getelementptr {{.+}}, ptr [[DATA]], i32 0, i32 4137// CHECK: [[ARG3:%.+]] = load fp128, ptr [[ARG3_PTR]]138// CHECK: [[ALLOCATED_PTR:%.+]] = getelementptr {{.+}}, ptr [[DATA]], i32 0, i32 5139// CHECK: [[ALLOCATED:%.+]] = load ptr, ptr [[ALLOCATED_PTR]]140// CHECK: [[LOADED_PTR:%.+]] = getelementptr {{.+}}, ptr [[DATA]], i32 0, i32 6141// CHECK: [[LOADED:%.+]] = load i32, ptr [[LOADED_PTR]]142// CHECK: br label143 144// CHECK: br i1 [[CONDITION]], label %[[TRUE:.+]], label %[[FALSE:.+]]145// CHECK: [[FALSE]]:146// CHECK-NEXT: br label147// CHECK: [[TRUE]]:148// CHECK: call void @foo(i32 [[ARG0]], float [[ARG1]], ptr [[ARG2]], fp128 [[ARG3]], ptr [[ALLOCATED]], i32 [[LOADED]])149// CHECK-NEXT: br label150// CHECK: ret void151 152// -----153 154llvm.func @beforeTeams()155llvm.func @duringTeams()156llvm.func @afterTeams()157 158// CHECK-LABEL: @omp_teams_thread_limit159// CHECK-SAME: (i32 [[THREAD_LIMIT:.+]])160llvm.func @omp_teams_thread_limit(%threadLimit: i32) {161 // CHECK-NEXT: call void @beforeTeams()162 llvm.call @beforeTeams() : () -> ()163 // CHECK: [[THREAD_NUM:%.+]] = call i32 @__kmpc_global_thread_num164 // CHECK-NEXT: call void @__kmpc_push_num_teams_51({{.+}}, i32 [[THREAD_NUM]], i32 0, i32 0, i32 [[THREAD_LIMIT]])165 // CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @1, i32 0, ptr [[OUTLINED_FN:.+]])166 omp.teams thread_limit(%threadLimit : i32) {167 llvm.call @duringTeams() : () -> ()168 omp.terminator169 }170 // CHECK: call void @afterTeams171 llvm.call @afterTeams() : () -> ()172 // CHECK: ret void173 llvm.return174}175 176// CHECK: define internal void [[OUTLINED_FN]](ptr {{.+}}, ptr {{.+}})177// CHECK: call void @duringTeams()178// CHECK: ret void179 180// -----181 182llvm.func @beforeTeams()183llvm.func @duringTeams()184llvm.func @afterTeams()185 186// CHECK-LABEL: @omp_teams_num_teams_upper187// CHECK-SAME: (i32 [[NUM_TEAMS_UPPER:.+]])188llvm.func @omp_teams_num_teams_upper(%numTeamsUpper: i32) {189 // CHECK-NEXT: call void @beforeTeams()190 llvm.call @beforeTeams() : () -> ()191 // CHECK: [[THREAD_NUM:%.+]] = call i32 @__kmpc_global_thread_num192 // CHECK-NEXT: call void @__kmpc_push_num_teams_51({{.+}}, i32 [[THREAD_NUM]], i32 [[NUM_TEAMS_UPPER]], i32 [[NUM_TEAMS_UPPER]], i32 0)193 // CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @1, i32 0, ptr [[OUTLINED_FN:.+]])194 omp.teams num_teams(to %numTeamsUpper : i32) {195 llvm.call @duringTeams() : () -> ()196 omp.terminator197 }198 // CHECK: call void @afterTeams199 llvm.call @afterTeams() : () -> ()200 // CHECK: ret void201 llvm.return202}203 204// CHECK: define internal void [[OUTLINED_FN]](ptr {{.+}}, ptr {{.+}})205// CHECK: call void @duringTeams()206// CHECK: ret void207 208// -----209 210llvm.func @beforeTeams()211llvm.func @duringTeams()212llvm.func @afterTeams()213 214// CHECK-LABEL: @omp_teams_num_teams_lower_and_upper215// CHECK-SAME: (i32 [[NUM_TEAMS_LOWER:.+]], i32 [[NUM_TEAMS_UPPER:.+]])216llvm.func @omp_teams_num_teams_lower_and_upper(%numTeamsLower: i32, %numTeamsUpper: i32) {217 // CHECK-NEXT: call void @beforeTeams()218 llvm.call @beforeTeams() : () -> ()219 // CHECK: [[THREAD_NUM:%.+]] = call i32 @__kmpc_global_thread_num220 // CHECK-NEXT: call void @__kmpc_push_num_teams_51({{.+}}, i32 [[THREAD_NUM]], i32 [[NUM_TEAMS_LOWER]], i32 [[NUM_TEAMS_UPPER]], i32 0)221 // CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @1, i32 0, ptr [[OUTLINED_FN:.+]])222 omp.teams num_teams(%numTeamsLower : i32 to %numTeamsUpper: i32) {223 llvm.call @duringTeams() : () -> ()224 omp.terminator225 }226 // CHECK: call void @afterTeams227 llvm.call @afterTeams() : () -> ()228 // CHECK: ret void229 llvm.return230}231 232// CHECK: define internal void [[OUTLINED_FN]](ptr {{.+}}, ptr {{.+}})233// CHECK: call void @duringTeams()234// CHECK: ret void235 236// -----237 238llvm.func @beforeTeams()239llvm.func @duringTeams()240llvm.func @afterTeams()241 242// CHECK-LABEL: @omp_teams_num_teams_and_thread_limit243// CHECK-SAME: (i32 [[NUM_TEAMS_LOWER:.+]], i32 [[NUM_TEAMS_UPPER:.+]], i32 [[THREAD_LIMIT:.+]])244llvm.func @omp_teams_num_teams_and_thread_limit(%numTeamsLower: i32, %numTeamsUpper: i32, %threadLimit: i32) {245 // CHECK-NEXT: call void @beforeTeams()246 llvm.call @beforeTeams() : () -> ()247 // CHECK: [[THREAD_NUM:%.+]] = call i32 @__kmpc_global_thread_num248 // CHECK-NEXT: call void @__kmpc_push_num_teams_51({{.+}}, i32 [[THREAD_NUM]], i32 [[NUM_TEAMS_LOWER]], i32 [[NUM_TEAMS_UPPER]], i32 [[THREAD_LIMIT]])249 // CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @1, i32 0, ptr [[OUTLINED_FN:.+]])250 omp.teams num_teams(%numTeamsLower : i32 to %numTeamsUpper: i32) thread_limit(%threadLimit: i32) {251 llvm.call @duringTeams() : () -> ()252 omp.terminator253 }254 // CHECK: call void @afterTeams255 llvm.call @afterTeams() : () -> ()256 // CHECK: ret void257 llvm.return258}259 260// CHECK: define internal void [[OUTLINED_FN]](ptr {{.+}}, ptr {{.+}})261// CHECK: call void @duringTeams()262// CHECK: ret void263 264// -----265 266llvm.func @beforeTeams()267llvm.func @duringTeams()268llvm.func @afterTeams()269 270// CHECK-LABEL: @teams_if271// CHECK-SAME: (i1 [[ARG:.+]])272llvm.func @teams_if(%arg : i1) {273 // CHECK-NEXT: call void @beforeTeams()274 llvm.call @beforeTeams() : () -> ()275 // If the condition is true, then the value of bounds is zero - which basically means "implementation-defined". 276 // The runtime sees zero and sets a default value of number of teams. This behavior is according to the standard.277 // The same is true for `thread_limit`.278 // CHECK: [[NUM_TEAMS_UPPER:%.+]] = select i1 [[ARG]], i32 0, i32 1279 // CHECK: [[NUM_TEAMS_LOWER:%.+]] = select i1 [[ARG]], i32 0, i32 1280 // CHECK: call void @__kmpc_push_num_teams_51(ptr {{.+}}, i32 {{.+}}, i32 [[NUM_TEAMS_LOWER]], i32 [[NUM_TEAMS_UPPER]], i32 0)281 // CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}})282 omp.teams if(%arg) {283 llvm.call @duringTeams() : () -> ()284 omp.terminator285 }286 // CHECK: call void @afterTeams()287 llvm.call @afterTeams() : () -> ()288 llvm.return289}290 291// -----292 293llvm.func @beforeTeams()294llvm.func @duringTeams()295llvm.func @afterTeams()296 297// CHECK-LABEL: @teams_if_with_num_teams298// CHECK-SAME: (i1 [[CONDITION:.+]], i32 [[NUM_TEAMS_LOWER:.+]], i32 [[NUM_TEAMS_UPPER:.+]], i32 [[THREAD_LIMIT:.+]])299llvm.func @teams_if_with_num_teams(%condition: i1, %numTeamsLower: i32, %numTeamsUpper: i32, %threadLimit: i32) {300 // CHECK: call void @beforeTeams()301 llvm.call @beforeTeams() : () -> ()302 // CHECK: [[NUM_TEAMS_UPPER_NEW:%.+]] = select i1 [[CONDITION]], i32 [[NUM_TEAMS_UPPER]], i32 1303 // CHECK: [[NUM_TEAMS_LOWER_NEW:%.+]] = select i1 [[CONDITION]], i32 [[NUM_TEAMS_LOWER]], i32 1304 // CHECK: call void @__kmpc_push_num_teams_51(ptr {{.+}}, i32 {{.+}}, i32 [[NUM_TEAMS_LOWER_NEW]], i32 [[NUM_TEAMS_UPPER_NEW]], i32 [[THREAD_LIMIT]])305 // CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}})306 omp.teams if(%condition) num_teams(%numTeamsLower: i32 to %numTeamsUpper: i32) thread_limit(%threadLimit: i32) {307 llvm.call @duringTeams() : () -> ()308 omp.terminator309 }310 // CHECK: call void @afterTeams()311 llvm.call @afterTeams() : () -> ()312 llvm.return313}314