This is an archive of the discontinued LLVM Phabricator instance.

[X86] Prefer rotate by 1 over rotate by imm
ClosedPublic

Authored by zvi on Oct 8 2016, 12:08 PM.

Details

Summary

Rotate by 1 is translated to 1 micro-op, while rotate with imm8 is translated to 2 micro-ops.

Fixes pr30644.

Diff Detail

Repository
rL LLVM

Event Timeline

zvi updated this revision to Diff 74042.Oct 8 2016, 12:08 PM
zvi retitled this revision from to [X86] Prefer rotate by 1 over rotate by imm.
zvi updated this object.
zvi added reviewers: delena, igorb, craig.topper, spatel, RKSimon.
zvi set the repository for this revision to rL LLVM.
craig.topper added inline comments.Oct 8 2016, 12:33 PM
lib/Target/X86/X86InstrShiftRotate.td
612

Does rotr by 1 never get emitted or should we really have two patterns here?

zvi added inline comments.Oct 8 2016, 12:40 PM
lib/Target/X86/X86InstrShiftRotate.td
612

Note that for 8-bit operands:
rotate right by 1 is same as rotate left by 7.

It seems that the canonical form prefers the latter while the target prefers the former.

Does this answer your question, Craig?

RKSimon added inline comments.Oct 8 2016, 12:43 PM
test/CodeGen/X86/rotate.ll
2

We have a 64-bit triple and a 32-bit arch - this needs fixing and if possible test on both 32 and 64 bit targets.

If possible add i64 tests as well?

zvi added inline comments.Oct 8 2016, 12:46 PM
test/CodeGen/X86/rotate.ll
2

Good catch!
Will add the i64 tests.

zvi updated this revision to Diff 74071.Oct 9 2016, 6:28 AM

Rebased on top of trunk after r283695 was comitted.

zvi marked 2 inline comments as done.Oct 9 2016, 6:29 AM
zvi added inline comments.
test/CodeGen/X86/rotate.ll
2

Fixed in r283695

RKSimon edited edge metadata.Oct 9 2016, 7:36 AM

Please can you confirm that the _lrotl/_lrotr intrinsics (I think they are only on clang-cl) can't create the removed rotr #1 pattern

zvi marked an inline comment as done.EditedOct 9 2016, 11:27 AM

Please can you confirm that the _lrotl/_lrotr intrinsics (I think they are only on clang-cl) can't create the removed rotr #1 pattern

Seems like for 64-bit operand intrinsics we are not matching any rotate instructions:

unsigned long ltestl(unsigned long _Value) {
   return _lrotl(_Value, 1);
}
      leaq    (%rdi,%rdi), %rax
      shrq    $31, %rdi
      orq     %rdi, %rax
      retq


unsigned long ltestr(unsigned long _Value) {
  return _lrotr(_Value, 1);
}
      movq    %rdi, %rax
      shrq    %rax
      shlq    $31, %rdi
      orq     %rax, %rdi
      movq    %rdi, %rax
      retq

But the 32-bit operand flavors are matching rotate instructions (these are withour this patch):

unsigned long testl(unsigned long _Value) {
  return _rotl(_Value, 1);
}
      roll    %edi
      movq    %rdi, %rax
      retq


unsigned long testr(unsigned long _Value) {
  return _rotr(_Value, 1);
}
      roll    $31, %edi
      movq    %rdi, %rax
      retq

The 64-bit operand issue seems like out of scope of this patch, since the matching to ISD::ROTR/ROTL nodes happens in the target-independent phase of DagCombine. I will open a Bugzilla for this and will investigate it further.

zvi added a comment.Oct 9 2016, 11:58 AM

Actually, the relevant 64-bit operand intrinsics are _rotl64 and _rotr64 for which the generated code without this patch is:

test_rotl64(unsigned long):                       # @test_rotl64(unsigned long)
      rolq    %rdi
      movq    %rdi, %rax
      retq

test_rotr64(unsigned long):                       # @test_rotr64(unsigned long)
      rolq    $63, %rdi
      movq    %rdi, %rax
      retq
RKSimon accepted this revision.Oct 10 2016, 7:44 AM
RKSimon edited edge metadata.

Thanks for checking, LGTM

This revision is now accepted and ready to land.Oct 10 2016, 7:44 AM
Eugene.Zelenko added a subscriber: Eugene.Zelenko.

Committed in rL283758.