[LLVMdev] [RFC] add Function Attribute to disable optimization

Nick Lewycky nicholas at mxc.ca
Thu Jul 18 09:38:29 PDT 2013


Andrea_DiBiagio at sn.scee.net wrote:
> So..
> I have investigated more on how a new function attribute to disable
> optimization on a per-function basis could be implemented.
> At the current state, with the lack of specific support from the pass
> managers I found two big problems when trying to implement a prototype
> implementation of the new attribute.
>
> Here are the problems found:
> 1) It is not safe to disable some transform passes in the backend.

Hold on. By 'backend' do you mean LLVM IR FunctionPasses, or LLVM 
CodeGen MachineFunctionPasses? The former you should be able to turn 
off, reorder, etc., at will. The latter is a fixed pipeline, you either 
choose the -O0 pipeline or the -O2 pipeline.

If you find that turning off IR-level passes is triggering assertions, 
please start filing bugs.

Nick

> It looks like there are some unwritten dependences between passes and
> disrupting the sequence of passes to run may result in unexpected crashes
> and/or assertion failures;
> 2)  The fact that pass managers are not currently designed to support
> per-function optimization makes it difficult to find a reasonable way to
> implement this new feature.
>
> About point 2. the Idea that came in my mind consisted in making passes
> aware of the 'noopt' attribute.
> In my experiment:
>   - I added a virtual method called 'mustAlwaysRun' in class Pass that
> 'returns true if it is not safe to disable this pass'.
> If a pass does not override the default implementation of that method,
> then by default it will always return true (i.e. the pass "must
> always run" pass even when attribute 'noopt' is specified).
>   - I then redefined in override that method on all the optimization passes
> that could have been safely turned off when attribute noopt was present.
> In my experiment, I specifically didn't disable Module Passes;
>   - Then I modified the 'doInitialize()' 'run*()' and 'doFinalize' methods
> in Pass Manger to check for both the presence of attribute noopt AND the
> value returned by method 'mustAlwaysRun' called on the current pass
> instance.
>
> That experiment seemed to "work" on a few tests and benchmarks.
> However:
>   a) 'noopt' wouldn't really imply no optimization, since not all codegen
> optimization passes can be safely disabled. As a result, the assembly
> produced for noopt functions had few differences with respect to the
> assembly generated for the same functions at -O0;
>   b) I don't particularly like the idea of making passes "aware" of the
> 'noopt' attribute. However, I don't know if there is a reasonable way to
> implement the noopt attribute without having to re-design how pass
> managers work.
>    c)  Because of a. and b.,  I am concerned that a change like the one
> described above won't be accepted. If so however, I would be really
> interested in the feedback from the community. Maybe there are better ways
> to implement 'noopt' which I don't know/didn't think about?
>
> As I said, I am not very happy with the proposed solution and any feedback
> would be really appreciated at this point.
>
> By the way, here is how I thought the 'noopt' proposal could have been
> contributed in terms of patches:
>
> [LLVM IR][Patch 1]
> ================
> This patch extends the IR adding a new attribute called 'noopt'.
> Below, is a sequence of steps which describes how to implement this patch.
>
> 1) Add a definition for attribute 'noopt' in File llvm/IR/Attribute.h;
> 2) Teach how attribute 'noopt' should be encoded and also how to print it
> out
>     as a string value (File lib/IR/Attributes.cpp);
> 2b) Add a new enum value for the new attribute in enum LLVMAttribute
>      (File "include/llvm-c/Core.h");
> 3) The new attribute is a function attribute;
>     Teach the verifier pass that 'noopt' is a function attribute;
>     Add checks in method VerifyAttributeTypes() (File lib/IR/Verifier.cpp):
>     * NoOpt is a function-only attribute;
>     * Assert if NoOpt is used in the same context as alwaysinline;
>     * Assert if NoOpt is used in the same context as OptimizeForSize
> (needed?);
>     * Assert if NoOpt is used in the same context as MinSize (needed?).
> 4) Add a LLVM test in test/Feature to verify that we correctly disassemble
>     the new function attribute (see for example file cold.ll);
> 5) Teach the AsmParser how to parse the new attribute:
>   * Add a new token for the new attribute noopt;
>   * Add rules to parse the new token;
> 6) Add a description of the new attribute in "docs/LangRef.rst";
>
> [LLVM][Opt][Patch 2]
> ==================
> This patch implements the required changes to passes and pass managers.
> Below, is a sequence of steps which describes how to implement this patch.
>
> 1) Make the new inliner aware of the new flag.
>   * In lib/Transforms/IPO/Inliner.cpp:
>     ** do not inline the callee if it is not always_inline and the caller
> is marked 'noopt'.
>   * No other changes are required since 'noopt' already implies 'noinline'.
> 2) Tell the pass manager which transform passes can be safely disabled
> with 'noopt'.
>
> [CLANG][Patch 3]
> ===============
> This patch teaches clang how to parse and generate code for functions that
> are marked with attribute 'noopt'.
>
> 1) Lex
>   * Add a new token for the 'noopt' keyword.
>   * That keyword is for a function attribute.
> 2) Sema
>   * Add a rule to handle the case where noopt is passed as function
> attribute.
>   * check that the attribute does not take extra arguments.
>   * check that the attribute is associated to a function declaration.
>   * Add the attribute to the IR Set of Attributes.
> 3) CodeGen
>   * noopt implies 'noinline.
>   * noopt always wins over always_inline
>   * noopt does not win over 'naked': naked functions only contain asm
>     statements. This attribute is only valid for ARM, AVX, MCORE, RL78, RX
> and
>     SPU to indicate that the specified function does not need
> prologue/epilogue
>     sequence generated by the compiler. (NOTE: this constraint can be
> removed).
> 4) Add clang tests:
>   * in test/Sema:
>     ** Verify that noopt only applies to functions. (-cc1 -fsyntax-only
> -verify)
>   * in test/CodeGen:
>     ** Check that noopt implies noinline
>     ** Check combinations of noopt and noinline and always_inline
>
>
> Andrea Di Biagio
> SN Systems - Sony Computer Entertainment Group.
>
> Andrea DiBiagio/SN R&D/BS/UK/SCEE wrote on 25/06/2013 15:20:12:
>
>> From: Andrea DiBiagio/SN R&D/BS/UK/SCEE
>> To: Nick Lewycky<nicholas at mxc.ca>
>> Cc: cfe-dev at cs.uiuc.edu, llvmdev at cs.uiuc.edu
>> Date: 25/06/2013 15:20
>> Subject: Re: [LLVMdev] [RFC] add Function Attribute to disable
> optimization
>>
>> Hi Nick,
>>
>>> From: Nick Lewycky<nicholas at mxc.ca>
>>>> This proposal is to create a new function-level attribute which
> would tell
>>>> the compiler to not to perform any optimizing transformations on the
>>>> specified function.
>>>
>>> What about module passes? Do you want to disable all module passes in
> a
>>> TU which contains a single one of these? I'll be unhappy if we need to
>
>>> litter checks throughout the module passes that determine whether a
>>> given instruction is inside an unoptimizable function or not. Saying
>>> that module passes are exempt from checking the 'noopt' attribute is
>>> fine to me, but then somebody needs to know how to module passes (and
>>> users may be surprised to discover that adding such an annotation to
> one
>>> function will cause seemingly-unrelated functions to become less
> optimized).
>
>> Right, module passes are a difficult case.
>> I understand your point. I think ignoring the `noopt' attribute (or
>> whatever we want to call it) may be the best approach in this case:
>> it avoid the problems you describe but should still be sufficient
>> for the purposes we care about. I am currently studying the module
>> passes in more details to be certain about this.
>
>> Thanks for the useful feedback,
>> Andrea Di Biagio
>> SN Systems - Sony Computer Entertainment Group
>>
>>>> The use-case is to be able to selectively disable optimizations when
>>>> debugging a small number of functions in a compilation unit to
> provide an
>>>> -O0-like quality of debugging in cases where compiling the whole
> unit at
>>>> anything less than full optimization would make the program run too
>>>> slowly.  A useful secondary-effect of this feature would be to allow
> users
>>>> to temporarily work-around optimization bugs in LLVM without having
> to
>>>> reduce the optimization level for the whole compilation unit,
> however we
>>>> do not consider this the most important use-case.
>>>>
>>>> Our suggestion for the name for this attribute is "optnone" which
> seems to
>>>> be in keeping with the existing "optsize" attribute, although it
> could
>>>> equally be called "noopt" or something else entirely.  It would be
> exposed
>>>> to Clang users through __attribute__((optnone)) or [[optnone]].
>>>>
>>>> I would like to discuss this proposal with the rest of the community
> to
>>>> share opinions and have feedback on this.
>>>>
>>>> ===================================================
>>>> Interactions with the existing function attributes:
>>>>
>>>> LLVM allows to decorate functions with 'noinline', alwaysinline' and
>>>> 'inlinehint'.  We think that it makes sense for 'optnone' to
> implicitly
>>>> imply 'noinline' (at least from a user's point of view) and
> therefore
>>>> 'optnone' should be considered incompatible with 'alwaysinline' and
>>>> 'inlinehint'.
>>>>
>>>> Example:
>>>> __attribute__((optnone, always_inline))
>>>> void foo() { ... }
>>>>
>>>> In this case we could make 'optnone' override 'alwaysinline'. The
> effect
>>>> would be that 'alwaysinline' wouldn't appear in the IR if 'optnone'
> is
>>>> specified.
>>>>
>>>> Under the assumption that 'optnone' implies 'noinline', other things
> that
>>>> should be taken into account are:
>>>> 1) functions marked as 'optnone' should never be considered as
> potential
>>>> candidates for inlining;
>>>> 2) the inliner shouldn't try to inline a function if the call site
> is in a
>>>> 'optnone' function.
>>>>
>>>> Point 1 can be easily achieved by simply pushing attribute
> 'noinline' on
>>>> the list of function attributes if 'optnone' is used.
>>>> point 2 however would probably require to teach the Inliner about
>>>> 'optnone' and how to deal with it.
>>>>
>>>> As in the case of 'alwaysinline' and 'inlinehint', I think 'optnone'
>>>> should also override 'optsize'/'minsize'.
>>>>
>>>> Last (but not least), implementing 'optnone' would still require
> changes
>>>> in how optimizations are run on functions. This last part is
> probably the
>>>> hardest part since the current optimizer does not allow the level of
>>>> flexibility required by 'optnone'.  It seems it would either require
> some
>>>> modifications to the Pass Manager or we would have to make
> individual
>>>> passes aware of the attribute.  Neither of these solutions seem
>>>> particularly attractive to me, so I'm open to any suggestions!
>>>>
>>>> Thanks,
>>>> Andrea Di Biagio
>>>> SN Systems - Sony Computer Entertainment Group
>>>>
>>>>
>>>>
> **********************************************************************
>>>> This email and any files transmitted with it are confidential and
> intended
>>>> solely for the use of the individual or entity to whom they are
> addressed.
>>>> If you have received this email in error please notify
> postmaster at scee.net
>>>> This footnote also confirms that this email message has been checked
> for
>>>> all known viruses.
>>>> Sony Computer Entertainment Europe Limited
>>>> Registered Office: 10 Great Marlborough Street, London W1F 7LP,
> United
>>>> Kingdom
>>>> Registered in England: 3277793
>>>>
> **********************************************************************
>>>>
>>>> P Please consider the environment before printing this e-mail
>>>> _______________________________________________
>>>> LLVM Developers mailing list
>>>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>>>>
>>>
>>
>>
>> **********************************************************************
>> This email and any files transmitted with it are confidential and
>> intended solely for the use of the individual or entity to whom they
>> are addressed. If you have received this email in error please
>> notify postmaster at scee.net
>> This footnote also confirms that this email message has been checked
>> for all known viruses.
>> Sony Computer Entertainment Europe Limited
>> Registered Office: 10 Great Marlborough Street, London W1F 7LP, United
> Kingdom
>> Registered in England: 3277793
>> **********************************************************************
>>
>> P Please consider the environment before printing this e-mail
>
> **********************************************************************
> This email and any files transmitted with it are confidential and intended
> solely for the use of the individual or entity to whom they are addressed.
> If you have received this email in error please notify postmaster at scee.net
> This footnote also confirms that this email message has been checked for
> all known viruses.
> Sony Computer Entertainment Europe Limited
> Registered Office: 10 Great Marlborough Street, London W1F 7LP, United
> Kingdom
> Registered in England: 3277793
> **********************************************************************
>
> P Please consider the environment before printing this e-mail
>




More information about the llvm-dev mailing list