[llvm-commits] [PATCH] X86: Turn cmovs into branches when profitable.

Evan Cheng evan.cheng at apple.com
Mon Apr 30 22:42:41 PDT 2012


Hi Benjamin,

I haven't forgotten about this. I'll try to run some tests tomorrow. 

Evan

On Apr 29, 2012, at 10:00 AM, Benjamin Kramer <benny.kra at googlemail.com> wrote:

> 
> On 27.04.2012, at 07:48, Evan Cheng wrote:
> 
>> 
>> 
>> On Apr 26, 2012, at 12:30 PM, Benjamin Kramer <benny.kra at googlemail.com> wrote:
>> 
>>> 
>>> On 26.04.2012, at 08:04, Evan Cheng wrote:
>>> 
>>>> Hi Benjamin,
>>>> 
>>>> You are right. LLVM likes to canonicalize to select instructions and that can really hurt us on some modern cpu's. I've wanted a way to undo llvm selects for a while. 
>>>> 
>>>> That said. I'm not sure this is the right approach. I think it's better to turn selects back into control flows at llvm ir level. I'm envision something that's done around codegen prep time. IMHO, there are a few potential benefits. 
>>>> 
>>>> 1. It will be target independent. I don't want to duplicate this kind of patterns for different targets. 
>>>> 2. It will be possible to use better and more sophisticated heuristics (look at how the MI level if-converter compute the profitability). It should be able to take advantage of profile info if it's available. 
>>>> 
>>>> I also think the isel approach feels wrong. Isel really shouldn't use these complex predicates to drive isel decisions. It hurts compile time and it just generally goes against the design. Expanding pseudo instructions into control flows is also kinda yucky. We should only use it when there isn't a better design. 
>>>> 
>>>> Can I interest you into writing a llvm it de-select pass? :) We'd be more than happy in helping you with performance benchmarking and analysis. 
>>> 
>>> My first idea was to do it during selection DAG formation but that was even uglier, it makes sense to do it at IR level though.
>>> 
>>> Attached is a basic pass that is run by codegen the same way CodeGenPrepare runs. It uses the (dumb) cmp-with-load heuristic I came up with for the x86 backend patch. I didn't run the test-suite this time (no non-noisy builder at my hands) but the improvement on richards_benchmark is still measurable. Testing the patch is easy, just pass -enable-select2branch to llc.
>> 
>> Thanks. We should run some tests. 
>> 
>>> 
>>> Some questions remain open. Should it be merged into CodeGenPrepare? We need some kind of target hook to avoid doing the optimization on CPUs that are unlikely to benefit, like Atom and pre-A9 ARM cores. Of course benchmarking is key, it's just hard to dig up the hardware ;)
>> 
>> I think it should be merged into codegenprepare. Given the primitive heuristics, we should add a target hook so it's only run when it's explicitly opted in.
> 
> Attached is a version in CodeGenPrepare, the option is now "-enable-cgp-select2branch". There are some tests that fail because they assembly that they expect more cmovs. I've yet to figure out how to wire up a target hook into CodeGenPrepare.
> <cmov-into-branch-2.patch>
> 
>>> 
>>> Coming up with good heuristics is hard. I'd love to use BranchProbabilityInfo here, but it doesn't understand selects. We also need some clever way to break up long select chains.
>> 
>> That seems like a BranchProbabilityInfo deficiency. Andy, what do you think? Benjamin, can you point us to examples of long select chains? Are they in real world benchmarks?
> 
> One of the examples that I found in the test-suite (though not in a hot path) was something like the following loop:
> 
> unsigned foo(unsigned *x) {
>  unsigned i, max = 0;
>  for (i = 0; i != 7; ++i) {
>    if (x[i] > max) max = x[i];
>  }
>  return max;
> }
> 
> We unroll it and form a 7-instruction long chain of cmovs which is obviously bad. I haven't found a better example yet but I'm sure there is.
> 
> - Ben



More information about the llvm-commits mailing list