155 lines · plain
1; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s2; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}3 4; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s5; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}6 7; CHECK-DAG: OpName [[ADD:%.*]] "test_add"8; CHECK-DAG: OpName [[SUB:%.*]] "test_sub"9; CHECK-DAG: OpName [[MIN:%.*]] "test_min"10; CHECK-DAG: OpName [[MAX:%.*]] "test_max"11; CHECK-DAG: OpName [[UMIN:%.*]] "test_umin"12; CHECK-DAG: OpName [[UMAX:%.*]] "test_umax"13; CHECK-DAG: OpName [[AND:%.*]] "test_and"14; CHECK-DAG: OpName [[OR:%.*]] "test_or"15; CHECK-DAG: OpName [[XOR:%.*]] "test_xor"16 17; CHECK-DAG: [[I32Ty:%.*]] = OpTypeInt 32 018; CHECK-DAG: [[PtrI32Ty:%.*]] = OpTypePointer Function [[I32Ty]]19; CHECK-DAG: [[I64Ty:%.*]] = OpTypeInt 64 020; CHECK-DAG: [[PtrI64Ty:%.*]] = OpTypePointer Generic [[I64Ty]]21; CHECK-DAG: [[CROSSDEVICESCOPE:%.*]] = OpConstantNull [[I32Ty]]22; CHECK-DAG: [[DEVICESCOPE:%.*]] = OpConstant [[I32Ty]] 123;; "monotonic" maps to the relaxed memory semantics, encoded with constant 024 25; CHECK: [[ADD]] = OpFunction [[I32Ty]]26; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[PtrI32Ty]]27; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter [[I32Ty]]28; CHECK-NEXT: OpLabel29; CHECK-NEXT: [[R:%.*]] = OpAtomicIAdd [[I32Ty]] [[A]] [[CROSSDEVICESCOPE]] {{.+}} [[B]]30; CHECK-NEXT: OpReturnValue [[R]]31; CHECK-NEXT: OpFunctionEnd32define i32 @test_add(i32* %ptr, i32 %val) {33 %r = atomicrmw add i32* %ptr, i32 %val monotonic34 ret i32 %r35}36 37; CHECK: [[SUB]] = OpFunction [[I32Ty]]38; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[PtrI32Ty]]39; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter [[I32Ty]]40; CHECK-NEXT: OpLabel41; CHECK-NEXT: [[R:%.*]] = OpAtomicISub [[I32Ty]] [[A]] [[CROSSDEVICESCOPE]] {{.+}} [[B]]42; CHECK-NEXT: OpReturnValue [[R]]43; CHECK-NEXT: OpFunctionEnd44define i32 @test_sub(i32* %ptr, i32 %val) {45 %r = atomicrmw sub i32* %ptr, i32 %val monotonic46 ret i32 %r47}48 49; CHECK: [[MIN]] = OpFunction [[I32Ty]]50; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[PtrI32Ty]]51; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter [[I32Ty]]52; CHECK-NEXT: OpLabel53; CHECK-NEXT: [[R:%.*]] = OpAtomicSMin [[I32Ty]] [[A]] [[CROSSDEVICESCOPE]] {{.+}} [[B]]54; CHECK-NEXT: OpReturnValue [[R]]55; CHECK-NEXT: OpFunctionEnd56define i32 @test_min(i32* %ptr, i32 %val) {57 %r = atomicrmw min i32* %ptr, i32 %val monotonic58 ret i32 %r59}60 61; CHECK: [[MAX]] = OpFunction [[I32Ty]]62; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[PtrI32Ty]]63; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter [[I32Ty]]64; CHECK-NEXT: OpLabel65; CHECK-NEXT: [[R:%.*]] = OpAtomicSMax [[I32Ty]] [[A]] [[CROSSDEVICESCOPE]] {{.+}} [[B]]66; CHECK-NEXT: OpReturnValue [[R]]67; CHECK-NEXT: OpFunctionEnd68define i32 @test_max(i32* %ptr, i32 %val) {69 %r = atomicrmw max i32* %ptr, i32 %val monotonic70 ret i32 %r71}72 73; CHECK: [[UMIN]] = OpFunction [[I32Ty]]74; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[PtrI32Ty]]75; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter [[I32Ty]]76; CHECK-NEXT: OpLabel77; CHECK-NEXT: [[R:%.*]] = OpAtomicUMin [[I32Ty]] [[A]] [[CROSSDEVICESCOPE]] {{.+}} [[B]]78; CHECK-NEXT: OpReturnValue [[R]]79; CHECK-NEXT: OpFunctionEnd80define i32 @test_umin(i32* %ptr, i32 %val) {81 %r = atomicrmw umin i32* %ptr, i32 %val monotonic82 ret i32 %r83}84 85; CHECK: [[UMAX]] = OpFunction [[I32Ty]]86; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[PtrI32Ty]]87; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter [[I32Ty]]88; CHECK-NEXT: OpLabel89; CHECK-NEXT: [[R:%.*]] = OpAtomicUMax [[I32Ty]] [[A]] [[CROSSDEVICESCOPE]] {{.+}} [[B]]90; CHECK-NEXT: OpReturnValue [[R]]91; CHECK-NEXT: OpFunctionEnd92define i32 @test_umax(i32* %ptr, i32 %val) {93 %r = atomicrmw umax i32* %ptr, i32 %val monotonic94 ret i32 %r95}96 97; CHECK: [[AND]] = OpFunction [[I32Ty]]98; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[PtrI32Ty]]99; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter [[I32Ty]]100; CHECK-NEXT: OpLabel101; CHECK-NEXT: [[R:%.*]] = OpAtomicAnd [[I32Ty]] [[A]] [[CROSSDEVICESCOPE]] {{.+}} [[B]]102; CHECK-NEXT: OpReturnValue [[R]]103; CHECK-NEXT: OpFunctionEnd104define i32 @test_and(i32* %ptr, i32 %val) {105 %r = atomicrmw and i32* %ptr, i32 %val monotonic106 ret i32 %r107}108 109; CHECK: [[OR]] = OpFunction [[I32Ty]]110; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[PtrI32Ty]]111; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter [[I32Ty]]112; CHECK-NEXT: OpLabel113; CHECK-NEXT: [[R:%.*]] = OpAtomicOr [[I32Ty]] [[A]] [[CROSSDEVICESCOPE]] {{.+}} [[B]]114; CHECK-NEXT: OpReturnValue [[R]]115; CHECK-NEXT: OpFunctionEnd116define i32 @test_or(i32* %ptr, i32 %val) {117 %r = atomicrmw or i32* %ptr, i32 %val monotonic118 ret i32 %r119}120 121; CHECK: [[XOR]] = OpFunction [[I32Ty]]122; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[PtrI32Ty]]123; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter [[I32Ty]]124; CHECK-NEXT: OpLabel125; CHECK-NEXT: [[R:%.*]] = OpAtomicXor [[I32Ty]] [[A]] [[CROSSDEVICESCOPE]] {{.+}} [[B]]126; CHECK-NEXT: OpReturnValue [[R]]127; CHECK-NEXT: OpFunctionEnd128define i32 @test_xor(i32* %ptr, i32 %val) {129 %r = atomicrmw xor i32* %ptr, i32 %val monotonic130 ret i32 %r131}132 133; CHECK: OpFunction134; CHECK-NEXT: [[Arg1:%.*]] = OpFunctionParameter [[PtrI64Ty]]135; CHECK-NEXT: [[Arg2:%.*]] = OpFunctionParameter [[I64Ty]]136; CHECK-NEXT: OpLabel137; CHECK-NEXT: OpAtomicSMin [[I64Ty]] [[Arg1]] [[DEVICESCOPE]] {{.+}} [[Arg2]]138; CHECK-NEXT: OpAtomicSMax [[I64Ty]] [[Arg1]] [[DEVICESCOPE]] {{.+}} [[Arg2]]139; CHECK-NEXT: OpAtomicUMin [[I64Ty]] [[Arg1]] [[DEVICESCOPE]] {{.+}} [[Arg2]]140; CHECK-NEXT: OpAtomicUMax [[I64Ty]] [[Arg1]] [[DEVICESCOPE]] {{.+}} [[Arg2]]141; CHECK-NEXT: OpReturn142; CHECK-NEXT: OpFunctionEnd143define dso_local spir_kernel void @test_wrappers(ptr addrspace(4) %arg, i64 %val) {144 %r1 = call spir_func i64 @__spirv_AtomicSMin(ptr addrspace(4) %arg, i32 1, i32 0, i64 %val)145 %r2 = call spir_func i64 @__spirv_AtomicSMax(ptr addrspace(4) %arg, i32 1, i32 0, i64 %val)146 %r3 = call spir_func i64 @__spirv_AtomicUMin(ptr addrspace(4) %arg, i32 1, i32 0, i64 %val)147 %r4 = call spir_func i64 @__spirv_AtomicUMax(ptr addrspace(4) %arg, i32 1, i32 0, i64 %val)148 ret void149}150 151declare dso_local spir_func i64 @__spirv_AtomicSMin(ptr addrspace(4), i32, i32, i64)152declare dso_local spir_func i64 @__spirv_AtomicSMax(ptr addrspace(4), i32, i32, i64)153declare dso_local spir_func i64 @__spirv_AtomicUMin(ptr addrspace(4), i32, i32, i64)154declare dso_local spir_func i64 @__spirv_AtomicUMax(ptr addrspace(4), i32, i32, i64)155