Skip to content

[InferAddrSpaces] Correctly replace identical operands of insts #82610

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,7 @@ bool InferAddressSpacesImpl::rewriteWithNewAddressSpaces(
Value::use_iterator I, E, Next;
for (I = V->use_begin(), E = V->use_end(); I != E;) {
Use &U = *I;
User *CurUser = U.getUser();

// Some users may see the same pointer operand in multiple operands. Skip
// to the next instruction.
Expand All @@ -1231,11 +1232,10 @@ bool InferAddressSpacesImpl::rewriteWithNewAddressSpaces(
// If V is used as the pointer operand of a compatible memory operation,
// sets the pointer operand to NewV. This replacement does not change
// the element type, so the resultant load/store is still valid.
U.set(NewV);
CurUser->replaceUsesOfWith(V, NewV);
continue;
}

User *CurUser = U.getUser();
// Skip if the current user is the new value itself.
if (CurUser == NewV)
continue;
Expand Down Expand Up @@ -1311,10 +1311,13 @@ bool InferAddressSpacesImpl::rewriteWithNewAddressSpaces(

while (isa<PHINode>(InsertPos))
++InsertPos;
U.set(new AddrSpaceCastInst(NewV, V->getType(), "", &*InsertPos));
// This instruction may contain multiple uses of V, update them all.
CurUser->replaceUsesOfWith(
V, new AddrSpaceCastInst(NewV, V->getType(), "", &*InsertPos));
} else {
U.set(ConstantExpr::getAddrSpaceCast(cast<Constant>(NewV),
V->getType()));
CurUser->replaceUsesOfWith(
V, ConstantExpr::getAddrSpaceCast(cast<Constant>(NewV),
V->getType()));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -S -passes=infer-address-spaces --verify-each %s | FileCheck %s

; Inst can use a value multiple time. When we're inserting an addrspacecast to flat,
; it's important all the identical uses use an indentical replacement, especially
; for PHIs.

define amdgpu_kernel void @test_phi() {
; CHECK-LABEL: @test_phi(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOADED_PTR:%.*]] = load ptr, ptr addrspace(4) null, align 8
; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[LOADED_PTR]] to ptr addrspace(1)
; CHECK-NEXT: br label [[BB0:%.*]]
; CHECK: bb0:
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr addrspace(1) [[TMP0]], i64 3
; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(1) [[GEP]] to ptr
; CHECK-NEXT: switch i32 0, label [[END:%.*]] [
; CHECK-NEXT: i32 1, label [[END]]
; CHECK-NEXT: i32 4, label [[END]]
; CHECK-NEXT: i32 5, label [[BB1:%.*]]
; CHECK-NEXT: ]
; CHECK: bb1:
; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr addrspace(1) [[GEP]], align 16
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[RETVAL_SROA_0_0_I569_PH:%.*]] = phi ptr [ null, [[BB1]] ], [ [[TMP1]], [[BB0]] ], [ [[TMP1]], [[BB0]] ], [ [[TMP1]], [[BB0]] ]
; CHECK-NEXT: ret void
;
entry:
%loaded.ptr = load ptr, ptr addrspace(4) null, align 8
br label %bb0

bb0:
%gep = getelementptr i64, ptr %loaded.ptr, i64 3
switch i32 0, label %end [
i32 1, label %end
i32 4, label %end
i32 5, label %bb1
]

bb1:
%0 = load double, ptr %gep, align 16
br label %end

end:
%retval.sroa.0.0.i569.ph = phi ptr [ null, %bb1 ], [ %gep, %bb0 ], [ %gep, %bb0 ], [ %gep, %bb0 ]
ret void
}

declare void @uses_ptrs(ptr, ptr, ptr)

; We shouldn't treat PHIs differently, even other users should have the same treatment.
; All occurences of %gep are replaced with an identical value.
define amdgpu_kernel void @test_other() {
; CHECK-LABEL: @test_other(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOADED_PTR:%.*]] = load ptr, ptr addrspace(4) null, align 8
; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[LOADED_PTR]] to ptr addrspace(1)
; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(1) [[TMP0]] to ptr
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, ptr [[TMP1]], i64 3
; CHECK-NEXT: call void @uses_ptrs(ptr [[GEP]], ptr [[GEP]], ptr [[GEP]])
; CHECK-NEXT: ret void
;
entry:
%loaded.ptr = load ptr, ptr addrspace(4) null, align 8
%gep = getelementptr i64, ptr %loaded.ptr, i64 3
call void @uses_ptrs(ptr %gep, ptr %gep, ptr %gep)
ret void
}