This is an archive of the discontinued LLVM Phabricator instance.

[ARM] Relax condition for PerformSHLSimplify
Needs ReviewPublic

Authored by samparker on Mar 5 2018, 8:57 AM.
This revision needs review, but all reviewers have resigned.

Details

Reviewers
john.brawn
Summary

PerformSHLSimplify previously would be bail if one of given node's users had a shl operand because the transformation wouldn't necessarily combine the shift into the user nodes. I guess this should have also happened for other shifts too... Anyway, by removing this restriction we can still remove mov instructions or a mov is replaced by a shift, which sometimes can help register pressure.

Diff Detail

Event Timeline

samparker created this revision.Mar 5 2018, 8:57 AM

It looks like loosening this restriction doesn't necessarily lead to better code being generated, e.g. looking at load_i32_by_i8_bswap in load-combine-big-endian.ll that lsl r0, r0, #24 introduces a register dependency that wasn't there before which likely makes this worse on an in-order CPU.

Looking at the tests you added it looks like doing this is of benefit when it turns an immediate which can't be encoded (510) into an immediate which can (255), so maybe you should be checking for that? Maybe instead of removing the "is the other operand already a shift" check set a bool, and then later when you know the pre- and post-shift constants only proceed if that bool is false of if the constant is now better.

Thanks John, I'll try those changes.

samparker updated this revision to Diff 137376.Mar 7 2018, 6:23 AM

Hi John,

I've changed the function to check the immediate to handle the subtle differences between Thumb and Arm immediate encoding. I also tried exiting early when there's a shifted user and the immediate is already valid, but this produced worse code for almost all my new tests. The problem is that a mov is still required because the bin op is using an immediate and a shifted operand. This is particularly worse for Thumb where code size increase is greater as well.

lib/Target/ARM/ARMISelLowering.cpp
10478

I'll remove this whitespace.

I also tried exiting early when there's a shifted user and the immediate is already valid, but this produced worse code for almost all my new tests. The problem is that a mov is still required because the bin op is using an immediate and a shifted operand. This is particularly worse for Thumb where code size increase is greater as well.

It looks like, in the added tests at least, what we should be trying to do is:

  • We have this node N
  • We want to transform this node so that its user can use it in a shifted operand, in a way that saves us an instruction
  • If the user already has another operand that it can use as a shifted operand, then we won't actually be saving an instruction in that way
  • But we can save an instruction if this transformation causes an immediate to be a valid operand meaning we can eliminate a mov

I think it's specifically the "check that the other operand of the user could be used as a shifted operand" that we need to be careful about. Just checking for a shift isn't right in thumb because it's only a shift by an immediate that can be used as an operand, but in arm we can do that so the check needs to take that into account.

Could you provide me with an example to illustrate your concern please? I keep going around in circles and I just see either the number of instructions or register pressure being reduced. Could the codegen of my new tests be improved?

john.brawn resigned from this revision.May 12 2020, 6:40 AM