[cfe-dev] -Wunreachable-code and templates

David Blaikie dblaikie at gmail.com
Tue Feb 14 16:35:49 PST 2012


On Tue, Jan 10, 2012 at 11:48 AM, David Blaikie <dblaikie at gmail.com> wrote:
> On Tue, Jan 10, 2012 at 10:07 AM, Ted Kremenek <kremenek at apple.com> wrote:
>> On Jan 10, 2012, at 8:46 AM, David Blaikie wrote:
>>
>> I haven't done any perf analysis yet - I was asking if there was any
>> recommended approach I should be using to make such measurements.
>>
>> I'll take this answer as implying that there probably isn't much &
>> I'll have a first blush at making my own ad-hoc measurements. I'll
>> repost here once I have any numbers I think might be useful.
>>
>>
>> That's not quite the message I was trying to convey.  :)
>
> Ah - sorry for the misunderstanding.
>
>> As a first pass, I was wondering if you had observed anything noticeable
>> before digging deeper.
>
> Thanks for the clarification. All I've really done so far is run the
> basic regression tests ('make test') & I didn't even look at the time
> very closely - but it didn't pull the compiler to a
> noticeable/ridiculous crawl.
>
>> I'd approach this as follows:
>>
>> (1) Try running turning the warning on by default and run it through all of
>> our benchmark tests, e.g. the GCC testsuite, clang tests, etc.  See if there
>> is a performance regression there.  We regularly do this when measuring
>> compile time regressions.
>
> I'll look into how to run the GCC testsuite (I assume it's documented
> somewhere on the Clang website) & the clang tests are just 'make test'
> or some other tests I should find?
>
> I was also curious about how you measure performance - I can simply
> run "time make test" and look at the user+sys time spent though I was
> wondering if there were particular tools/techniques to reduce noise,
> particular margins of error/thresholds that are used, etc.
>
>> (2) Try building a few real world C++ codebases that are known to use
>> templates (or otherwise make heavy use of C++) with this warning, e.g.
>> Clang, Boost, Blender, Qt and see if there is a noticeable compile-time
>> regression.
>>
>> (3) While doing (2), see if the results of the warning (if any) are
>> acceptable.
>
> Yep - sounds like I've got some issues to work out just in terms of
> correctness anyway (as you suspected, the CFG code might not be
> entirely up to handling uninstantiated templates - I'll see if it's
> very far off) that some more extensive testing would expose. I'll see
> what comes up.
>
>> This is a fair amount of work, but it's the kind of thing we need to do to
>> make this warning production quality.
>
> Fair enough. I suppose one day, ideally, these sort of payloads would
> become part of some amount of automated (infrequent and/or opt-in)
> regression validation that would make this work a bit smoother.

So I've come up with some numbers for feedback.

