Skip to content

Commit de3ea08

Browse files
vtjnashJeffBezanson
authored andcommitted
codegen,gc-lowering: post fixup tbaa information (#32321)
Certain metadata (invariant.load, tbaa_const) allows reordering of memory operations over unknown calls (including safepoint). Before GC lowering this is legal, because the optimizer sinking a load over a safepoint will automatically extend the live range of the heap object (by definition the live range of the heap object before GC lowering matches the live ranges of any reference to it). However, after GC lowering, we have fixed the live ranges of the heap objects, and thus it is no longer legal to sink such memory operations over safepoints (as the update to the object's live range won't be tracked). fix #32215 (cherry picked from commit b2304c5)
1 parent e1820db commit de3ea08

File tree

1 file changed

+77
-22
lines changed

1 file changed

+77
-22
lines changed

src/llvm-late-gc-lowering.cpp

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -902,26 +902,35 @@ JL_USED_FUNC static void dumpLivenessState(Function &F, State &S) {
902902
}
903903
}
904904

905-
// Check if this is a load from an immutable value. The easiest
906-
// way to do so is to look at the tbaa and see if it derives from
907-
// jtbaa_immut.
908-
static bool isLoadFromImmut(LoadInst *LI)
905+
static bool isTBAA(MDNode *TBAA, std::initializer_list<const char*> const strset)
909906
{
910-
if (LI->getMetadata(LLVMContext::MD_invariant_load))
911-
return true;
912-
MDNode *TBAA = LI->getMetadata(LLVMContext::MD_tbaa);
913907
if (!TBAA)
914908
return false;
915909
while (TBAA->getNumOperands() > 1) {
916910
TBAA = cast<MDNode>(TBAA->getOperand(1).get());
917911
auto str = cast<MDString>(TBAA->getOperand(0))->getString();
918-
if (str == "jtbaa_immut" || str == "jtbaa_const") {
919-
return true;
912+
for (auto str2 : strset) {
913+
if (str == str2) {
914+
return true;
915+
}
920916
}
921917
}
922918
return false;
923919
}
924920

921+
// Check if this is a load from an immutable value. The easiest
922+
// way to do so is to look at the tbaa and see if it derives from
923+
// jtbaa_immut.
924+
static bool isLoadFromImmut(LoadInst *LI)
925+
{
926+
if (LI->getMetadata(LLVMContext::MD_invariant_load))
927+
return true;
928+
MDNode *TBAA = LI->getMetadata(LLVMContext::MD_tbaa);
929+
if (isTBAA(TBAA, {"jtbaa_immut", "jtbaa_const"}))
930+
return true;
931+
return false;
932+
}
933+
925934
// Check if this is a load from an constant global.
926935
static bool isLoadFromConstGV(LoadInst *LI)
927936
{
@@ -930,14 +939,8 @@ static bool isLoadFromConstGV(LoadInst *LI)
930939
if (!isa<GlobalVariable>(LI->getPointerOperand()->stripInBoundsOffsets()))
931940
return false;
932941
MDNode *TBAA = LI->getMetadata(LLVMContext::MD_tbaa);
933-
if (!TBAA)
934-
return false;
935-
while (TBAA->getNumOperands() > 1) {
936-
TBAA = cast<MDNode>(TBAA->getOperand(1).get());
937-
if (cast<MDString>(TBAA->getOperand(0))->getString() == "jtbaa_const") {
938-
return true;
939-
}
940-
}
942+
if (isTBAA(TBAA, {"jtbaa_const"}))
943+
return true;
941944
return false;
942945
}
943946

@@ -1720,6 +1723,40 @@ static inline void UpdatePtrNumbering(Value *From, Value *To, State *S)
17201723
}
17211724
}
17221725

