This is an archive of the discontinued LLVM Phabricator instance.

SystemZ: improved optimizeCompareZero()
ClosedPublic

Authored by jonpa on Sep 20 2017, 3:45 AM.

Details

Reviewers
uweigand
Summary

It was recently discovered that the ElimCompare pass can optimize:

%F2S<def> = LER %F0S
LTEBRCompare %F0S, %F0S, %CC<imp-def> LTEBRCompare %F0S, %F0S, %CC<imp-def>

but not:

LTEBRCompare %F0S, %F0S, %CC<imp-def> LTEBRCompare %F0S, %F0S, %CC<imp-def>
%F2S<def> = LER %F0S

My first thought was to swap the instructions as a setup for the algorithm, but then I realised I would still have
to do a search to do so, so I instead simply added the loop to do the forward search.

Have not yet checked if adjustCCMasksForInstr() can also be called here, but the calling fucntion is doing a
bottom-up traversal of MBB, so this might not work. For load-and-test, a top-down search here seems ok, I think.

Also fixed the comment at resultTests() which I thought was incomplete.

Diff Detail

Event Timeline

jonpa created this revision.Sep 20 2017, 3:45 AM
uweigand edited edge metadata.Sep 20 2017, 10:07 AM

The code change looks good to me, but please try to simplify the .mir test case following the suggestions outlined here: https://llvm.org/docs/MIRLangRef.html#simplifying-mir-files

jonpa updated this revision to Diff 116148.Sep 21 2017, 1:57 AM

Test case reduced.

Also found out that the first check in resultTests() must not be used in a forward search, as in that case the reg is actually taking on a new value in between the compare and the CC-user. For this purpse, I added the 'BeforeCompare' parameter to the function.

I also wonder if the first check in resultTests() should include a check for a CC<def> operand?

jonpa added a comment.Sep 21 2017, 1:59 AM

Opcode differences:

                  master                                             patched                                     
lgr            : 343498                                             342961                                                   -537
ltgr           : 4756                                               5293                                                     +537
jlh            : 48677                                              49178                                                    +501
cgijlh         : 18083                                              17600                                                    -483
ltr            : 218                                                460                                                      +242
lr             : 25730                                              25488                                                    -242
chi            : 15183                                              14995                                                    -188
cghi           : 4056                                               4019                                                      -37
je             : 94826                                              94848                                                     +22
...

Test case reduced.

Also found out that the first check in resultTests() must not be used in a forward search, as in that case the reg is actually taking on a new value in between the compare and the CC-user. For this purpse, I added the 'BeforeCompare' parameter to the function.

Ah, right, this doesn't quite fit. The "resultTests()" routine currently is intended to check the following question: if MI were to be changed to an instruction that does the same as it does now, and also sets CC based on the result of the operation, would then that CC value also reflect the status of "Reg". This is true if either MI actually sets Reg, or else uses Reg as input to a value-preserving operation (like a copy or extend).

But for the new code, you actually want to check for something else; you only look whether MI uses Reg as input and sets CC accordingly. So your change is functionally correct, but I think it would be clearer if the resultTest() routine were split into two parts:

  • add a new routine called something like preservesValueOf(MI, Reg) which returns true if MI is an instruction whose output equals the value in Reg. (This would be the switch part in resultTests.)
  • change resultTests to do the first check for using Reg as output, and then simply call preservesValueOf(MI, Reg)

In the new code you add, you'd simply only call preservesValueOf.

I also wonder if the first check in resultTests() should include a check for a CC<def> operand?

No, the point is that even if MI currently does not define CC, if it can be modified to add a CC check that CC result would reflect the status (0, <0, >0) of the correct value. *Whether* or not MI already sets CC or can be modified to do so, is then checked at some later point (e.g. in convertToLoadAndTest).

jonpa updated this revision to Diff 116178.Sep 21 2017, 6:24 AM

But for the new code, you actually want to check for something else; you only look whether MI uses Reg as input and sets CC accordingly. So your change is functionally correct, but I think it would be clearer if the resultTest() routine were split into two parts:

yes, that seems better - done.

I also wonder if the first check in resultTests() should include a check for a CC<def> operand?

No, the point is that even if MI currently does not define CC, if it can be modified to add a CC check that CC result would reflect the status (0, <0, >0) of the correct value. *Whether* or not MI already sets CC or can be modified to do so, is then checked at some later point (e.g. in convertToLoadAndTest).

Ah, right.

uweigand accepted this revision.Sep 21 2017, 6:26 AM

LGTM, thanks!

This revision is now accepted and ready to land.Sep 21 2017, 6:26 AM
jonpa closed this revision.Sep 21 2017, 6:54 AM

r313877