<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Sorry for the breakage.  Hans, thanks for fixing this.<br>
    <br>
    Philip<br>
    <br>
    <div class="moz-cite-prefix">On 08/31/2015 02:08 PM, Yaron Keren
      wrote:<br>
    </div>
    <blockquote
cite="mid:CANa4zJpj0TJGocmJ8K5jUN20y35ykm6smva5LmA6wir-sJU2HQ@mail.gmail.com"
      type="cite">
      <div dir="rtl">
        <div dir="ltr">This may be breaking the Visual C++ builders:</div>
        <div dir="ltr"><br>
        </div>
        <div dir="ltr"> <a moz-do-not-send="true"
href="http://lab.llvm.org:8011/builders/lldb-x86-win7-msvc/builds/8864/steps/build/logs/stdio">http://lab.llvm.org:8011/builders/lldb-x86-win7-msvc/builds/8864/steps/build/logs/stdio</a><br>
        </div>
        <div dir="ltr"><br>
        </div>
        <div dir="ltr">dbgs() requiring llvm/Support/raw_ostream.h.</div>
        <div dir="ltr"><br>
        </div>
        <div dir="ltr"><br>
        </div>
      </div>
      <div class="gmail_extra"><br>
        <div class="gmail_quote">
          <div dir="ltr">2015-08-31 22:44 GMT+03:00 Philip Reames via
            llvm-commits <span dir="ltr"><<a moz-do-not-send="true"
                href="mailto:llvm-commits@lists.llvm.org"
                target="_blank">llvm-commits@lists.llvm.org</a>></span>:</div>
          <blockquote class="gmail_quote" style="margin:0 0 0
            .8ex;border-left:1px #ccc solid;padding-left:1ex">Author:
            reames<br>
            Date: Mon Aug 31 14:44:38 2015<br>
            New Revision: 246476<br>
            <br>
            URL: <a moz-do-not-send="true"
              href="http://llvm.org/viewvc/llvm-project?rev=246476&view=rev"
              rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=246476&view=rev</a><br>
            Log:<br>
            [FunctionAttr] Infer nonnull attributes on returns<br>
            <br>
            Teach FunctionAttr to infer the nonnull attribute on return
            values of functions which never return a potentially null
            value. This is done both via a conservative local analysis
            for the function itself and a optimistic per-SCC analysis.
            If no function in the SCC returns anything which could be
            null (other than values from other functions in the SCC), we
            can conclude no function returned a null pointer. Even if
            some function within the SCC returns a null pointer, we may
            be able to locally conclude that some don't.<br>
            <br>
            Differential Revision: <a moz-do-not-send="true"
              href="http://reviews.llvm.org/D9688" rel="noreferrer"
              target="_blank">http://reviews.llvm.org/D9688</a><br>
            <br>
            <br>
            Added:<br>
                llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll<br>
            Modified:<br>
                llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp<br>
            <br>
            Modified: llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp<br>
            URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp?rev=246476&r1=246475&r2=246476&view=diff"
              rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp?rev=246476&r1=246475&r2=246476&view=diff</a><br>