1726+
#if JL_LLVM_VERSION < 80000
1727+
MDNode *createMutableTBAAAccessTag(MDNode *Tag) {
1728+
MDNode *BaseType = cast<MDNode>(Tag->getOperand(0));
1729+
MDNode *AccessType = cast<MDNode>(Tag->getOperand(1));
1730+
Metadata *OffsetNode = Tag->getOperand(2);
1731+
uint64_t Offset = mdconst::extract<ConstantInt>(OffsetNode)->getZExtValue();
1732+
1733+
bool NewFormat = isa<MDNode>(AccessType->getOperand(0));
1734+
1735+
// See if the tag is already mutable.
1736+
unsigned ImmutabilityFlagOp = NewFormat ? 4 : 3;
1737+
if (Tag->getNumOperands() <= ImmutabilityFlagOp)
1738+
return Tag;
1739+
1740+
// If Tag is already mutable then return it.
1741+
Metadata *ImmutabilityFlagNode = Tag->getOperand(ImmutabilityFlagOp);
1742+
if (!mdconst::extract<ConstantInt>(ImmutabilityFlagNode)->getValue())
1743+
return Tag;
1744+
1745+
// Otherwise, create another node.
1746+
if (!NewFormat)
1747+
return MDBuilder(Tag->getContext()).createTBAAStructTagNode(BaseType, AccessType, Offset);
1748+
1749+
Metadata *SizeNode = Tag->getOperand(3);
1750+
uint64_t Size = mdconst::extract<ConstantInt>(SizeNode)->getZExtValue();
1751+
return MDBuilder(Tag->getContext()).createTBAAAccessTag(BaseType, AccessType, Offset, Size);
1752+
}
1753+
#else
1754+
MDNode *createMutableTBAAAccessTag(MDNode *Tag) {
1755+
return MDBuilder(Tag->getContext()).createMutableTBAAAccessTag(TBAA);
1756+
}
1757+
#endif
1758+
1759+
17231760
bool LateLowerGCFrame::CleanupIR(Function &F, State *S) {
17241761
bool ChangesMade = false;
17251762
// We create one alloca for all the jlcall frames that haven't been processed
@@ -1737,6 +1774,24 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S) {
17371774
SmallVector<CallInst*, 16> write_barriers;
17381775
for (BasicBlock &BB : F) {
17391776
for (auto it = BB.begin(); it != BB.end();) {
1777+
Instruction *I = &*it;
1778+
if (isa<LoadInst>(I) || isa<StoreInst>(I)) {
1779+
// strip all constant alias information, as it might depend on the gc having
1780+
// preserved a gc root, which stops being true after this pass (#32215)
1781+
// we'd like to call RewriteStatepointsForGC::stripNonValidData here, but
1782+
// that function asserts that the GC strategy must be named either "statepoint-example" or "coreclr",
1783+
// while we don't give a name to our GC in the IR, and C++ scope rules prohibit us from using it,
1784+
// so instead we reimplement it here badly
1785+
if (I->getMetadata(LLVMContext::MD_invariant_load))
1786+
I->setMetadata(LLVMContext::MD_invariant_load, NULL);
1787+
if (MDNode *TBAA = I->getMetadata(LLVMContext::MD_tbaa)) {
1788+
if (TBAA->getNumOperands() == 4 && isTBAA(TBAA, {"jtbaa_const"})) {
1789+
MDNode *MutableTBAA = createMutableTBAAAccessTag(TBAA);
1790+
if (MutableTBAA != TBAA)
1791+
I->setMetadata(LLVMContext::MD_tbaa, MutableTBAA);
1792+
}
1793+
}
1794+
}
17401795
auto *CI = dyn_cast<CallInst>(&*it);
17411796
if (!CI) {
17421797
++it;
@@ -1805,16 +1860,16 @@ bool LateLowerGCFrame::CleanupIR(Function &F, State *S) {
18051860
size_t nargs = CI->getNumArgOperands();
18061861
size_t nframeargs = nargs - (CC == JLCALL_F_CC);
18071862
SmallVector<Value *, 3> ReplacementArgs;
1808-
auto it = CI->arg_begin();
1863+
auto arg_it = CI->arg_begin();
18091864
if (CC == JLCALL_F_CC) {
1810-
assert(it != CI->arg_end());
1811-
ReplacementArgs.push_back(*(it++));
1865+
assert(arg_it != CI->arg_end());
1866+
ReplacementArgs.push_back(*(arg_it++));
18121867
}
18131868
maxframeargs = std::max(maxframeargs, nframeargs);
18141869
int slot = 0;
18151870
IRBuilder<> Builder (CI);
1816-
for (; it != CI->arg_end(); ++it) {
1817-
Builder.CreateStore(*it, Builder.CreateGEP(T_prjlvalue, Frame,
1871+
for (; arg_it != CI->arg_end(); ++arg_it) {
1872+
Builder.CreateStore(*arg_it, Builder.CreateGEP(T_prjlvalue, Frame,
18181873
ConstantInt::get(T_int32, slot++)));
18191874
}
18201875
ReplacementArgs.push_back(nframeargs == 0 ?

0 commit comments

Comments
 (0)