Skip to content

Commit f5a0b03

Browse files
authored
[GCLowering] Expand support for vectors of pointers (#28455)
Most of the support was already there, but it was mostly unexercised. The recent activation of the SLP vectorizer made these patterns appear in the IR, so fixup the support. Fixes #28445
1 parent 00d6f72 commit f5a0b03

File tree

3 files changed

+70
-10
lines changed

3 files changed

+70
-10
lines changed

src/llvm-late-gc-lowering.cpp

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,9 @@ static std::pair<Value*,int> FindBaseValue(const State &S, Value *V, bool UseCac
486486
isa<Argument>(CurrentV) || isa<SelectInst>(CurrentV) ||
487487
isa<PHINode>(CurrentV) || isa<AddrSpaceCastInst>(CurrentV) ||
488488
isa<Constant>(CurrentV) || isa<AllocaInst>(CurrentV) ||
489-
isa<ExtractValueInst>(CurrentV));
489+
isa<ExtractValueInst>(CurrentV) ||
490+
isa<InsertElementInst>(CurrentV) ||
491+
isa<ShuffleVectorInst>(CurrentV));
490492
return std::make_pair(CurrentV, fld_idx);
491493
}
492494

@@ -602,22 +604,37 @@ std::vector<int> LateLowerGCFrame::NumberVectorBase(State &S, Value *CurrentV) {
602604
((isa<Argument>(CurrentV) || isa<AllocaInst>(CurrentV) ||
603605
isa<AddrSpaceCastInst>(CurrentV)) &&
604606
getValueAddrSpace(CurrentV) != AddressSpace::Tracked)) {
607+
Numbers.resize(cast<VectorType>(CurrentV->getType())->getNumElements(), -1);
605608
}
606609
/* We (the frontend) don't insert either of these, but it would be legal -
607610
though a bit strange, considering they're pointers - for the optimizer to
608611
do so. All that's needed here is to NumberVector the previous vector/value
609612
and lift the operation */
610-
else if (isa<ShuffleVectorInst>(CurrentV)) {
611-
assert(false && "TODO Shuffle");
612-
} else if (isa<InsertElementInst>(CurrentV)) {
613-
assert(false && "TODO Insert");
614-
} else if (isa<LoadInst>(CurrentV)) {
613+
else if (auto *SVI = dyn_cast<ShuffleVectorInst>(CurrentV)) {
614+
std::vector<int> Numbers1 = NumberVectorBase(S, SVI->getOperand(0));
615+
std::vector<int> Numbers2 = NumberVectorBase(S, SVI->getOperand(1));
616+
auto Mask = SVI->getShuffleMask();
617+
for (unsigned idx : Mask) {
618+
if (idx < Numbers1.size()) {
619+
Numbers.push_back(Numbers1[idx]);
620+
} else {
621+
Numbers.push_back(Numbers2[idx - Numbers1.size()]);
622+
}
623+
}
624+
} else if (auto *IEI = dyn_cast<InsertElementInst>(CurrentV)) {
625+
unsigned idx = cast<ConstantInt>(IEI->getOperand(2))->getZExtValue();
626+
Numbers = NumberVectorBase(S, IEI->getOperand(0));
627+
int ElNumber = Number(S, IEI->getOperand(1));
628+
Numbers[idx] = ElNumber;
629+
} else if (isa<LoadInst>(CurrentV) || isa<CallInst>(CurrentV) || isa<PHINode>(CurrentV)) {
615630
// This is simple, we can just number them sequentially
616631
for (unsigned i = 0; i < cast<VectorType>(CurrentV->getType())->getNumElements(); ++i) {
617632
int Num = ++S.MaxPtrNumber;
618633
Numbers.push_back(Num);
619634
S.ReversePtrNumbering[Num] = CurrentV;
620635
}
636+
} else {
637+
assert(false && "Unexpected vector generating operating");
621638
}
622639
S.AllVectorNumbering[CurrentV] = Numbers;
623640
return Numbers;
@@ -629,9 +646,17 @@ std::vector<int> LateLowerGCFrame::NumberVector(State &S, Value *V) {
629646
return it->second;
630647
auto CurrentV = FindBaseValue(S, V);
631648
assert(CurrentV.second == -1);
632-
auto Numbers = NumberVectorBase(S, CurrentV.first);
633-
S.AllVectorNumbering[V] = Numbers;
634-
return Numbers;
649+
// E.g. if this is a gep, it's possible for the base to be a single ptr
650+
if (isSpecialPtrVec(CurrentV.first->getType())) {
651+
auto Numbers = NumberVectorBase(S, CurrentV.first);
652+
S.AllVectorNumbering[V] = Numbers;
653+
return Numbers;
654+
} else {
655+
std::vector<int> Numbers{};
656+
Numbers.resize(cast<VectorType>(V->getType())->getNumElements(),
657+
NumberBase(S, V, CurrentV.first));
658+
return Numbers;
659+
}
635660
}
636661

637662
static void MaybeResize(BBState &BBS, unsigned Idx) {
@@ -714,6 +739,8 @@ void LateLowerGCFrame::NoteUse(State &S, BBState &BBS, Value *V, BitVector &Uses
714739
std::vector<int> Nums = NumberVector(S, V);
715740
for (int Num : Nums) {
716741
MaybeResize(BBS, Num);
742+
if (Num < 0)
743+
continue;
717744
Uses[Num] = 1;
718745
}
719746
}
@@ -729,7 +756,7 @@ void LateLowerGCFrame::NoteUse(State &S, BBState &BBS, Value *V, BitVector &Uses
729756
void LateLowerGCFrame::NoteOperandUses(State &S, BBState &BBS, User &UI, BitVector &Uses) {
730757
for (Use &U : UI.operands()) {
731758
Value *V = U;
732-
if (!isSpecialPtr(V->getType()))
759+
if (!isSpecialPtr(V->getType()) && !isSpecialPtrVec(V->getType()))
733760
continue;
734761
NoteUse(S, BBS, V, Uses);
735762
}

test/core.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6675,3 +6675,23 @@ c28399 = 42
66756675
@test g28399(0)() == 42
66766676
@test g28399(1)() == 42
66776677
@test_throws UndefVarError(:__undef_28399__) f28399()
6678+
6679+
# issue #28445
6680+
mutable struct foo28445
6681+
x::Int
6682+
end
6683+
6684+
@noinline make_foo28445() = (foo28445(1), foo28445(rand(1:10)), foo28445(rand(1:10)))
6685+
@noinline function use_tuple28445(c)
6686+
@test isa(c[2], foo28445)
6687+
@test isa(c[3], foo28445)
6688+
end
6689+
6690+
function repackage28445()
6691+
(_, a, b) = make_foo28445()
6692+
GC.gc()
6693+
c = (foo28445(1), foo28445(2), a, b)
6694+
use_tuple28445(c)
6695+
true
6696+
end
6697+
@test repackage28445()

test/llvmpasses/gcroots.ll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,19 @@ top:
401401
ret i8 %val
402402
}
403403

404+
define %jl_value_t addrspace(10)* @vecstoreload(<2 x %jl_value_t addrspace(10)*> *%arg) {
405+
; CHECK-LABEL: @vecstoreload
406+
; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4
407+
top:
408+
%ptls = call %jl_value_t*** @julia.ptls_states()
409+
%loaded = load <2 x %jl_value_t addrspace(10)*>, <2 x %jl_value_t addrspace(10)*> *%arg
410+
call void @jl_safepoint()
411+
%obj = call %jl_value_t addrspace(10) *@alloc()
412+
%casted = bitcast %jl_value_t addrspace(10)* %obj to <2 x %jl_value_t addrspace(10)*> addrspace(10)*
413+
store <2 x %jl_value_t addrspace(10)*> %loaded, <2 x %jl_value_t addrspace(10)*> addrspace(10)* %casted
414+
ret %jl_value_t addrspace(10)* %obj
415+
}
416+
404417
!0 = !{!"jtbaa"}
405418
!1 = !{!"jtbaa_const", !0, i64 0}
406419
!2 = !{!1, !1, i64 0, i64 1}

0 commit comments

Comments
 (0)