X86: Enable ISel of 16-bit MOVBE instructions.
authorJim Grosbach <grosbach@apple.com>
Tue, 11 Mar 2014 00:44:14 +0000 (00:44 +0000)
committerJim Grosbach <grosbach@apple.com>
Tue, 11 Mar 2014 00:44:14 +0000 (00:44 +0000)
When the MOVBE instructions are available, use them for 16-bit endian
swapping as well as for 32 and 64 bit.

The patterns were already present on the instructions, but weren't being
matched because the operation was unconditionally marked to 'Expand.'
Change that to be conditional on whether the MOVBE instructions are
available. Use 'rolw' to implement the in-register version (32 and 64
bit have the dedicated 'bswap' instruction for that).

Patch by Louis Gerbarg <lgg@apple.com>.

rdar://15479984

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203524 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86InstrCompiler.td
test/CodeGen/X86/movbe.ll

index 951d3ded99dba15c05b5c7a850b148bc1f502a4a..07c83e8b294ef02ee1137bbec9e2a310aec0ae7e 100644 (file)
@@ -505,7 +505,9 @@ void X86TargetLowering::resetOperationActions() {
   }
 
   setOperationAction(ISD::READCYCLECOUNTER , MVT::i64  , Custom);
-  setOperationAction(ISD::BSWAP            , MVT::i16  , Expand);
+
+  if (!Subtarget->hasMOVBE())
+    setOperationAction(ISD::BSWAP          , MVT::i16  , Expand);
 
   // These should be promoted to a larger select which is supported.
   setOperationAction(ISD::SELECT          , MVT::i1   , Promote);
index 8446c2cfb90df6eed085c02f2f2aafb8c4dfcf5a..a8aff44d06c058e0803b009a731b63ea317554a8 100644 (file)
@@ -1839,3 +1839,9 @@ def : Pat<(cttz_zero_undef GR64:$src), (BSF64rr GR64:$src)>;
 def : Pat<(cttz_zero_undef (loadi16 addr:$src)), (BSF16rm addr:$src)>;
 def : Pat<(cttz_zero_undef (loadi32 addr:$src)), (BSF32rm addr:$src)>;
 def : Pat<(cttz_zero_undef (loadi64 addr:$src)), (BSF64rm addr:$src)>;
+
+// When HasMOVBE is enabled it is possible to get a non-legalized
+// register-register 16 bit bswap. This maps it to a ROL instruction.
+let Predicates = [HasMOVBE] in {
+ def : Pat<(bswap GR16:$src), (ROL16ri GR16:$src, (i8 8))>;
+}
index 3f459be70d2a693eb55e120d6ebf6fec11fa6879..e248410b2020fe454bffd11af79349413d11b936 100644 (file)
@@ -1,45 +1,66 @@
 ; RUN: llc -mtriple=x86_64-linux -mcpu=atom < %s | FileCheck %s
 ; RUN: llc -mtriple=x86_64-linux -mcpu=slm < %s | FileCheck %s -check-prefix=SLM
 
+declare i16 @llvm.bswap.i16(i16) nounwind readnone
 declare i32 @llvm.bswap.i32(i32) nounwind readnone
 declare i64 @llvm.bswap.i64(i64) nounwind readnone
 
-define void @test1(i32* nocapture %x, i32 %y) nounwind {
+define void @test1(i16* nocapture %x, i16 %y) nounwind {
+  %bswap = call i16 @llvm.bswap.i16(i16 %y)
+  store i16 %bswap, i16* %x, align 2
+  ret void
+; CHECK-LABEL: test1:
+; CHECK: movbew %si, (%rdi)
+; SLM-LABEL: test1:
+; SLM: movbew   %si, (%rdi)
+}
+
+define i16 @test2(i16* %x) nounwind {
+  %load = load i16* %x, align 2
+  %bswap = call i16 @llvm.bswap.i16(i16 %load)
+  ret i16 %bswap
+; CHECK-LABEL: test2:
+; CHECK: movbew (%rdi), %ax
+; SLM-LABEL: test2:
+; SLM: movbew   (%rdi), %ax
+}
+
+define void @test3(i32* nocapture %x, i32 %y) nounwind {
   %bswap = call i32 @llvm.bswap.i32(i32 %y)
   store i32 %bswap, i32* %x, align 4
   ret void
-; CHECK-LABEL: test1:
+; CHECK-LABEL: test3:
 ; CHECK: movbel        %esi, (%rdi)
-; SLM-LABEL: test1:
+; SLM-LABEL: test3:
 ; SLM: movbel  %esi, (%rdi)
 }
 
-define i32 @test2(i32* %x) nounwind {
+define i32 @test4(i32* %x) nounwind {
   %load = load i32* %x, align 4
   %bswap = call i32 @llvm.bswap.i32(i32 %load)
   ret i32 %bswap
-; CHECK-LABEL: test2:
+; CHECK-LABEL: test4:
 ; CHECK: movbel        (%rdi), %eax
-; SLM-LABEL: test2:
+; SLM-LABEL: test4:
 ; SLM: movbel  (%rdi), %eax
 }
 
-define void @test3(i64* %x, i64 %y) nounwind {
+define void @test5(i64* %x, i64 %y) nounwind {
   %bswap = call i64 @llvm.bswap.i64(i64 %y)
   store i64 %bswap, i64* %x, align 8
   ret void
-; CHECK-LABEL: test3:
+; CHECK-LABEL: test5:
 ; CHECK: movbeq        %rsi, (%rdi)
-; SLM-LABEL: test3:
+; SLM-LABEL: test5:
 ; SLM: movbeq  %rsi, (%rdi)
 }
 
-define i64 @test4(i64* %x) nounwind {
+define i64 @test6(i64* %x) nounwind {
   %load = load i64* %x, align 8
   %bswap = call i64 @llvm.bswap.i64(i64 %load)
   ret i64 %bswap
-; CHECK-LABEL: test4:
+; CHECK-LABEL: test6:
 ; CHECK: movbeq        (%rdi), %rax
-; SLM-LABEL: test4:
+; SLM-LABEL: test6:
 ; SLM: movbeq  (%rdi), %rax
 }