| ; RUN: opt -S -dxil-resource-access -dxil-op-lower -mtriple=dxil-pc-shadermodel6.0-compute %s | FileCheck %s |
| |
| ; DXIL has no floating-point atomic op. A float exchange only moves the bit |
| ; pattern, so it lowers to an i32 AtomicBinOp with a bitcast on the value and |
| ; on the returned original value. This needs no capability bits, so it works |
| ; from SM 6.0. |
| |
| target triple = "dxil-pc-shadermodel6.0-compute" |
| |
| ; CHECK-LABEL: define float @bab_xchg_float |
| define float @bab_xchg_float(i32 %offset, float %val) { |
| %buffer = call target("dx.RawBuffer", i8, 1, 0, 0) |
| @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null) |
| %ptr = call ptr @llvm.dx.resource.getpointer( |
| target("dx.RawBuffer", i8, 1, 0, 0) %buffer, i32 %offset) |
| ; CHECK: [[CAST:%.*]] = bitcast float %val to i32 |
| ; CHECK: [[OLD:%.*]] = call i32 @dx.op.atomicBinOp.i32(i32 78, %dx.types.Handle %{{.*}}, i32 8, i32 %offset, i32 poison, i32 poison, i32 [[CAST]]) |
| ; CHECK: [[RES:%.*]] = bitcast i32 [[OLD]] to float |
| %old = atomicrmw xchg ptr %ptr, float %val monotonic |
| ; CHECK: ret float [[RES]] |
| ret float %old |
| } |
| |
| ; A StructuredBuffer of float keeps the struct index in coord0 and the byte |
| ; offset in coord1. |
| ; CHECK-LABEL: define float @sbuf_xchg_float |
| define float @sbuf_xchg_float(i32 %index, float %val) { |
| %buffer = call target("dx.RawBuffer", float, 1, 0, 0) |
| @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null) |
| %ptr = call ptr @llvm.dx.resource.getpointer( |
| target("dx.RawBuffer", float, 1, 0, 0) %buffer, i32 %index) |
| ; CHECK: [[CAST:%.*]] = bitcast float %val to i32 |
| ; CHECK: [[OLD:%.*]] = call i32 @dx.op.atomicBinOp.i32(i32 78, %dx.types.Handle %{{.*}}, i32 8, i32 %index, i32 0, i32 poison, i32 [[CAST]]) |
| ; CHECK: [[RES:%.*]] = bitcast i32 [[OLD]] to float |
| %old = atomicrmw xchg ptr %ptr, float %val monotonic |
| ; CHECK: ret float [[RES]] |
| ret float %old |
| } |
| |
| ; A texture of scalar float lowers the same way, with one coordinate operand |
| ; per texture dimension. |
| ; CHECK-LABEL: define float @texture2d_xchg_float |
| define float @texture2d_xchg_float(<2 x i32> %coords, float %val) { |
| %texture = call target("dx.Texture", float, 1, 0, 0, 2) |
| @llvm.dx.resource.handlefrombinding(i32 0, i32 1, i32 1, i32 0, ptr null) |
| %ptr = call ptr @llvm.dx.resource.getpointer( |
| target("dx.Texture", float, 1, 0, 0, 2) %texture, <2 x i32> %coords) |
| ; CHECK: %[[X:.*]] = extractelement <2 x i32> %coords, i64 0 |
| ; CHECK: %[[Y:.*]] = extractelement <2 x i32> %coords, i64 1 |
| ; CHECK: [[CAST:%.*]] = bitcast float %val to i32 |
| ; CHECK: [[OLD:%.*]] = call i32 @dx.op.atomicBinOp.i32(i32 78, %dx.types.Handle %{{.*}}, i32 8, i32 %[[X]], i32 %[[Y]], i32 poison, i32 [[CAST]]) |
| ; CHECK: [[RES:%.*]] = bitcast i32 [[OLD]] to float |
| %old = atomicrmw xchg ptr %ptr, float %val monotonic |
| ; CHECK: ret float [[RES]] |
| ret float %old |
| } |