[llvm] [AMDGPU] Hoist readlane/readfirst through unary/binary operands (PR #129037)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 27 03:14:52 PST 2025


================
@@ -0,0 +1,143 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -mtriple=amdgcn-- -mcpu=gfx1030 -passes=instcombine -S < %s | FileCheck %s
+
+; The readfirstlane version of this test covers all the interesting cases of the
+; shared logic. This testcase focuses on readlane specific pitfalls.
+
+; test unary
+
+define float @hoist_fneg_f32(float %arg, i32 %lane) {
+; CHECK-LABEL: define float @hoist_fneg_f32(
+; CHECK-SAME: float [[ARG:%.*]], i32 [[LANE:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    [[VAL:%.*]] = fneg float [[ARG]]
+; CHECK-NEXT:    [[RFL:%.*]] = call float @llvm.amdgcn.readlane.f32(float [[VAL]], i32 [[LANE]])
+; CHECK-NEXT:    ret float [[RFL]]
+;
+bb:
+  %val = fneg float %arg
+  %rfl = call float @llvm.amdgcn.readlane.f32(float %val, i32 %lane)
+  ret float %rfl
+}
+
+define double @hoist_fneg_f64(double %arg, i32 %lane) {
+; CHECK-LABEL: define double @hoist_fneg_f64(
+; CHECK-SAME: double [[ARG:%.*]], i32 [[LANE:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    [[VAL:%.*]] = fneg double [[ARG]]
+; CHECK-NEXT:    [[RFL:%.*]] = call double @llvm.amdgcn.readlane.f64(double [[VAL]], i32 [[LANE]])
+; CHECK-NEXT:    ret double [[RFL]]
+;
+bb:
+  %val = fneg double %arg
+  %rfl = call double @llvm.amdgcn.readlane.f64(double %val, i32 %lane)
+  ret double %rfl
+}
+
+; test binary i32
+
+define i32 @hoist_add_i32(i32 %arg, i32 %lane) {
+; CHECK-LABEL: define i32 @hoist_add_i32(
+; CHECK-SAME: i32 [[ARG:%.*]], i32 [[LANE:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    [[VAL:%.*]] = add i32 [[ARG]], 16777215
+; CHECK-NEXT:    [[RFL:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[VAL]], i32 [[LANE]])
+; CHECK-NEXT:    ret i32 [[RFL]]
+;
+bb:
+  %val = add i32 %arg, 16777215
+  %rfl = call i32 @llvm.amdgcn.readlane.i32(i32 %val, i32 %lane)
+  ret i32 %rfl
+}
+
+define float @hoist_fadd_f32(float %arg, i32 %lane) {
+; CHECK-LABEL: define float @hoist_fadd_f32(
+; CHECK-SAME: float [[ARG:%.*]], i32 [[LANE:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    [[VAL:%.*]] = fadd float [[ARG]], 1.280000e+02
+; CHECK-NEXT:    [[RFL:%.*]] = call float @llvm.amdgcn.readlane.f32(float [[VAL]], i32 [[LANE]])
+; CHECK-NEXT:    ret float [[RFL]]
+;
+bb:
+  %val = fadd float %arg, 128.0
+  %rfl = call float @llvm.amdgcn.readlane.f32(float %val, i32 %lane)
+  ret float %rfl
+}
+
+; test binary i64
+
+define i64 @hoist_and_i64(i64 %arg, i32 %lane) {
+; CHECK-LABEL: define i64 @hoist_and_i64(
+; CHECK-SAME: i64 [[ARG:%.*]], i32 [[LANE:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    [[VAL:%.*]] = and i64 [[ARG]], 16777215
+; CHECK-NEXT:    [[RFL:%.*]] = call i64 @llvm.amdgcn.readlane.i64(i64 [[VAL]], i32 [[LANE]])
+; CHECK-NEXT:    ret i64 [[RFL]]
+;
+bb:
+  %val = and i64 %arg, 16777215
+  %rfl = call i64 @llvm.amdgcn.readlane.i32(i64 %val, i32 %lane)
+  ret i64 %rfl
+}
+
+define double @hoist_fadd_f64(double %arg, i32 %lane) {
+; CHECK-LABEL: define double @hoist_fadd_f64(
+; CHECK-SAME: double [[ARG:%.*]], i32 [[LANE:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    [[VAL:%.*]] = fadd double [[ARG]], 1.280000e+02
+; CHECK-NEXT:    [[RFL:%.*]] = call double @llvm.amdgcn.readlane.f64(double [[VAL]], i32 [[LANE]])
+; CHECK-NEXT:    ret double [[RFL]]
+;
+bb:
+  %val = fadd double %arg, 128.0
+  %rfl = call double @llvm.amdgcn.readlane.f64(double %val, i32 %lane)
+  ret double %rfl
+}
+
+; test constant on LHS
+
+define i32 @hoist_sub_i32_lhs(i32 %arg, i32 %lane) {
+; CHECK-LABEL: define i32 @hoist_sub_i32_lhs(
+; CHECK-SAME: i32 [[ARG:%.*]], i32 [[LANE:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    [[VAL:%.*]] = sub i32 16777215, [[ARG]]
+; CHECK-NEXT:    [[RFL:%.*]] = call i32 @llvm.amdgcn.readlane.i32(i32 [[VAL]], i32 [[LANE]])
+; CHECK-NEXT:    ret i32 [[RFL]]
+;
+bb:
+  %val = sub i32 16777215, %arg
+  %rfl = call i32 @llvm.amdgcn.readlane.i32(i32 %val, i32 %lane)
+  ret i32 %rfl
+}
+
+define float @hoist_fsub_f32_lhs(float %arg, i32 %lane) {
+; CHECK-LABEL: define float @hoist_fsub_f32_lhs(
+; CHECK-SAME: float [[ARG:%.*]], i32 [[LANE:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    [[VAL:%.*]] = fsub float 1.280000e+02, [[ARG]]
+; CHECK-NEXT:    [[RFL:%.*]] = call float @llvm.amdgcn.readlane.f32(float [[VAL]], i32 [[LANE]])
+; CHECK-NEXT:    ret float [[RFL]]
+;
+bb:
+  %val = fsub float 128.0, %arg
+  %rfl = call float @llvm.amdgcn.readlane.f32(float %val, i32 %lane)
+  ret float %rfl
+}
+
+; Check cases where we can't move the readlane higher
+
+define float @cannot_move_readlane(float %arg, i32 %base) {
+; CHECK-LABEL: define float @cannot_move_readlane(
+; CHECK-SAME: float [[ARG:%.*]], i32 [[BASE:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    [[VAL:%.*]] = fsub float 1.280000e+02, [[ARG]]
+; CHECK-NEXT:    [[LANE:%.*]] = add i32 [[BASE]], 2
+; CHECK-NEXT:    [[RFL:%.*]] = call float @llvm.amdgcn.readlane.f32(float [[VAL]], i32 [[LANE]])
+; CHECK-NEXT:    ret float [[RFL]]
+;
+bb:
+  %val = fsub float 128.0, %arg
+  %lane = add i32 %base, 2
+  %rfl = call float @llvm.amdgcn.readlane.f32(float %val, i32 %lane)
+  ret float %rfl
+}
----------------
arsenm wrote:

Add tests with convergence tokens 

https://github.com/llvm/llvm-project/pull/129037


More information about the llvm-commits mailing list