[llvm-commits] [llvm] r61525 - in /llvm/trunk: include/llvm/ include/llvm/Transforms/ lib/Transforms/IPO/ test/Transforms/AddReadAttrs/ test/Transforms/FunctionAttrs/ tools/opt/ win32/Transforms/

Nick Lewycky nicholas at mxc.ca
Sun Jan 4 11:46:14 PST 2009


Duncan Sands wrote:
> Author: baldrick
> Date: Wed Dec 31 10:14:43 2008
> New Revision: 61525
>
> URL: http://llvm.org/viewvc/llvm-project?rev=61525&view=rev
> Log:
> Rename AddReadAttrs to FunctionAttrs, and teach it how
> to work out (in a very simplistic way) which function
> arguments (pointer arguments only) are only dereferenced
> and so do not escape.  Mark such arguments 'nocapture'.
>   
The whole isCaptured function is very very similar to 
BasicAliasAnalysis.cpp's AddressMightEscape. I think they should be 
merged, probably by making AliasAnalysis expose virtual bool 
AddressMightEscape and having FunctionAttrs use it.

isCaptured is a little fancier in that it's iterative instead of 
recursive and supports PHI nodes, but I prefer the switch(I->getOpcode) 
to a list of if(isa<...>()) statements.

Nick
> +/// isCaptured - Returns whether this pointer value is captured.
> +bool FunctionAttrs::isCaptured(Function &F, Value *V) {
> +  SmallVector<Use*, 16> Worklist;
> +  SmallPtrSet<Use*, 16> Visited;
> +
> +  for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE;
> +       ++UI) {
> +    Use *U = &UI.getUse();
> +    Visited.insert(U);
> +    Worklist.push_back(U);
> +  }
> +
> +  while (!Worklist.empty()) {
> +    Use *U = Worklist.pop_back_val();
> +    Instruction *I = cast<Instruction>(U->getUser());
> +    V = U->get();
> +
> +    if (isa<LoadInst>(I)) {
> +      // Loading a pointer does not cause it to escape.
> +      continue;
> +    }
> +
> +    if (isa<StoreInst>(I)) {
> +      if (V == I->getOperand(0))
> +        // Stored the pointer - escapes.  TODO: improve this.
> +        return true;
> +      // Storing to the pointee does not cause the pointer to escape.
> +      continue;
> +    }
> +
> +    CallSite CS = CallSite::get(I);
> +    if (CS.getInstruction()) {
> +      // Does not escape if only passed via 'nocapture' arguments.  Note
> +      // that calling a function pointer does not in itself cause that
> +      // function pointer to escape.  This is a subtle point considering
> +      // that (for example) the callee might return its own address.  It
> +      // is analogous to saying that loading a value from a pointer does
> +      // not cause the pointer to escape, even though the loaded value
> +      // might be the pointer itself (think of self-referential objects).
> +      CallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end();
> +      for (CallSite::arg_iterator A = B; A != E; ++A)
> +        if (A->get() == V && !CS.paramHasAttr(A-B+1, Attribute::NoCapture))
> +          // The parameter is not marked 'nocapture' - escapes.
> +          return true;
> +      // Only passed via 'nocapture' arguments, or is the called function.
> +      // Does not escape.
> +      continue;
> +    }
> +
> +    if (isa<BitCastInst>(I) || isa<GetElementPtrInst>(I)) {
> +      // Type conversion or calculating an offset.  Does not escape if the new
> +      // value doesn't.
> +      for (Instruction::use_iterator UI = I->use_begin(), UE = I->use_end();
> +           UI != UE; ++UI) {
> +        Use *U = &UI.getUse();
> +        if (Visited.insert(U))
> +          Worklist.push_back(U);
> +      }
> +      continue;
> +    }
> +
> +    // Something else - be conservative and say it escapes.
> +    return true;
> +  }
> +
> +  return false;
> +}
> +
> +/// AddNoCaptureAttrs - Deduce nocapture attributes for the SCC.
> +bool FunctionAttrs::AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC) {
> +  bool Changed = false;
> +
> +  // Check each function in turn, determining which pointer arguments are not
> +  // captured.
> +  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
> +    Function *F = SCC[i]->getFunction();
> +
> +    if (F == 0)
> +      // External node - skip it;
> +      continue;
> +
> +    // Definitions with weak linkage may be overridden at linktime with
> +    // something that writes memory, so treat them like declarations.
> +    if (F->isDeclaration() || F->mayBeOverridden())
> +      continue;
> +
> +    for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A!=E; ++A)
> +      if (isa<PointerType>(A->getType()) && !isCaptured(*F, A)) {
> +        A->addAttr(Attribute::NoCapture);
> +        NumNoCapture++;
> +        Changed = true;
> +      }
> +  }
> +
> +  return Changed;
> +}
> +
> +bool FunctionAttrs::runOnSCC(const std::vector<CallGraphNode *> &SCC) {
> +  bool Changed = AddReadAttrs(SCC);
> +  Changed |= AddNoCaptureAttrs(SCC);
> +  return Changed;
> +}
>   




More information about the llvm-commits mailing list