[LLVMdev] Making optimization passes do less

Devang Patel dpatel at apple.com
Tue May 27 10:42:13 PDT 2008


Matthijs,

On May 26, 2008, at 4:23 AM, Matthijs Kooijman wrote:

> Hi all,
>
> I'm currently struggling with a few optimization passes that change  
> stuff I
> don't want to be changed. However, for the most part those passes  
> (InstructionCombining
> and SimplifyCFG currently) do stuff that I do want, so disabling them
> alltogether doesn't help me much.
>
> The problem arises because the architecture I'm compiling for is quite
> non-standard. In particular, it has the ability to execute a lot of
> instructions in parallel, but at the same time can't execute  
> everything you
> throw at it.
>
> My problem with SimplifyCFG is the following: Whenever the if and  
> else branch
> start with the same instruction, it gets hoisted up into the  
> predecessor
> block. For my architecture, instructions in different blocks can't  
> be run in
> parallel, so this optimization makes code either very inefficient or  
> not
> compile at all.
>
> InstructionCombining has this habit of removing unneeded bits from  
> constants.
> For example, if I do i & 63, where i is a loop counter that is  
> always even,
> this gets replaced by i & 62. Which gives, of course, the same  
> results when
> interpreted, but our backend cannot just use any constant as an &  
> mask (in
> particular, it can only use a limited amount of them). I'd very much  
> prefer to
> preserve the original value from the source here (I also assume that  
> this
> optimization is in place to help further optimizations, because I  
> can't really
> see any use of this change on regular architectures...).
>
> I've been thinking a bit on how to achieve this, and I see a few  
> options:
> * Use a local patch to simply disable the parts of the passes we  
> don't want,
> 	 optionally protected by some check to only disable it when it's  
> unwanted.
> 	 This would be a very effective approach, though also very much  
> unwanted.
> 	 Local patches to the LLVM source are a pain to maintain.

Yes, but it works!

> * Use some kind of subclassed pass. Since, AFAICS, simply  
> subclassing an
> 	 existing pass doesn't really work due to the class ID stuff, this  
> requires
> 	 making a superclass to do most of the work and a subclass to  
> decide when to
> 	 do it in LLVM, so we can add another subclass (similar to the  
> Inliner
> 	 pass). Alternatively, the functionality of instruction combining  
> could be
> 	 split off into a utility class, though that would prevent using  
> overriding
> 	 methods to disable some functionality. This approach could be  
> useful, but
> 	 I can't really see how it would work out yet.
> * Add options to the current passes. I could add an option to the  
> current
>   passes to make them do what I want (either using an option to
> 	 createXXXPass() and the constructor, or perhaps using a  
> set_XXX_option()
> 	 methode or something). This might work for SimplifyCFG, since that  
> option
> 	 could be made a bit more generic, such as "Don't move instructions  
> between
> 	 blocks" (leaving SimplifyCFG free to merge blocks whenever  
> appropriate).
>
> 	 For InstructionCombining this is harder, since our requirements  
> are not as
> 	 easily captured in an elegant option, I'm afraid.

In general, I'd like to avoid additional options if possible.

> * Mark instructions / values as immutable. We could write a pass  
> that marks
>   the values we want preserved as immutable and other passes should  
> leave
> 	 those values alone. This requires quite some modification to LLVM  
> (probably
> 	 even the IR) and all optimization passes. Though I think it's  
> actually
> 	 quite an elegant solution, it's probably hard to express  
> everything we need
> 	 in it (also, if we mark some instruction or value as immutable,  
> it's hard
> 	 to prevent a pass from making a copy of the instruction (perhaps
> 	 indirectly) and simply making the immutable instruction unused).

Usually "volatile" is one hammer used in such situation to instruct  
optimizers to stay away. But it is not elegant and smells like hack.

> * Use some kind of TargetInfo/TargetData struct to control certain
>   optimizations. I'm not really sure how this is used now, but I could
> 	 imagine that there is some interface for optimization passes to  
> find out
> 	 what optimizations are worthwile and what are not (something like a
> 	 bool isBetter(Value* old, Value* new) as a very simple example. Is  
> there
> 	 already something like this?

Instruction Combiner uses TargetData. However AFAIK, there is not any  
general purpose interface available to select optimization based on  
target.

> None of these options seem too attractive to me, what do others  
> think? Is
> there some other option I'm missing here?

Would it be possible for write a code gen level pass to sink the  
instructions to maximize parallel instructions in a block for your  
target ?

-
Devang






More information about the llvm-dev mailing list