| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=instcombine < %s | FileCheck -check-prefixes=CHECK,WAVE64 %s |
| ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mattr=+wavefrontsize32 -passes=instcombine < %s | FileCheck -check-prefixes=CHECK,WAVE32 %s |
| ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mattr=+wavefrontsize64 -passes=instcombine < %s | FileCheck -check-prefixes=CHECK,WAVE64 %s |
| |
| ; -------------------------------------------------------------------- |
| ; llvm.amdgcn.readlane |
| ; -------------------------------------------------------------------- |
| |
| define i32 @readlane_31(i32 %arg) #0 { |
| ; CHECK-LABEL: define i32 @readlane_31( |
| ; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0:[0-9]+]] { |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 31) |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.readlane.i32(i32 %arg, i32 31) |
| ret i32 %res |
| } |
| |
| define i32 @readlane_32(i32 %arg) #0 { |
| ; WAVE64-LABEL: define i32 @readlane_32( |
| ; WAVE64-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] { |
| ; WAVE64-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 32) |
| ; WAVE64-NEXT: ret i32 [[RES]] |
| ; |
| ; WAVE32-LABEL: define i32 @readlane_32( |
| ; WAVE32-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] { |
| ; WAVE32-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 0) |
| ; WAVE32-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.readlane.i32(i32 %arg, i32 32) |
| ret i32 %res |
| } |
| |
| define i32 @readlane_33(i32 %arg) #0 { |
| ; WAVE64-LABEL: define i32 @readlane_33( |
| ; WAVE64-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] { |
| ; WAVE64-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 33) |
| ; WAVE64-NEXT: ret i32 [[RES]] |
| ; |
| ; WAVE32-LABEL: define i32 @readlane_33( |
| ; WAVE32-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] { |
| ; WAVE32-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 1) |
| ; WAVE32-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.readlane.i32(i32 %arg, i32 33) |
| ret i32 %res |
| } |
| |
| define i32 @readlane_63(i32 %arg) #0 { |
| ; WAVE64-LABEL: define i32 @readlane_63( |
| ; WAVE64-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] { |
| ; WAVE64-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 63) |
| ; WAVE64-NEXT: ret i32 [[RES]] |
| ; |
| ; WAVE32-LABEL: define i32 @readlane_63( |
| ; WAVE32-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] { |
| ; WAVE32-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 31) |
| ; WAVE32-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.readlane.i32(i32 %arg, i32 63) |
| ret i32 %res |
| } |
| |
| define i32 @readlane_64(i32 %arg) #0 { |
| ; CHECK-LABEL: define i32 @readlane_64( |
| ; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 0) |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.readlane.i32(i32 %arg, i32 64) |
| ret i32 %res |
| } |
| |
| define i32 @readlane_and_31(i32 %arg, i32 %idx) #0 { |
| ; WAVE64-LABEL: define i32 @readlane_and_31( |
| ; WAVE64-SAME: i32 [[ARG:%.*]], i32 [[IDX:%.*]]) #[[ATTR0]] { |
| ; WAVE64-NEXT: [[IDX_CLAMP:%.*]] = and i32 [[IDX]], 31 |
| ; WAVE64-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 [[IDX_CLAMP]]) |
| ; WAVE64-NEXT: ret i32 [[RES]] |
| ; |
| ; WAVE32-LABEL: define i32 @readlane_and_31( |
| ; WAVE32-SAME: i32 [[ARG:%.*]], i32 [[IDX:%.*]]) #[[ATTR0]] { |
| ; WAVE32-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 [[IDX]]) |
| ; WAVE32-NEXT: ret i32 [[RES]] |
| ; |
| %idx.clamp = and i32 %idx, 31 |
| %res = call i32 @llvm.amdgcn.readlane.i32(i32 %arg, i32 %idx.clamp) |
| ret i32 %res |
| } |
| |
| define i32 @readlane_and_63(i32 %arg, i32 %idx) #0 { |
| ; CHECK-LABEL: define i32 @readlane_and_63( |
| ; CHECK-SAME: i32 [[ARG:%.*]], i32 [[IDX:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 [[IDX]]) |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| %idx.clamp = and i32 %idx, 63 |
| %res = call i32 @llvm.amdgcn.readlane.i32(i32 %arg, i32 %idx.clamp) |
| ret i32 %res |
| } |
| |
| define i32 @readlane_poison(i32 %arg) #0 { |
| ; CHECK-LABEL: define i32 @readlane_poison( |
| ; CHECK-SAME: i32 [[ARG:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[ARG]], i32 poison) |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.readlane.i32(i32 %arg, i32 poison) |
| ret i32 %res |
| } |
| |
| define float @readlane_f32_63(float %arg) #0 { |
| ; WAVE64-LABEL: define float @readlane_f32_63( |
| ; WAVE64-SAME: float [[ARG:%.*]]) #[[ATTR0]] { |
| ; WAVE64-NEXT: [[RES:%.*]] = call float @llvm.amdgcn.readlane.f32(float [[ARG]], i32 63) |
| ; WAVE64-NEXT: ret float [[RES]] |
| ; |
| ; WAVE32-LABEL: define float @readlane_f32_63( |
| ; WAVE32-SAME: float [[ARG:%.*]]) #[[ATTR0]] { |
| ; WAVE32-NEXT: [[RES:%.*]] = call float @llvm.amdgcn.readlane.f32(float [[ARG]], i32 31) |
| ; WAVE32-NEXT: ret float [[RES]] |
| ; |
| %res = call float @llvm.amdgcn.readlane.f32(float %arg, i32 63) |
| ret float %res |
| } |
| |
| ; -------------------------------------------------------------------- |
| ; llvm.amdgcn.writelane |
| ; -------------------------------------------------------------------- |
| |
| define i32 @writelane_31(i32 %arg0, i32 %arg1) #0 { |
| ; CHECK-LABEL: define i32 @writelane_31( |
| ; CHECK-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 31, i32 [[ARG1]]) |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.writelane.i32(i32 %arg0, i32 31, i32 %arg1) |
| ret i32 %res |
| } |
| |
| define i32 @writelane_32(i32 %arg0, i32 %arg1) #0 { |
| ; WAVE64-LABEL: define i32 @writelane_32( |
| ; WAVE64-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] { |
| ; WAVE64-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 32, i32 [[ARG1]]) |
| ; WAVE64-NEXT: ret i32 [[RES]] |
| ; |
| ; WAVE32-LABEL: define i32 @writelane_32( |
| ; WAVE32-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] { |
| ; WAVE32-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 0, i32 [[ARG1]]) |
| ; WAVE32-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.writelane.i32(i32 %arg0, i32 32, i32 %arg1) |
| ret i32 %res |
| } |
| |
| define i32 @writelane_33(i32 %arg0, i32 %arg1) #0 { |
| ; WAVE64-LABEL: define i32 @writelane_33( |
| ; WAVE64-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] { |
| ; WAVE64-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 33, i32 [[ARG1]]) |
| ; WAVE64-NEXT: ret i32 [[RES]] |
| ; |
| ; WAVE32-LABEL: define i32 @writelane_33( |
| ; WAVE32-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] { |
| ; WAVE32-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 1, i32 [[ARG1]]) |
| ; WAVE32-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.writelane.i32(i32 %arg0, i32 33, i32 %arg1) |
| ret i32 %res |
| } |
| |
| define i32 @writelane_63(i32 %arg0, i32 %arg1) #0 { |
| ; WAVE64-LABEL: define i32 @writelane_63( |
| ; WAVE64-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] { |
| ; WAVE64-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 63, i32 [[ARG1]]) |
| ; WAVE64-NEXT: ret i32 [[RES]] |
| ; |
| ; WAVE32-LABEL: define i32 @writelane_63( |
| ; WAVE32-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] { |
| ; WAVE32-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 31, i32 [[ARG1]]) |
| ; WAVE32-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.writelane.i32(i32 %arg0, i32 63, i32 %arg1) |
| ret i32 %res |
| } |
| |
| define i32 @writelane_64(i32 %arg0, i32 %arg1) #0 { |
| ; CHECK-LABEL: define i32 @writelane_64( |
| ; CHECK-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 0, i32 [[ARG1]]) |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.writelane.i32(i32 %arg0, i32 64, i32 %arg1) |
| ret i32 %res |
| } |
| |
| define i32 @writelane_and_31(i32 %arg0, i32 %arg1, i32 %idx) #0 { |
| ; WAVE64-LABEL: define i32 @writelane_and_31( |
| ; WAVE64-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]], i32 [[IDX:%.*]]) #[[ATTR0]] { |
| ; WAVE64-NEXT: [[IDX_CLAMP:%.*]] = and i32 [[IDX]], 31 |
| ; WAVE64-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 [[IDX_CLAMP]], i32 [[ARG1]]) |
| ; WAVE64-NEXT: ret i32 [[RES]] |
| ; |
| ; WAVE32-LABEL: define i32 @writelane_and_31( |
| ; WAVE32-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]], i32 [[IDX:%.*]]) #[[ATTR0]] { |
| ; WAVE32-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 [[IDX]], i32 [[ARG1]]) |
| ; WAVE32-NEXT: ret i32 [[RES]] |
| ; |
| %idx.clamp = and i32 %idx, 31 |
| %res = call i32 @llvm.amdgcn.writelane.i32(i32 %arg0, i32 %idx.clamp, i32 %arg1) |
| ret i32 %res |
| } |
| |
| define i32 @writelane_and_63(i32 %arg0, i32 %arg1, i32 %idx) #0 { |
| ; CHECK-LABEL: define i32 @writelane_and_63( |
| ; CHECK-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]], i32 [[IDX:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 [[IDX]], i32 [[ARG1]]) |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| %idx.clamp = and i32 %idx, 63 |
| %res = call i32 @llvm.amdgcn.writelane.i32(i32 %arg0, i32 %idx.clamp, i32 %arg1) |
| ret i32 %res |
| } |
| |
| define i32 @writelane_poison(i32 %arg0, i32 %arg1) #0 { |
| ; CHECK-LABEL: define i32 @writelane_poison( |
| ; CHECK-SAME: i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.amdgcn.writelane.i32(i32 [[ARG0]], i32 poison, i32 [[ARG1]]) |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| %res = call i32 @llvm.amdgcn.writelane.i32(i32 %arg0, i32 poison, i32 %arg1) |
| ret i32 %res |
| } |
| |
| define float @writelane_f32_63(float %arg0, float %arg1) #0 { |
| ; WAVE64-LABEL: define float @writelane_f32_63( |
| ; WAVE64-SAME: float [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0]] { |
| ; WAVE64-NEXT: [[RES:%.*]] = call float @llvm.amdgcn.writelane.f32(float [[ARG0]], i32 63, float [[ARG1]]) |
| ; WAVE64-NEXT: ret float [[RES]] |
| ; |
| ; WAVE32-LABEL: define float @writelane_f32_63( |
| ; WAVE32-SAME: float [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0]] { |
| ; WAVE32-NEXT: [[RES:%.*]] = call float @llvm.amdgcn.writelane.f32(float [[ARG0]], i32 31, float [[ARG1]]) |
| ; WAVE32-NEXT: ret float [[RES]] |
| ; |
| %res = call float @llvm.amdgcn.writelane.f32(float %arg0, i32 63, float %arg1) |
| ret float %res |
| } |
| |
| attributes #0 = { nounwind } |