Experiment:
* Take the attached templates.cpp (it includes every C++11 header
clang can compile (I was using libstdc++ for this), plus a bunch of
boost headers - and a little hand-written sanity check)
* preprocess it (with -std=c++11)
* strip out the line directives (so that clang won't suppress all the
diagnostics because they're in system headers)
* using "perf stat -r100":
  * run with -Wno-everything and either with or without
-Wunreachable-code -c -std=c++11
  * run the same thing with the template_unreachable.diff applied
(I did this at runlevel 1 to try to reduce some of the noise/background)
This is basically the worst case I can think of - lots of templated
code, almost no instantiations or non-templated code.

Results
* you should observe relatively similar results to mine in results.txt except:
  * I pruned the 100 repetitions of diagnostics from the results file,
leaving only one sample of the diagnostic output from the two
-Wunreachable-code runs (with & without my patch applied)
  * I added the check to not build the CFG if we're in a dependent
context and -Wunreachable-code is /not/ enabled after I'd already run
my perf numbers, so the discrepency in my results between the two
versions without the flag enabled should probably not be there (I can
rerun that to demonstrate if desired)

& these were the execution time results I got:

No patch
  No warning: 1.915069815 seconds ( +-  0.02% )
  Warning (10 found): 1.923400323 seconds ( +-  0.02% )
With patch
  No warning: 1.937073564 seconds ( +-  0.03% ) (this should probably
be closer to/the same as the first result - it was just run without
the shortcut as called out above)
  Warning (20 found - including my sanity check): 1.980802759 seconds
( +-  0.03% )

So about a 3% slow down (in the enabled case), according to this
experiment which is a pretty extreme case.

What do you reckon? Good? Bad? Need further data/better experiments?

- David
-------------- next part --------------

 Performance counter stats for '../llvm/install/clang/x86-64/Release/bin/clang++ -std=c++11 -c -Wno-everything templates.pp.cpp' (100 runs):

       3830.833994 task-clock                #    2.000 CPUs utilized            ( +-  0.02% )
                60 context-switches          #    0.000 M/sec                    ( +-  1.08% )
                 4 CPU-migrations            #    0.000 M/sec                    ( +-  2.73% )
             26633 page-faults               #    0.007 M/sec                    ( +-  0.04% )
        4086935496 cycles                    #    1.067 GHz                      ( +-  0.02% )
     <not counted> stalled-cycles-frontend 
     <not counted> stalled-cycles-backend  
        2867079666 instructions              #    0.70  insns per cycle          ( +-  0.03% )
         596838403 branches                  #  155.799 M/sec                    ( +-  0.03% )
          27919213 branch-misses             #    4.68% of all branches          ( +-  0.04% )

       1.915069815 seconds time elapsed                                          ( +-  0.02% )

templates.pp.cpp:19178:107: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((char)(-1) < 0) ? (char)1 << (sizeof(char) * 8 - ((char)(-1) < 0)) : (char)0); }
                                                                                                          ^
