Skip to content

Commit 59029b9

Browse files
committed
[RS4GC] Handle uses of extractelement for conversion from vector to scalar base
As mentioned in the comments, extractelement is special since we actually want a scalar base for that element we extracted from the vector (i.e. not a vector base). This same logic should apply to uses of the extractelement such as phis and selects which have the same BDV as the extractelement. Howeber, for these uses we conservatively mark the BDV state as conflict, since setting the EE's new base BDV does not always dominate these uses. Added testcase showcases the problem where the BDV identification chokes on the incorrect cast from vector to scalar for the phi use of extractelement. Tests-Run: make check, internal fuzzer testing Reviewers: reames, skatkov, dantrushin Reviewed-By: dantrushin Differential Revision: https://reviews.llvm.org/D75704
1 parent eb755df commit 59029b9

File tree

2 files changed

+87
-12
lines changed

2 files changed

+87
-12
lines changed

llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -926,8 +926,7 @@ static Value *findBasePointer(Value *I, DefiningValueMapTy &Cache) {
926926
}
927927
#endif
928928

929-
// Insert Phis for all conflicts
930-
// TODO: adjust naming patterns to avoid this order of iteration dependency
929+
// Handle extractelement instructions and their uses.
931930
for (auto Pair : States) {
932931
Instruction *I = cast<Instruction>(Pair.first);
933932
BDVState State = Pair.second;
@@ -938,17 +937,40 @@ static Value *findBasePointer(Value *I, DefiningValueMapTy &Cache) {
938937
// insert an extract even when we know an exact base for the instruction.
939938
// The problem is that we need to convert from a vector base to a scalar
940939
// base for the particular indice we're interested in.
941-
if (State.isBase() && isa<ExtractElementInst>(I) &&
942-
isa<VectorType>(State.getBaseValue()->getType())) {
943-
auto *EE = cast<ExtractElementInst>(I);
944-
// TODO: In many cases, the new instruction is just EE itself. We should
945-
// exploit this, but can't do it here since it would break the invariant
946-
// about the BDV not being known to be a base.
947-
auto *BaseInst = ExtractElementInst::Create(
948-
State.getBaseValue(), EE->getIndexOperand(), "base_ee", EE);
949-
BaseInst->setMetadata("is_base_value", MDNode::get(I->getContext(), {}));
950-
States[I] = BDVState(BDVState::Base, BaseInst);
940+
if (!State.isBase() || !isa<ExtractElementInst>(I) ||
941+
!isa<VectorType>(State.getBaseValue()->getType()))
942+
continue;
943+
auto *EE = cast<ExtractElementInst>(I);
944+
// TODO: In many cases, the new instruction is just EE itself. We should
945+
// exploit this, but can't do it here since it would break the invariant
946+
// about the BDV not being known to be a base.
947+
auto *BaseInst = ExtractElementInst::Create(
948+
State.getBaseValue(), EE->getIndexOperand(), "base_ee", EE);
949+
BaseInst->setMetadata("is_base_value", MDNode::get(I->getContext(), {}));
950+
States[I] = BDVState(BDVState::Base, BaseInst);
951+
952+
// We need to handle uses of the extractelement that have the same vector
953+
// base as well but the use is a scalar type. Since we cannot reuse the
954+
// same BaseInst above (may not satisfy property that base pointer should
955+
// always dominate derived pointer), we conservatively set this as conflict.
956+
// Setting the base value for these conflicts is handled in the next loop
957+
// which traverses States.
958+
for (User *U : I->users()) {
959+
auto *UseI = dyn_cast<Instruction>(U);
960+
if (!UseI || !States.count(UseI))
961+
continue;
962+
if (!isa<VectorType>(UseI->getType()) && States[UseI] == State)
963+
States[UseI] = BDVState(BDVState::Conflict);
951964
}
965+
}
966+
967+
// Insert Phis for all conflicts
968+
// TODO: adjust naming patterns to avoid this order of iteration dependency
969+
for (auto Pair : States) {
970+
Instruction *I = cast<Instruction>(Pair.first);
971+
BDVState State = Pair.second;
972+
assert(!isKnownBaseResult(I) && "why did it get added?");
973+
assert(!State.isUnknown() && "Optimistic algorithm didn't complete!");
952974

953975
// Since we're joining a vector and scalar base, they can never be the
954976
// same. As a result, we should always see insert element having reached

llvm/test/Transforms/RewriteStatepointsForGC/scalar-base-vector.ll

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,56 @@ entry:
141141
%ptr = extractelement <2 x i32 addrspace(1)*> %vec, i32 0
142142
ret i32 addrspace(1)* %ptr
143143
}
144+
145+
define void @test6() gc "statepoint-example" {
146+
; CHECK-LABEL: @test6(
147+
; CHECK-NEXT: bb:
148+
; CHECK-NEXT: br label [[HEADER:%.*]]
149+
; CHECK: header:
150+
; CHECK-NEXT: [[TMP_BASE:%.*]] = phi i8 addrspace(1)* [ [[TMP6_BASE:%.*]], [[LATCH:%.*]] ], [ null, [[BB:%.*]] ], !is_base_value !0
151+
; CHECK-NEXT: [[TMP:%.*]] = phi i8 addrspace(1)* [ [[TMP6:%.*]], [[LATCH]] ], [ undef, [[BB]] ]
152+
; CHECK-NEXT: br label [[BB10:%.*]]
153+
; CHECK: bb10:
154+
; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @spam, i32 0, i32 0, i32 0, i32 1, i8 addrspace(1)* [[TMP]], i8 addrspace(1)* [[TMP]], i8 addrspace(1)* [[TMP_BASE]])
155+
; CHECK-NEXT: [[TMP_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 9, i32 8)
156+
; CHECK-NEXT: [[TMP_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 9, i32 9)
157+
; CHECK-NEXT: br label [[BB25:%.*]]
158+
; CHECK: bb25:
159+
; CHECK-NEXT: [[STATEPOINT_TOKEN1:%.*]] = call token (i64, i32, <2 x i8 addrspace(1)*> ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_v2p1i8f(i64 2882400000, i32 0, <2 x i8 addrspace(1)*> ()* @baz, i32 0, i32 0, i32 0, i32 0)
160+
; CHECK-NEXT: [[TMP262:%.*]] = call <2 x i8 addrspace(1)*> @llvm.experimental.gc.result.v2p1i8(token [[STATEPOINT_TOKEN1]])
161+
; CHECK-NEXT: [[BASE_EE:%.*]] = extractelement <2 x i8 addrspace(1)*> [[TMP262]], i32 0, !is_base_value !0
162+
; CHECK-NEXT: [[TMP27:%.*]] = extractelement <2 x i8 addrspace(1)*> [[TMP262]], i32 0
163+
; CHECK-NEXT: br i1 undef, label [[BB7:%.*]], label [[LATCH]]
164+
; CHECK: bb7:
165+
; CHECK-NEXT: br label [[LATCH]]
166+
; CHECK: latch:
167+
; CHECK-NEXT: [[TMP6_BASE]] = phi i8 addrspace(1)* [ [[BASE_EE]], [[BB25]] ], [ [[BASE_EE]], [[BB7]] ], !is_base_value !0
168+
; CHECK-NEXT: [[TMP6]] = phi i8 addrspace(1)* [ [[TMP27]], [[BB25]] ], [ [[TMP27]], [[BB7]] ]
169+
; CHECK-NEXT: br label [[HEADER]]
170+
;
171+
bb:
172+
br label %header
173+
174+
header: ; preds = %latch, %bb
175+
%tmp = phi i8 addrspace(1)* [ %tmp6, %latch ], [ undef, %bb ]
176+
br label %bb10
177+
178+
bb10: ; preds = %bb2
179+
call void @spam() [ "deopt"(i8 addrspace(1)* %tmp) ]
180+
br label %bb25
181+
182+
bb25: ; preds = %bb24
183+
%tmp26 = call <2 x i8 addrspace(1)*> @baz()
184+
%tmp27 = extractelement <2 x i8 addrspace(1)*> %tmp26, i32 0
185+
br i1 undef, label %bb7, label %latch
186+
187+
bb7: ; preds = %bb25
188+
br label %latch
189+
190+
latch: ; preds = %bb25, %bb7
191+
%tmp6 = phi i8 addrspace(1)* [ %tmp27, %bb25 ], [ %tmp27, %bb7 ]
192+
br label %header
193+
}
194+
195+
declare void @spam()
196+
declare <2 x i8 addrspace(1)*> @baz()

0 commit comments

Comments
 (0)