==============================================================================<br>
            --- llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp
            (original)<br>
            +++ llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp Mon Aug
            31 14:44:38 2015<br>
            @@ -27,10 +27,12 @@<br>
             #include "llvm/Analysis/CallGraph.h"<br>
             #include "llvm/Analysis/CallGraphSCCPass.h"<br>
             #include "llvm/Analysis/CaptureTracking.h"<br>
            +#include "llvm/Analysis/ValueTracking.h"<br>
             #include "llvm/IR/GlobalVariable.h"<br>
             #include "llvm/IR/InstIterator.h"<br>
             #include "llvm/IR/IntrinsicInst.h"<br>
             #include "llvm/IR/LLVMContext.h"<br>
            +#include "llvm/Support/Debug.h"<br>
             #include "llvm/Analysis/TargetLibraryInfo.h"<br>
             using namespace llvm;<br>
            <br>
            @@ -42,6 +44,7 @@ STATISTIC(NumNoCapture, "Number of argum<br>
             STATISTIC(NumReadNoneArg, "Number of arguments marked
            readnone");<br>
             STATISTIC(NumReadOnlyArg, "Number of arguments marked
            readonly");<br>
             STATISTIC(NumNoAlias, "Number of function returns marked
            noalias");<br>
            +STATISTIC(NumNonNullReturn, "Number of function returns
            marked nonnull");<br>
             STATISTIC(NumAnnotated, "Number of attributes added to
            library functions");<br>
            <br>
             namespace {<br>
            @@ -67,6 +70,13 @@ namespace {<br>
                 // AddNoAliasAttrs - Deduce noalias attributes for the
            SCC.<br>
                 bool AddNoAliasAttrs(const CallGraphSCC &SCC);<br>
            <br>
            +    /// \brief Does this function return null?<br>
            +    bool ReturnsNonNull(Function *F,
            SmallPtrSet<Function*, 8> &,<br>
            +                        bool &Speculative) const;<br>
            +<br>
            +    /// \brief Deduce nonnull attributes for the SCC.<br>
            +    bool AddNonNullAttrs(const CallGraphSCC &SCC);<br>
            +<br>
                 // Utility methods used by inferPrototypeAttributes to
            add attributes<br>
                 // and maintain annotation statistics.<br>
            <br>
            @@ -832,6 +842,143 @@ bool
            FunctionAttrs::AddNoAliasAttrs(cons<br>
               return MadeChange;<br>
             }<br>
            <br>
            +bool FunctionAttrs::ReturnsNonNull(Function *F,<br>
            +                                 
             SmallPtrSet<Function*, 8> &SCCNodes,<br>
            +                                   bool &Speculative)
            const {<br>
            +  assert(F->getReturnType()->isPointerTy() &&<br>
            +         "nonnull only meaningful on pointer types");<br>
            +  Speculative = false;<br>
            +<br>
            +  SmallSetVector<Value *, 8> FlowsToReturn;<br>
            +  for (BasicBlock &BB : *F)<br>
            +    if (auto *Ret =
            dyn_cast<ReturnInst>(BB.getTerminator()))<br>
            +      FlowsToReturn.insert(Ret->getReturnValue());<br>
            +<br>
            +  for (unsigned i = 0; i != FlowsToReturn.size(); ++i) {<br>
            +    Value *RetVal = FlowsToReturn[i];<br>
            +<br>
            +    // If this value is locally known to be non-null, we're
            good<br>
            +    if (isKnownNonNull(RetVal, TLI))<br>
            +      continue;<br>
            +<br>
            +    // Otherwise, we need to look upwards since we can't
            make any local<br>
            +    // conclusions.<br>
            +    Instruction *RVI = dyn_cast<Instruction>(RetVal);<br>
            +    if (!RVI)<br>
            +      return false;<br>
            +    switch (RVI->getOpcode()) {<br>
            +      // Extend the analysis by looking upwards.<br>
            +    case Instruction::BitCast:<br>
            +    case Instruction::GetElementPtr:<br>
            +    case Instruction::AddrSpaceCast:<br>
            +      FlowsToReturn.insert(RVI->getOperand(0));<br>
            +      continue;<br>
            +    case Instruction::Select: {<br>
            +      SelectInst *SI = cast<SelectInst>(RVI);<br>
            +      FlowsToReturn.insert(SI->getTrueValue());<br>
            +      FlowsToReturn.insert(SI->getFalseValue());<br>
            +      continue;<br>
            +    }<br>
            +    case Instruction::PHI: {<br>
            +      PHINode *PN = cast<PHINode>(RVI);<br>
            +      for (int i = 0, e = PN->getNumIncomingValues(); i
            != e; ++i)<br>
            +        FlowsToReturn.insert(PN->getIncomingValue(i));<br>
            +      continue;<br>
            +    }<br>
            +    case Instruction::Call:<br>
            +    case Instruction::Invoke: {<br>
            +      CallSite CS(RVI);<br>
            +      Function *Callee = CS.getCalledFunction();<br>
            +      // A call to a node within the SCC is assumed to
            return null until<br>
            +      // proven otherwise<br>
            +      if (Callee && SCCNodes.count(Callee)) {<br>
            +        Speculative = true;<br>
            +        continue;<br>
            +      }<br>
            +      return false;<br>
            +    }<br>
            +    default:<br>
            +      return false;  // Unknown source, may be null<br>
            +    };<br>
            +    llvm_unreachable("should have either continued or
            returned");<br>
            +  }<br>
            +<br>
            +  return true;<br>
            +}<br>
            +<br>
            +bool FunctionAttrs::AddNonNullAttrs(const CallGraphSCC
            &SCC) {<br>
            +  SmallPtrSet<Function*, 8> SCCNodes;<br>
            +<br>
            +  // Fill SCCNodes with the elements of the SCC.  Used for
            quickly<br>
            +  // looking up whether a given CallGraphNode is in this
            SCC.<br>
            +  for (CallGraphSCC::iterator I = SCC.begin(), E =
            SCC.end(); I != E; ++I)<br>
            +    SCCNodes.insert((*I)->getFunction());<br>
            +<br>
            +  // Speculative that all functions in the SCC return only
            nonnull<br>
            +  // pointers.  We may refute this as we analyze functions.<br>
            +  bool SCCReturnsNonNull = true;<br>
            +<br>
            +  bool MadeChange = false;<br>
            +<br>
            +  // Check each function in turn, determining which
            functions return nonnull<br>
            +  // pointers.<br>
            +  for (CallGraphSCC::iterator I = SCC.begin(), E =
            SCC.end(); I != E; ++I) {<br>
            +    Function *F = (*I)->getFunction();<br>
            +<br>
            +    if (!F ||
            F->hasFnAttribute(Attribute::OptimizeNone))<br>
            +      // External node or node we don't want to optimize -
            skip it;<br>
            +      return false;<br>
            +<br>
            +    // Already nonnull.<br>
            +    if
            (F->getAttributes().hasAttribute(AttributeSet::ReturnIndex,<br>
            +                                       
            Attribute::NonNull))<br>
            +      continue;<br>
            +<br>
            +    // Definitions with weak linkage may be overridden at
            linktime, so<br>
            +    // treat them like declarations.<br>
            +    if (F->isDeclaration() || F->mayBeOverridden())<br>
            +      return false;<br>
            +<br>
            +    // We annotate nonnull return values, which are only
            applicable to<br>
            +    // pointer types.<br>
            +    if (!F->getReturnType()->isPointerTy())<br>
            +      continue;<br>
            +<br>
            +    bool Speculative = false;<br>
            +    if (ReturnsNonNull(F, SCCNodes, Speculative)) {<br>
            +      if (!Speculative) {<br>
            +        // Mark the function eagerly since we may discover
            a function<br>
            +        // which prevents us from speculating about the
            entire SCC<br>
            +        DEBUG(dbgs() << "Eagerly marking " <<
            F->getName() << " as nonnull\n");<br>
            +        F->addAttribute(AttributeSet::ReturnIndex,
            Attribute::NonNull);<br>
            +        ++NumNonNullReturn;<br>
            +        MadeChange = true;<br>
            +      }<br>
            +      continue;<br>
            +    }<br>
            +    // At least one function returns something which could
            be null, can't<br>
            +    // speculate any more.<br>
            +    SCCReturnsNonNull = false;<br>
            +  }<br>
            +<br>
            +  if (SCCReturnsNonNull) {<br>
            +    for (CallGraphSCC::iterator I = SCC.begin(), E =
            SCC.end(); I != E; ++I) {<br>
            +      Function *F = (*I)->getFunction();<br>
            +      if
            (F->getAttributes().hasAttribute(AttributeSet::ReturnIndex,<br>
            +                                         
            Attribute::NonNull) ||<br>
            +          !F->getReturnType()->isPointerTy())<br>
            +        continue;<br>
            +<br>
            +      DEBUG(dbgs() << "SCC marking " <<
            F->getName() << " as nonnull\n");<br>
            +      F->addAttribute(AttributeSet::ReturnIndex,
            Attribute::NonNull);<br>
            +      ++NumNonNullReturn;<br>
            +      MadeChange = true;<br>
            +    }<br>
            +  }<br>
            +<br>
            +  return MadeChange;<br>
            +}<br>
            +<br>
             /// inferPrototypeAttributes - Analyze the name and
            prototype of the<br>
             /// given function and set any applicable attributes. 
            Returns true<br>
             /// if any attributes were set and false otherwise.<br>
            @@ -1707,5 +1854,6 @@ bool
            FunctionAttrs::runOnSCC(CallGraphSC<br>
               Changed |= AddReadAttrs(SCC);<br>
               Changed |= AddArgumentAttrs(SCC);<br>
               Changed |= AddNoAliasAttrs(SCC);<br>
            +  Changed |= AddNonNullAttrs(SCC);<br>
               return Changed;<br>
             }<br>
            <br>
            Added: llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll<br>
            URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll?rev=246476&view=auto"
              rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll?rev=246476&view=auto</a><br>
==============================================================================<br>
            --- llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll
            (added)<br>
            +++ llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll Mon
            Aug 31 14:44:38 2015<br>
            @@ -0,0 +1,74 @@<br>
            +; RUN: opt -S -functionattrs %s | FileCheck %s<br>
            +declare nonnull i8* @ret_nonnull()<br>
            +<br>
            +; Return a pointer trivially nonnull (call return
            attribute)<br>
            +define i8* @test1() {<br>
            +; CHECK: define nonnull i8* @test1<br>
            +  %ret = call i8* @ret_nonnull()<br>
            +  ret i8* %ret<br>
            +}<br>
            +<br>
            +; Return a pointer trivially nonnull (argument attribute)<br>
            +define i8* @test2(i8* nonnull %p) {<br>
            +; CHECK: define nonnull i8* @test2<br>
            +  ret i8* %p<br>
            +}<br>
            +<br>
            +; Given an SCC where one of the functions can not be marked
            nonnull,<br>
            +; can we still mark the other one which is trivially
            nonnull<br>
            +define i8* @scc_binder() {<br>
            +; CHECK: define i8* @scc_binder<br>
            +  call i8* @test3()<br>
            +  ret i8* null<br>
            +}<br>
            +<br>
            +define i8* @test3() {<br>
            +; CHECK: define nonnull i8* @test3<br>
            +  call i8* @scc_binder()<br>
            +  %ret = call i8* @ret_nonnull()<br>
            +  ret i8* %ret<br>
            +}<br>
            +<br>
            +; Given a mutual recursive set of functions, we can mark
            them<br>
            +; nonnull if neither can ever return null.  (In this case,
            they<br>
            +; just never return period.)<br>
            +define i8* @test4_helper() {<br>
            +; CHECK: define noalias nonnull i8* @test4_helper<br>
            +  %ret = call i8* @test4()<br>
            +  ret i8* %ret<br>
            +}<br>
            +<br>
            +define i8* @test4() {<br>
            +; CHECK: define noalias nonnull i8* @test4<br>
            +  %ret = call i8* @test4_helper()<br>
            +  ret i8* %ret<br>
            +}<br>
            +<br>
            +; Given a mutual recursive set of functions which *can*
            return null<br>
            +; make sure we haven't marked them as nonnull.<br>
            +define i8* @test5_helper() {<br>
            +; CHECK: define noalias i8* @test5_helper<br>
            +  %ret = call i8* @test5()<br>
            +  ret i8* null<br>
            +}<br>
            +<br>
            +define i8* @test5() {<br>
            +; CHECK: define noalias i8* @test5<br>
            +  %ret = call i8* @test5_helper()<br>
            +  ret i8* %ret<br>
            +}<br>
            +<br>
            +; Local analysis, but going through a self recursive phi<br>
            +define i8* @test6() {<br>
            +entry:<br>
            +; CHECK: define nonnull i8* @test6<br>
            +  %ret = call i8* @ret_nonnull()<br>
            +  br label %loop<br>
            +loop:<br>
            +  %phi = phi i8* [%ret, %entry], [%phi, %loop]<br>
            +  br i1 undef, label %loop, label %exit<br>
            +exit:<br>
            +  ret i8* %phi<br>
            +}<br>
            +<br>
            +<br>
            <br>
            <br>
            _______________________________________________<br>
            llvm-commits mailing list<br>
            <a moz-do-not-send="true"
              href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
            <a moz-do-not-send="true"
              href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits"
              rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
          </blockquote>
        </div>
        <br>
      </div>
    </blockquote>
    <br>
  </body>
</html>