templates.pp.cpp:19181:135: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((char)(-1) < 0) ? (((((char)1 << ((sizeof(char) * 8 - ((char)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(char)0); }
                                                                                                                                      ^
templates.pp.cpp:19382:122: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((wchar_t)(-1) < 0) ? (wchar_t)1 << (sizeof(wchar_t) * 8 - ((wchar_t)(-1) < 0)) : (wchar_t)0); }
                                                                                                                         ^
templates.pp.cpp:19385:150: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((wchar_t)(-1) < 0) ? (((((wchar_t)1 << ((sizeof(wchar_t) * 8 - ((wchar_t)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(wchar_t)0); }
                                                                                                                                                     ^
templates.pp.cpp:19451:64: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((char16_t)(-1) < 0) ? (char16_t)1 << (sizeof(char16_t) * 8 - ((char16_t)(-1) < 0)) : (char16_t)0); }
                                                               ^
templates.pp.cpp:19454:68: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((char16_t)(-1) < 0) ? (((((char16_t)1 << ((sizeof(char16_t) * 8 - ((char16_t)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(char16_t)0); }
                                                                   ^
templates.pp.cpp:19521:64: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((char32_t)(-1) < 0) ? (char32_t)1 << (sizeof(char32_t) * 8 - ((char32_t)(-1) < 0)) : (char32_t)0); }
                                                               ^
templates.pp.cpp:19524:68: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((char32_t)(-1) < 0) ? (((((char32_t)1 << ((sizeof(char32_t) * 8 - ((char32_t)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(char32_t)0); }
                                                                   ^
templates.pp.cpp:48715:10: warning: will never be executed [-Wunreachable-code]
 return *new _WordT;
         ^~~~~~~~~~
templates.pp.cpp:109991:35: warning: will never be executed [-Wunreachable-code]
    ((false) ? static_cast<void> (0) : __assert_fail ("false", "/usr/include/boost/variant/detail/forced_return.hpp", 55, __PRETTY_FUNCTION__));
                                  ^
10 warnings generated.

 Performance counter stats for '../llvm/install/clang/x86-64/Release/bin/clang++ -std=c++11 -c -Wno-everything -Wunreachable-code templates.pp.cpp' (100 runs):

       3847.485620 task-clock                #    2.000 CPUs utilized            ( +-  0.02% )
                61 context-switches          #    0.000 M/sec                    ( +-  1.08% )
                 4 CPU-migrations            #    0.000 M/sec                    ( +-  0.60% )
             26452 page-faults               #    0.007 M/sec                    ( +-  0.01% )
        4105284333 cycles                    #    1.067 GHz                      ( +-  0.02% )
     <not counted> stalled-cycles-frontend 
     <not counted> stalled-cycles-backend  
        2890808252 instructions              #    0.70  insns per cycle          ( +-  0.02% )
         602596237 branches                  #  156.621 M/sec                    ( +-  0.02% )
          28161770 branch-misses             #    4.67% of all branches          ( +-  0.05% )

       1.923400323 seconds time elapsed                                          ( +-  0.02% )


 Performance counter stats for '../llvm/build/clang/x86-64/Release/Release/bin/clang++ -std=c++11 -c -Wno-everything templates.pp.cpp' (100 runs):

       3874.837319 task-clock                #    2.000 CPUs utilized            ( +-  0.03% )
                59 context-switches          #    0.000 M/sec                    ( +-  1.13% )
                 5 CPU-migrations            #    0.000 M/sec                    ( +-  2.90% )
             26632 page-faults               #    0.007 M/sec                    ( +-  0.03% )
        4132500264 cycles                    #    1.066 GHz                      ( +-  0.03% )
     <not counted> stalled-cycles-frontend 
     <not counted> stalled-cycles-backend  
        2878471463 instructions              #    0.70  insns per cycle          ( +-  0.04% )
         598763782 branches                  #  154.526 M/sec                    ( +-  0.03% )
          28211407 branch-misses             #    4.71% of all branches          ( +-  0.04% )

       1.937073564 seconds time elapsed                                          ( +-  0.03% )

templates.pp.cpp:19178:107: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((char)(-1) < 0) ? (char)1 << (sizeof(char) * 8 - ((char)(-1) < 0)) : (char)0); }
                                                                                                          ^
templates.pp.cpp:19181:135: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((char)(-1) < 0) ? (((((char)1 << ((sizeof(char) * 8 - ((char)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(char)0); }
                                                                                                                                      ^
templates.pp.cpp:19382:122: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((wchar_t)(-1) < 0) ? (wchar_t)1 << (sizeof(wchar_t) * 8 - ((wchar_t)(-1) < 0)) : (wchar_t)0); }
                                                                                                                         ^
templates.pp.cpp:19385:150: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((wchar_t)(-1) < 0) ? (((((wchar_t)1 << ((sizeof(wchar_t) * 8 - ((wchar_t)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(wchar_t)0); }
                                                                                                                                                     ^
templates.pp.cpp:19451:64: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((char16_t)(-1) < 0) ? (char16_t)1 << (sizeof(char16_t) * 8 - ((char16_t)(-1) < 0)) : (char16_t)0); }
                                                               ^
templates.pp.cpp:19454:68: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((char16_t)(-1) < 0) ? (((((char16_t)1 << ((sizeof(char16_t) * 8 - ((char16_t)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(char16_t)0); }
                                                                   ^
templates.pp.cpp:19521:64: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((char32_t)(-1) < 0) ? (char32_t)1 << (sizeof(char32_t) * 8 - ((char32_t)(-1) < 0)) : (char32_t)0); }
                                                               ^
templates.pp.cpp:19524:68: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((char32_t)(-1) < 0) ? (((((char32_t)1 << ((sizeof(char32_t) * 8 - ((char32_t)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(char32_t)0); }
                                                                   ^
templates.pp.cpp:33007:8: warning: will never be executed [-Wunreachable-code]
       break;
       ^~~~~
templates.pp.cpp:36885:14: warning: will never be executed [-Wunreachable-code]
      return __first1;
             ^~~~~~~~
templates.pp.cpp:36943:14: warning: will never be executed [-Wunreachable-code]
      return __first1;
             ^~~~~~~~
templates.pp.cpp:48476:57: warning: will never be executed [-Wunreachable-code]
 return _M_w[0] + (static_cast<unsigned long long>(_M_w[1])
                                                        ^
templates.pp.cpp:48715:10: warning: will never be executed [-Wunreachable-code]
 return *new _WordT;
         ^~~~~~~~~~
templates.pp.cpp:51380:5: warning: will never be executed [-Wunreachable-code]
    const char* __cs;
    ^~~~~~~~~~~~~~~~~
templates.pp.cpp:109957:35: warning: will never be executed [-Wunreachable-code]
    ((false) ? static_cast<void> (0) : __assert_fail ("false", "/usr/include/boost/variant/detail/backup_holder.hpp", 82, __PRETTY_FUNCTION__));
                                  ^
templates.pp.cpp:109980:35: warning: will never be executed [-Wunreachable-code]
    ((false) ? static_cast<void> (0) : __assert_fail ("false", "/usr/include/boost/variant/detail/forced_return.hpp", 44, __PRETTY_FUNCTION__));
                                  ^
templates.pp.cpp:109991:35: warning: will never be executed [-Wunreachable-code]
    ((false) ? static_cast<void> (0) : __assert_fail ("false", "/usr/include/boost/variant/detail/forced_return.hpp", 55, __PRETTY_FUNCTION__));
                                  ^
templates.pp.cpp:110589:35: warning: will never be executed [-Wunreachable-code]
    ((false) ? static_cast<void> (0) : __assert_fail ("false", "/usr/include/boost/variant/detail/visitation_impl.hpp", 182, __PRETTY_FUNCTION__));
                                  ^
templates.pp.cpp:110614:35: warning: will never be executed [-Wunreachable-code]
    ((false) ? static_cast<void> (0) : __assert_fail ("false", "/usr/include/boost/variant/detail/visitation_impl.hpp", 207, __PRETTY_FUNCTION__));
                                  ^
templates.pp.cpp:113077:12: warning: will never be executed [-Wunreachable-code]
    return 1;
           ^
20 warnings generated.
templates.pp.cpp:19178:107: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((char)(-1) < 0) ? (char)1 << (sizeof(char) * 8 - ((char)(-1) < 0)) : (char)0); }
                                                                                                          ^
templates.pp.cpp:19181:135: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((char)(-1) < 0) ? (((((char)1 << ((sizeof(char) * 8 - ((char)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(char)0); }
                                                                                                                                      ^
templates.pp.cpp:19382:122: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((wchar_t)(-1) < 0) ? (wchar_t)1 << (sizeof(wchar_t) * 8 - ((wchar_t)(-1) < 0)) : (wchar_t)0); }
                                                                                                                         ^
templates.pp.cpp:19385:150: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((wchar_t)(-1) < 0) ? (((((wchar_t)1 << ((sizeof(wchar_t) * 8 - ((wchar_t)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(wchar_t)0); }
                                                                                                                                                     ^
templates.pp.cpp:19451:64: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((char16_t)(-1) < 0) ? (char16_t)1 << (sizeof(char16_t) * 8 - ((char16_t)(-1) < 0)) : (char16_t)0); }
                                                               ^
templates.pp.cpp:19454:68: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((char16_t)(-1) < 0) ? (((((char16_t)1 << ((sizeof(char16_t) * 8 - ((char16_t)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(char16_t)0); }
                                                                   ^
templates.pp.cpp:19521:64: warning: will never be executed [-Wunreachable-code]
      min() throw() { return (((char32_t)(-1) < 0) ? (char32_t)1 << (sizeof(char32_t) * 8 - ((char32_t)(-1) < 0)) : (char32_t)0); }
                                                               ^
templates.pp.cpp:19524:68: warning: will never be executed [-Wunreachable-code]
      max() throw() { return (((char32_t)(-1) < 0) ? (((((char32_t)1 << ((sizeof(char32_t) * 8 - ((char32_t)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(char32_t)0); }
                                                                   ^
templates.pp.cpp:33007:8: warning: will never be executed [-Wunreachable-code]
       break;
       ^~~~~
templates.pp.cpp:36885:14: warning: will never be executed [-Wunreachable-code]
      return __first1;
             ^~~~~~~~
templates.pp.cpp:36943:14: warning: will never be executed [-Wunreachable-code]
      return __first1;
             ^~~~~~~~
templates.pp.cpp:48476:57: warning: will never be executed [-Wunreachable-code]
 return _M_w[0] + (static_cast<unsigned long long>(_M_w[1])
                                                        ^
templates.pp.cpp:48715:10: warning: will never be executed [-Wunreachable-code]
 return *new _WordT;
         ^~~~~~~~~~
templates.pp.cpp:51380:5: warning: will never be executed [-Wunreachable-code]
    const char* __cs;
    ^~~~~~~~~~~~~~~~~
templates.pp.cpp:109957:35: warning: will never be executed [-Wunreachable-code]
    ((false) ? static_cast<void> (0) : __assert_fail ("false", "/usr/include/boost/variant/detail/backup_holder.hpp", 82, __PRETTY_FUNCTION__));
                                  ^
templates.pp.cpp:109980:35: warning: will never be executed [-Wunreachable-code]
    ((false) ? static_cast<void> (0) : __assert_fail ("false", "/usr/include/boost/variant/detail/forced_return.hpp", 44, __PRETTY_FUNCTION__));
                                  ^
templates.pp.cpp:109991:35: warning: will never be executed [-Wunreachable-code]
    ((false) ? static_cast<void> (0) : __assert_fail ("false", "/usr/include/boost/variant/detail/forced_return.hpp", 55, __PRETTY_FUNCTION__));
                                  ^
templates.pp.cpp:110589:35: warning: will never be executed [-Wunreachable-code]
    ((false) ? static_cast<void> (0) : __assert_fail ("false", "/usr/include/boost/variant/detail/visitation_impl.hpp", 182, __PRETTY_FUNCTION__));
                                  ^
templates.pp.cpp:110614:35: warning: will never be executed [-Wunreachable-code]
    ((false) ? static_cast<void> (0) : __assert_fail ("false", "/usr/include/boost/variant/detail/visitation_impl.hpp", 207, __PRETTY_FUNCTION__));
                                  ^
templates.pp.cpp:113077:12: warning: will never be executed [-Wunreachable-code]
    return 1;
           ^
20 warnings generated.

 Performance counter stats for '../llvm/build/clang/x86-64/Release/Release/bin/clang++ -std=c++11 -c -Wno-everything -Wunreachable-code templates.pp.cpp' (100 runs):

       3962.292166 task-clock                #    2.000 CPUs utilized            ( +-  0.03% )
                60 context-switches          #    0.000 M/sec                    ( +-  1.50% )
                 4 CPU-migrations            #    0.000 M/sec                    ( +-  0.64% )
             26410 page-faults               #    0.007 M/sec                    ( +-  0.01% )
        4228325917 cycles                    #    1.067 GHz                      ( +-  0.03% )
     <not counted> stalled-cycles-frontend 
     <not counted> stalled-cycles-backend  
        2955751682 instructions              #    0.70  insns per cycle          ( +-  0.03% )
         615742816 branches                  #  155.401 M/sec                    ( +-  0.03% )
          29309922 branch-misses             #    4.76% of all branches          ( +-  0.04% )

       1.980802759 seconds time elapsed                                          ( +-  0.03% )

-------------- next part --------------
A non-text attachment was scrubbed...
Name: template_unreachable.diff
Type: application/octet-stream
Size: 6561 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20120214/e6152f98/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: templates.cpp
Type: text/x-c++src
Size: 1688 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20120214/e6152f98/attachment.cpp>


More information about the cfe-dev mailing list