Skip to content

Commit 1ea6bd8

Browse files
Maqrkkyuri91
authored andcommitted
Lower thread locals used in Constant Expressions in genericjs
1 parent 230b96d commit 1ea6bd8

File tree

2 files changed

+42
-12
lines changed

2 files changed

+42
-12
lines changed

llvm/lib/CheerpUtils/ConstantExprLowering.cpp

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ bool ConstantExprLowering::runOnFunction(Function& F, bool& hasI64, const Target
3131
bool Changed = false;
3232
hasI64 = false;
3333

34+
Module* M = F.getParent();
35+
Function* getThreadLocalAddress = M->getFunction("__getThreadLocalAddress");
3436
DL = &F.getParent()->getDataLayout();
3537

3638
std::set<ConstantExpr*> visitedCE;
@@ -102,28 +104,55 @@ bool ConstantExprLowering::runOnFunction(Function& F, bool& hasI64, const Target
102104

103105
std::map<ConstantExpr*, Value*> mapCEToValue;
104106
std::map<GlobalValue*, Instruction*> mapGVToInst;
107+
// This is the insert point for the instructionized CEs. We update it so that
108+
// new ones are inserted before earlier ones.
109+
Instruction* ceInsertPt = F.getEntryBlock().getFirstNonPHI();
105110

106111
// 2. Iterate on the collected ConstantExpr, converting them to Instructions
107112
// Note that given the specific order of the visit, operands will be processed later (= will end up dominating their users)
108113
for (ConstantExpr* CE : toBeInstructionized)
109114
{
110115
Instruction* Conv = CE->getAsInstruction();
116+
Conv->insertBefore(ceInsertPt);
117+
ceInsertPt = Conv;
111118
for (auto& O: Conv->operands())
112119
{
120+
// 3. Process non-CE operands if needed. New instructions created
121+
// here go before all the CE instructions
113122
Value* NewC = O.get();
114123
if (auto *GV = dyn_cast<GlobalVariable>(NewC))
115124
{
116125
// In asmjs, addresses of globals are just integers
117126
// Ask LinearMemoryHelper for the value and cast to the pointer type
118127
if (!WasmSharedModule && GV->GlobalValue::getSection() == StringRef("asmjs") && !GV->isThreadLocal())
119128
{
120-
if (mapGVToInst.count(GV) == 0)
129+
auto it = mapGVToInst.find(GV);
130+
if (it == mapGVToInst.end())
121131
{
122132
auto *CI = ConstantInt::get(IntegerType::get(Conv->getContext(), 32), LH->getGlobalVariableAddress(GV));
123-
mapGVToInst[GV] = CastInst::Create(Instruction::IntToPtr, CI, NewC->getType());
133+
it = mapGVToInst.emplace(GV, CastInst::Create(Instruction::IntToPtr, CI, NewC->getType())).first;
134+
// Insert before all the CEs
135+
it->second->insertBefore(F.getEntryBlock().getFirstNonPHI());
124136
}
125-
126-
NewC = mapGVToInst.at(GV);
137+
NewC = it->second;
138+
}
139+
else if (GV->isThreadLocal() && F.getSection() != "asmjs")
140+
{
141+
auto it = mapGVToInst.find(GV);
142+
if (it == mapGVToInst.end())
143+
{
144+
// Insert before all the CEs
145+
Instruction* insertPt = F.getEntryBlock().getFirstNonPHI();
146+
// Access thread locals via the __getThreadLocalAddress wrapper
147+
Type* argTy = GV->getType();
148+
Function* getThreadLocalOffset = Intrinsic::getDeclaration(M, Intrinsic::cheerp_get_threadlocal_offset, argTy);
149+
auto* offset = CallInst::Create(getThreadLocalOffset, {GV}, "tl.offset", insertPt);
150+
Instruction* addr = CallInst::Create(getThreadLocalAddress, {offset}, "tl.addr", insertPt);
151+
if (addr->getType() != GV->getType())
152+
addr = CastInst::CreateBitOrPointerCast(addr, argTy, "tl.cast", insertPt);
153+
it = mapGVToInst.emplace(GV, addr).first;
154+
}
155+
NewC = it->second;
127156
}
128157
}
129158
else if (isa<UndefValue>(NewC) && NewC->getType()->isFloatingPointTy())
@@ -134,17 +163,9 @@ bool ConstantExprLowering::runOnFunction(Function& F, bool& hasI64, const Target
134163
}
135164
O.set(NewC);
136165
}
137-
Conv->insertBefore(F.getEntryBlock().getFirstNonPHI());
138166
Changed = true;
139167
mapCEToValue[CE] = Conv;
140168
}
141-
142-
// 3. Insert also PtrToIntInst that has been created while folding GV
143-
for (auto& pair : mapGVToInst)
144-
{
145-
pair.second->insertBefore(F.getEntryBlock().getFirstNonPHI());
146-
}
147-
148169
// 4. Actually substitute any ConstantExpr operand with the mapped Instruction (that will be in the Function entry BB)
149170
std::map<ConstantVector*, Value*> mapCVToValue;
150171
for (Instruction& I : instructions(F))

llvm/lib/CheerpUtils/GlobalDepsAnalyzer.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,15 @@ bool GlobalDepsAnalyzer::runOnModule( llvm::Module & module )
855855
llvm::errs() << "warning: _startPreThread function point not found, and -pthread is linked\n";
856856
}
857857

858+
// Keep the __getThreadLocalAddress function alive if it exists.
859+
llvm::Function* getThreadLocalAddress = module.getFunction("__getThreadLocalAddress");
860+
if (getThreadLocalAddress)
861+
{
862+
extendLifetime(getThreadLocalAddress);
863+
// __getThreadLocalAddress is always tagged asmjs.
864+
asmJSExportedFunctions.insert(getThreadLocalAddress);
865+
}
866+
858867
// Flush out all functions
859868
processEnqueuedFunctions();
860869

0 commit comments

Comments
 (0)