Skip to content

Commit f7629f5

Browse files
wenju-hearsenm
andauthored
[InferAddressSpaces] Extend undef pointer operand support to phi inst (#159548)
Previously undef pointer operand is only supported for select inst, where undef in generic AS behaves like `take the other side`. This PR extends the support to other instructions, e.g. phi inst. Defer joining and inferring constant pointer operand until all other operand AS states considered. --------- Co-authored-by: Matt Arsenault <[email protected]>
1 parent daed12d commit f7629f5

File tree

2 files changed

+76
-61
lines changed

2 files changed

+76
-61
lines changed

llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp

Lines changed: 40 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,70 +1002,49 @@ bool InferAddressSpacesImpl::updateAddressSpace(
10021002
// isAddressExpression should guarantee that V is an operator or an argument.
10031003
assert(isa<Operator>(V) || isa<Argument>(V));
10041004

1005-
if (isa<Operator>(V) &&
1006-
cast<Operator>(V).getOpcode() == Instruction::Select) {
1007-
const Operator &Op = cast<Operator>(V);
1008-
Value *Src0 = Op.getOperand(1);
1009-
Value *Src1 = Op.getOperand(2);
1010-
1011-
auto I = InferredAddrSpace.find(Src0);
1012-
unsigned Src0AS = (I != InferredAddrSpace.end())
1013-
? I->second
1014-
: Src0->getType()->getPointerAddressSpace();
1015-
1016-
auto J = InferredAddrSpace.find(Src1);
1017-
unsigned Src1AS = (J != InferredAddrSpace.end())
1018-
? J->second
1019-
: Src1->getType()->getPointerAddressSpace();
1020-
1021-
auto *C0 = dyn_cast<Constant>(Src0);
1022-
auto *C1 = dyn_cast<Constant>(Src1);
1023-
1024-
// If one of the inputs is a constant, we may be able to do a constant
1025-
// addrspacecast of it. Defer inferring the address space until the input
1026-
// address space is known.
1027-
if ((C1 && Src0AS == UninitializedAddressSpace) ||
1028-
(C0 && Src1AS == UninitializedAddressSpace))
1029-
return false;
1030-
1031-
if (C0 && isSafeToCastConstAddrSpace(C0, Src1AS))
1032-
NewAS = Src1AS;
1033-
else if (C1 && isSafeToCastConstAddrSpace(C1, Src0AS))
1034-
NewAS = Src0AS;
1035-
else
1036-
NewAS = joinAddressSpaces(Src0AS, Src1AS);
1005+
unsigned AS = TTI->getAssumedAddrSpace(&V);
1006+
if (AS != UninitializedAddressSpace) {
1007+
// Use the assumed address space directly.
1008+
NewAS = AS;
10371009
} else {
1038-
unsigned AS = TTI->getAssumedAddrSpace(&V);
1039-
if (AS != UninitializedAddressSpace) {
1040-
// Use the assumed address space directly.
1041-
NewAS = AS;
1042-
} else {
1043-
// Otherwise, infer the address space from its pointer operands.
1044-
for (Value *PtrOperand : getPointerOperands(V, *DL, TTI)) {
1045-
auto I = InferredAddrSpace.find(PtrOperand);
1046-
unsigned OperandAS;
1047-
if (I == InferredAddrSpace.end()) {
1048-
OperandAS = PtrOperand->getType()->getPointerAddressSpace();
1049-
if (OperandAS == FlatAddrSpace) {
1050-
// Check AC for assumption dominating V.
1051-
unsigned AS = getPredicatedAddrSpace(*PtrOperand, &V);
1052-
if (AS != UninitializedAddressSpace) {
1053-
LLVM_DEBUG(dbgs()
1054-
<< " deduce operand AS from the predicate addrspace "
1055-
<< AS << '\n');
1056-
OperandAS = AS;
1057-
// Record this use with the predicated AS.
1058-
PredicatedAS[std::make_pair(&V, PtrOperand)] = OperandAS;
1059-
}
1010+
// Otherwise, infer the address space from its pointer operands.
1011+
SmallVector<Constant *, 2> ConstantPtrOps;
1012+
for (Value *PtrOperand : getPointerOperands(V, *DL, TTI)) {
1013+
auto I = InferredAddrSpace.find(PtrOperand);
1014+
unsigned OperandAS;
1015+
if (I == InferredAddrSpace.end()) {
1016+
OperandAS = PtrOperand->getType()->getPointerAddressSpace();
1017+
if (auto *C = dyn_cast<Constant>(PtrOperand);
1018+
C && OperandAS == FlatAddrSpace) {
1019+
// Defer joining the address space of constant pointer operands.
1020+
ConstantPtrOps.push_back(C);
1021+
continue;
1022+
}
1023+
if (OperandAS == FlatAddrSpace) {
1024+
// Check AC for assumption dominating V.
1025+
unsigned AS = getPredicatedAddrSpace(*PtrOperand, &V);
1026+
if (AS != UninitializedAddressSpace) {
1027+
LLVM_DEBUG(dbgs()
1028+
<< " deduce operand AS from the predicate addrspace "
1029+
<< AS << '\n');
1030+
OperandAS = AS;
1031+
// Record this use with the predicated AS.
1032+
PredicatedAS[std::make_pair(&V, PtrOperand)] = OperandAS;
10601033
}
1061-
} else
1062-
OperandAS = I->second;
1034+
}
1035+
} else
1036+
OperandAS = I->second;
10631037

1064-
// join(flat, *) = flat. So we can break if NewAS is already flat.
1065-
NewAS = joinAddressSpaces(NewAS, OperandAS);
1066-
if (NewAS == FlatAddrSpace)
1067-
break;
1068-
}
1038+
// join(flat, *) = flat. So we can break if NewAS is already flat.
1039+
NewAS = joinAddressSpaces(NewAS, OperandAS);
1040+
if (NewAS == FlatAddrSpace)
1041+
break;
1042+
}
1043+
if (NewAS != FlatAddrSpace && NewAS != UninitializedAddressSpace) {
1044+
if (any_of(ConstantPtrOps, [=](Constant *C) {
1045+
return !isSafeToCastConstAddrSpace(C, NewAS);
1046+
}))
1047+
NewAS = FlatAddrSpace;
10691048
}
10701049
}
10711050

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -S -passes=infer-address-spaces %s | FileCheck %s
3+
4+
define void @phi_poison(ptr addrspace(1) %arg, <2 x ptr addrspace(1)> %arg1) {
5+
; CHECK-LABEL: @phi_poison(
6+
; CHECK-NEXT: entry:
7+
; CHECK-NEXT: [[TMP0:%.*]] = call i1 @is_leader()
8+
; CHECK-NEXT: br i1 [[TMP0]], label [[LEADER:%.*]], label [[MERGE:%.*]]
9+
; CHECK: leader:
10+
; CHECK-NEXT: br label [[MERGE]]
11+
; CHECK: merge:
12+
; CHECK-NEXT: [[I:%.*]] = phi ptr addrspace(1) [ [[ARG:%.*]], [[LEADER]] ], [ poison, [[ENTRY:%.*]] ]
13+
; CHECK-NEXT: [[I2:%.*]] = phi <2 x ptr addrspace(1)> [ [[ARG1:%.*]], [[LEADER]] ], [ poison, [[ENTRY]] ]
14+
; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast <2 x ptr addrspace(1)> [[I2]] to <2 x ptr>
15+
; CHECK-NEXT: [[J:%.*]] = icmp eq ptr addrspace(1) [[I]], addrspacecast (ptr null to ptr addrspace(1))
16+
; CHECK-NEXT: [[J1:%.*]] = icmp eq <2 x ptr> [[TMP1]], zeroinitializer
17+
; CHECK-NEXT: ret void
18+
;
19+
entry:
20+
%is = call i1 @is_leader()
21+
br i1 %is, label %leader, label %merge
22+
23+
leader:
24+
%cast = addrspacecast ptr addrspace(1) %arg to ptr
25+
%cast1 = addrspacecast <2 x ptr addrspace(1)> %arg1 to <2 x ptr>
26+
br label %merge
27+
28+
merge:
29+
%i = phi ptr [%cast, %leader], [poison, %entry]
30+
%i1 = phi <2 x ptr> [%cast1, %leader], [poison, %entry]
31+
%j = icmp eq ptr %i, null
32+
%j1 = icmp eq <2 x ptr> %i1, zeroinitializer
33+
ret void
34+
}
35+
36+
declare i1 @is_leader()

0 commit comments

Comments
 (0)