[llvm-commits] [Patch] Make GlobalOpt conservative with TLS vars (PR14309, 3.2-blocker)

Nick Lewycky nicholas at mxc.ca
Thu Nov 15 03:07:16 PST 2012


Hans Wennborg wrote:
> Thanks for the review, Nick! Attaching new patch addressing your comments.

+    const Constant *C = WorkList.back();
+    WorkList.pop_back();

const Constant *C = WorkList.pop_back_val();

+      if (!Visited.count(D)) {
+        WorkList.push_back(D);
+        Visited.insert(C);
+      }
'
if (Visited.insert(D)) {
   WorkList.push_back(D);
}

LGTM!

Nick

> On Tue, Nov 13, 2012 at 7:47 PM, Nick Lewycky<nicholas at mxc.ca>  wrote:
>> Hans Wennborg wrote:
>>>
>>> Hi all,
>>>
>>> The attached patch takes a stab at fixing PR14309 which was marked as
>>> a 3.2-blocker.
>>>
>>> For global variables which get the same value stored into them
>>> everywhere, GlobalOpt will replace them with a constant. The problem
>>> is that a thread-local GlobalVariable looks like one value, but is
>>> different between threads.
>>
>> +/// isThreadDependent - Return true if the value can vary between threads.
>> +bool Constant::isThreadDependent() const {
>> +  if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(this))
>> +    return GV->isThreadLocal();
>> +
>> +  for (unsigned I = 0, E = getNumOperands(); I != E; ++I) {
>> +    if (const Constant *C = dyn_cast<Constant>(getOperand(I))) {
>>
>> Use cast<>  instead of dyn_cast<>  here. Constant operands are always
>> constants.
>
> Done.
>
>> +      if (C->isThreadDependent())
>>
>> Two things. Firstly, I'm worried about stack depth, so I'd rather this
>> function maintained its own worklist.
>
> Done.
>
>> Secondly, I'm worried about callers
>> using this as part of their own constant visiting and accidentally forming
>> an O(n^2) loop, because this function doesn't expose a cache or anything.
>> You needn't do anything about point #2 though, there are many places in llvm
>> to fall into that particular trap.
>
> OK. I won't worry about this for now, then.
>
>> @@ -234,6 +235,14 @@ static bool AnalyzeGlobal(const Value *V, GlobalStatus
>> &GS,
>>
>>             if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(
>>
>> SI->getOperand(1))) {
>>               Value *StoredVal = SI->getOperand(0);
>> +
>> +            if (Constant *C = dyn_cast<Constant>(StoredVal)) {
>> +              if (C->isThreadDependent()) {
>> +                // The stored value changes between threads; don't track
>> it.
>>
>> +                return true;
>> +              }
>> +            }
>> +
>>               if (StoredVal == GV->getInitializer()) {
>>                 if (GS.StoredType<  GlobalStatus::isInitializerStored)
>>                   GS.StoredType = GlobalStatus::isInitializerStored;
>>
>> This is really scary. I didn't understand why you needed to to this until I
>> understood the test. (I thought the bug was that we weren't copying the TLS
>> bit to the new global at line 1819. Nope!)
>
> Indeed.
>
>>> Also, if anyone thinks there are more passes which assume that
>>> thread-local GlobalVariables have the same value everywhere, please
>>> let me know.
>>
>> The memdep users for a start; memdep itself, gvn, dse. I think what's been
>> saving us is that nobody marks their "create a thread" function as readonly.
>
> But memdep, gvn and dse are all function passes, right? I think
> (please correct me if I'm wrong here) it's safe to assume that a TLS
> variable has a constant address within a function, so this kind of
> problem only arises for inter-procedural optimizations/analyses.

You're right. Creating a thread, unlike forking, happens to take a 
function address for the thread_start. I don't know of any OS where you 
can create a thread like you fork.

> I don't understand your comment about readonly "create a
> thread"-functions. What does that imply?
>
>> I think this is just another reason we need to kill ConstantExpr, and forbid
>> expressions involving TLS to be constant.
>
> Has there been previous talk about killing ConstantExpr?

Yes, PR10368.

> Yes, the fundamental problem here is really that a TLS variable is a
> GlobalVariable, and therefore also Constant -- and it turns out that
> we can't assume that it's constant between functions :/
>
> Thanks,
> Hans




More information about the llvm-commits mailing list