; 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 }