diff options
author | Eric Christopher <echristo@apple.com> | 2009-08-08 21:55:08 +0000 |
---|---|---|
committer | Eric Christopher <echristo@apple.com> | 2009-08-08 21:55:08 +0000 |
commit | b5f948cbb5694e348fcbe8511d09ee2dd3fd9845 (patch) | |
tree | da5ce7301c16bef88ac50c36ac202f859e416c20 | |
parent | 69f1aec5be6e6b0a0059602abe2097d1b61abacb (diff) | |
download | external_llvm-b5f948cbb5694e348fcbe8511d09ee2dd3fd9845.zip external_llvm-b5f948cbb5694e348fcbe8511d09ee2dd3fd9845.tar.gz external_llvm-b5f948cbb5694e348fcbe8511d09ee2dd3fd9845.tar.bz2 |
Add crc32 instruction and intrinsics. Add a new class of prefix
bytes for F2 0F 38 and propagate. Add a FIXME for a set
of possibilities which correspond to intrinsics already used.
New test.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78508 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/X86/X86CodeEmitter.cpp | 5 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrFormats.td | 6 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.cpp | 7 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.h | 3 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrSSE.td | 72 | ||||
-rw-r--r-- | test/CodeGen/X86/sse42.ll | 38 |
6 files changed, 131 insertions, 0 deletions
diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp index 03d871a..3dd3c6b 100644 --- a/lib/Target/X86/X86CodeEmitter.cpp +++ b/lib/Target/X86/X86CodeEmitter.cpp @@ -517,6 +517,10 @@ void Emitter<CodeEmitter>::emitInstruction( case X86II::TA: // 0F 3A Need0FPrefix = true; break; + case X86II::TF: // F2 0F 38 + MCE.emitByte(0xF2); + Need0FPrefix = true; + break; case X86II::REP: break; // already handled. case X86II::XS: // F3 0F MCE.emitByte(0xF3); @@ -548,6 +552,7 @@ void Emitter<CodeEmitter>::emitInstruction( MCE.emitByte(0x0F); switch (Desc->TSFlags & X86II::Op0Mask) { + case X86II::TF: // F2 0F 38 case X86II::T8: // 0F 38 MCE.emitByte(0x38); break; diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td index eeed5bd..6f5941c 100644 --- a/lib/Target/X86/X86InstrFormats.td +++ b/lib/Target/X86/X86InstrFormats.td @@ -79,6 +79,7 @@ class XD { bits<4> Prefix = 11; } class XS { bits<4> Prefix = 12; } class T8 { bits<4> Prefix = 13; } class TA { bits<4> Prefix = 14; } +class TF { bits<4> Prefix = 15; } class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins, string AsmStr> @@ -229,6 +230,11 @@ class SS428I<bits<8> o, Format F, dag outs, dag ins, string asm, list<dag> pattern> : I<o, F, outs, ins, asm, pattern>, T8, Requires<[HasSSE42]>; +// SS42FI - SSE 4.2 instructions with TF prefix. +class SS42FI<bits<8> o, Format F, dag outs, dag ins, string asm, + list<dag> pattern> + : I<o, F, outs, ins, asm, pattern>, TF, Requires<[HasSSE42]>; + // X86-64 Instruction templates... // diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 393bd5c..b59f8e8 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -2931,6 +2931,10 @@ static unsigned GetInstSizeWithDesc(const MachineInstr &MI, case X86II::TA: // 0F 3A Need0FPrefix = true; break; + case X86II::TF: // F2 0F 38 + ++FinalSize; + Need0FPrefix = true; + break; case X86II::REP: break; // already handled. case X86II::XS: // F3 0F ++FinalSize; @@ -2966,6 +2970,9 @@ static unsigned GetInstSizeWithDesc(const MachineInstr &MI, case X86II::TA: // 0F 3A ++FinalSize; break; + case X86II::TF: // F2 0F 38 + ++FinalSize; + break; } // If this is a two-address instruction, skip one of the register operands. diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index 0fb2052..2e0235a 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -321,6 +321,9 @@ namespace X86II { // T8, TA - Prefix after the 0x0F prefix. T8 = 13 << Op0Shift, TA = 14 << Op0Shift, + + // TF - Prefix before and after 0x0F + TF = 15 << Op0Shift, //===------------------------------------------------------------------===// // REX_W - REX prefixes are instruction prefixes used in 64-bit mode. diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index 890ebae..fefdba0 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -3678,3 +3678,75 @@ def : Pat<(v2i64 (X86pcmpgtq VR128:$src1, VR128:$src2)), (PCMPGTQrr VR128:$src1, VR128:$src2)>; def : Pat<(v2i64 (X86pcmpgtq VR128:$src1, (memop addr:$src2))), (PCMPGTQrm VR128:$src1, addr:$src2)>; + +// crc intrinsic instruction +// This set of instructions are only rm, the only difference is the size +// of r and m. +let Constraints = "$src1 = $dst" in { + def CRC32m8 : SS42FI<0xF0, MRMSrcMem, (outs GR32:$dst), + (ins GR32:$src1, i8mem:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_8 GR32:$src1, + (load addr:$src2)))]>, OpSize; + def CRC32r8 : SS42FI<0xF0, MRMSrcReg, (outs GR32:$dst), + (ins GR32:$src1, GR8:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_8 GR32:$src1, GR8:$src2))]>, + OpSize; + def CRC32m16 : SS42FI<0xF1, MRMSrcMem, (outs GR32:$dst), + (ins GR32:$src1, i16mem:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_16 GR32:$src1, + (load addr:$src2)))]>, + OpSize; + def CRC32r16 : SS42FI<0xF1, MRMSrcReg, (outs GR32:$dst), + (ins GR32:$src1, GR16:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_16 GR32:$src1, GR16:$src2))]>, + OpSize; + def CRC32m32 : SS42FI<0xF1, MRMSrcMem, (outs GR32:$dst), + (ins GR32:$src1, i32mem:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_32 GR32:$src1, + (load addr:$src2)))]>, OpSize; + def CRC32r32 : SS42FI<0xF1, MRMSrcReg, (outs GR32:$dst), + (ins GR32:$src1, GR32:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR32:$dst, + (int_x86_sse42_crc32_32 GR32:$src1, GR32:$src2))]>, + OpSize; + def CRC64m64 : SS42FI<0xF0, MRMSrcMem, (outs GR64:$dst), + (ins GR64:$src1, i64mem:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR64:$dst, + (int_x86_sse42_crc32_64 GR64:$src1, + (load addr:$src2)))]>, + OpSize, REX_W; + def CRC64r64 : SS42FI<0xF0, MRMSrcReg, (outs GR64:$dst), + (ins GR64:$src1, GR64:$src2), + "crc32 \t{$src2, $src1|$src1, $src2}", + [(set GR64:$dst, + (int_x86_sse42_crc32_64 GR64:$src1, GR64:$src2))]>, + OpSize, REX_W; + + // TODO: These correspond to int_x86_sse42_crc32_8 but with a 64-bit src + // and dest, figure it out. + //def CRC64m8 : SS42FI<0xF1, MRMSrcMem, (outs GR64:$dst), + // (ins GR32:$src1, i8mem:$src2), + // "crc32 \t{$src2, $src1|$src1, $src2}", + // [(set GR64:$dst, + // (int_x86_sse42_crc32_8 GR64:$src1, + // (load addr:$src2)))]>, + // OpSize, REX_W; + //def CRC64r8 : SS42FI<0xF1, MRMSrcReg, (outs GR64:$dst), + // (ins GR64:$src1, GR8:$src2), + // "crc32 \t{$src2, $src1|$src1, $src2}", + // [(set GR64:$dst, + // (int_x86_sse42_crc32_8 GR32:$src1, GR8:$src2))]>, + // OpSize, REX_W; +} diff --git a/test/CodeGen/X86/sse42.ll b/test/CodeGen/X86/sse42.ll new file mode 100644 index 0000000..1652294 --- /dev/null +++ b/test/CodeGen/X86/sse42.ll @@ -0,0 +1,38 @@ +; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin9 -mattr=sse42 | FileCheck %s -check-prefix=X32 +; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 -mattr=sse42 | FileCheck %s -check-prefix=X64 + +declare i32 @llvm.x86.sse42.crc32.8(i32, i8) nounwind +declare i32 @llvm.x86.sse42.crc32.16(i32, i16) nounwind +declare i32 @llvm.x86.sse42.crc32.32(i32, i32) nounwind + +define i32 @crc32_8(i32 %a, i8 %b) nounwind { + %tmp = call i32 @llvm.x86.sse42.crc32.8(i32 %a, i8 %b) + ret i32 %tmp +; X32: _crc32_8: +; X32: crc32 8(%esp), %eax + +; X64: _crc32_8: +; X64: crc32 %sil, %eax +} + + +define i32 @crc32_16(i32 %a, i16 %b) nounwind { + %tmp = call i32 @llvm.x86.sse42.crc32.16(i32 %a, i16 %b) + ret i32 %tmp +; X32: _crc32_16: +; X32: crc32 8(%esp), %eax + +; X64: _crc32_16: +; X64: crc32 %si, %eax +} + + +define i32 @crc32_32(i32 %a, i32 %b) nounwind { + %tmp = call i32 @llvm.x86.sse42.crc32.32(i32 %a, i32 %b) + ret i32 %tmp +; X32: _crc32_32: +; X32: crc32 8(%esp), %eax + +; X64: _crc32_32: +; X64: crc32 %esi, %eax +} |