Intrinsic<[], [llvm_ptr_ty], []>;
}
+//===----------------------------------------------------------------------===//
+// XSAVE
+let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
+ def int_x86_xsave :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_xsave64 :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_xrstor :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_xrstor64 :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_xsaveopt :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_xsaveopt64 :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_xrstors :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_xrstors64 :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_xsavec :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_xsavec64 :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_xsaves :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+ def int_x86_xsaves64 :
+ Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
+}
+
//===----------------------------------------------------------------------===//
// Half float conversion
Features["movbe"] = (ECX >> 22) & 1;
Features["popcnt"] = (ECX >> 23) & 1;
Features["aes"] = (ECX >> 25) & 1;
+ Features["xsave"] = (ECX >> 26) & 1;
Features["rdrnd"] = (ECX >> 30) & 1;
// If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save;
Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save;
+
+ bool HasLeafD = MaxLevel >= 0xd &&
+ !GetX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
+
+ Features["xsaveopt"] = Features["xsave"] && HasLeafD && ((EAX >> 0) & 1);
+ Features["xsavec"] = Features["xsave"] && HasLeafD && ((EAX >> 1) & 1);
+ Features["xsaves"] = Features["xsave"] && HasLeafD && ((EAX >> 3) & 1);
+
return true;
}
#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
def FeaturePOPCNT : SubtargetFeature<"popcnt", "HasPOPCNT", "true",
"Support POPCNT instruction">;
+def FeatureXSAVE : SubtargetFeature<"xsave", "HasXSAVE", "true",
+ "Support xsave instructions">;
+
+def FeatureXSAVEOPT: SubtargetFeature<"xsaveopt", "HasXSAVEOPT", "true",
+ "Support xsaveopt instructions">;
+
+def FeatureXSAVEC : SubtargetFeature<"xsavec", "HasXSAVEC", "true",
+ "Support xsavec instructions">;
+
+def FeatureXSAVES : SubtargetFeature<"xsaves", "HasXSAVES", "true",
+ "Support xsaves instructions">;
+
// The MMX subtarget feature is separate from the rest of the SSE features
// because it's important (for odd compatibility reasons) to be able to
// turn it off explicitly while allowing SSE+ to be on.
def HasPOPCNT : Predicate<"Subtarget->hasPOPCNT()">;
def HasAES : Predicate<"Subtarget->hasAES()">;
+def HasXSAVE : Predicate<"Subtarget->hasXSAVE()">;
+def HasXSAVEOPT : Predicate<"Subtarget->hasXSAVEOPT()">;
+def HasXSAVEC : Predicate<"Subtarget->hasXSAVEC()">;
+def HasXSAVES : Predicate<"Subtarget->hasXSAVES()">;
def HasPCLMUL : Predicate<"Subtarget->hasPCLMUL()">;
def HasFMA : Predicate<"Subtarget->hasFMA()">;
def UseFMAOnAVX : Predicate<"Subtarget->hasFMA() && !Subtarget->hasAVX512()">;
def : MnemonicAlias<"xsaveq", "xsave64", "att">;
def : MnemonicAlias<"xrstorq", "xrstor64", "att">;
def : MnemonicAlias<"xsaveoptq", "xsaveopt64", "att">;
-
+def : MnemonicAlias<"xrstorsq", "xrstors64", "att">;
+def : MnemonicAlias<"xsavecq", "xsavec64", "att">;
+def : MnemonicAlias<"xsavesq", "xsaves64", "att">;
class CondCodeAlias<string Prefix,string Suffix, string OldCond, string NewCond,
string VariantName>
//===----------------------------------------------------------------------===//
// XSAVE instructions
let SchedRW = [WriteSystem] in {
+let Predicates = [HasXSAVE] in {
let Defs = [EDX, EAX], Uses = [ECX] in
def XGETBV : I<0x01, MRM_D0, (outs), (ins), "xgetbv", []>, TB;
let Uses = [EDX, EAX, ECX] in
def XSETBV : I<0x01, MRM_D1, (outs), (ins), "xsetbv", []>, TB;
+}
-let Uses = [RDX, RAX] in {
- def XSAVE : I<0xAE, MRM4m, (outs opaque512mem:$dst), (ins),
- "xsave\t$dst", []>, TB;
- def XSAVE64 : RI<0xAE, MRM4m, (outs opaque512mem:$dst), (ins),
- "xsave64\t$dst", []>, TB, Requires<[In64BitMode]>;
+let Uses = [EDX, EAX] in {
+let Predicates = [HasXSAVE] in {
+ def XSAVE : I<0xAE, MRM4m, (outs), (ins opaque512mem:$dst),
+ "xsave\t$dst",
+ [(int_x86_xsave addr:$dst, EDX, EAX)]>, TB;
+ def XSAVE64 : RI<0xAE, MRM4m, (outs), (ins opaque512mem:$dst),
+ "xsave64\t$dst",
+ [(int_x86_xsave64 addr:$dst, EDX, EAX)]>, TB, Requires<[In64BitMode]>;
def XRSTOR : I<0xAE, MRM5m, (outs), (ins opaque512mem:$dst),
- "xrstor\t$dst", []>, TB;
+ "xrstor\t$dst",
+ [(int_x86_xrstor addr:$dst, EDX, EAX)]>, TB;
def XRSTOR64 : RI<0xAE, MRM5m, (outs), (ins opaque512mem:$dst),
- "xrstor64\t$dst", []>, TB, Requires<[In64BitMode]>;
- def XSAVEOPT : I<0xAE, MRM6m, (outs opaque512mem:$dst), (ins),
- "xsaveopt\t$dst", []>, PS;
- def XSAVEOPT64 : RI<0xAE, MRM6m, (outs opaque512mem:$dst), (ins),
- "xsaveopt64\t$dst", []>, PS, Requires<[In64BitMode]>;
-
+ "xrstor64\t$dst",
+ [(int_x86_xrstor64 addr:$dst, EDX, EAX)]>, TB, Requires<[In64BitMode]>;
+}
+let Predicates = [HasXSAVEOPT] in {
+ def XSAVEOPT : I<0xAE, MRM6m, (outs), (ins opaque512mem:$dst),
+ "xsaveopt\t$dst",
+ [(int_x86_xsaveopt addr:$dst, EDX, EAX)]>, TB;
+ def XSAVEOPT64 : RI<0xAE, MRM6m, (outs), (ins opaque512mem:$dst),
+ "xsaveopt64\t$dst",
+ [(int_x86_xsaveopt64 addr:$dst, EDX, EAX)]>, TB, Requires<[In64BitMode]>;
+}
+let Predicates = [HasXSAVEC] in {
+ def XSAVEC : I<0xC7, MRM4m, (outs), (ins opaque512mem:$dst),
+ "xsavec\t$dst",
+ [(int_x86_xsavec addr:$dst, EDX, EAX)]>, TB;
+ def XSAVEC64 : RI<0xC7, MRM4m, (outs), (ins opaque512mem:$dst),
+ "xsavec64\t$dst",
+ [(int_x86_xsavec64 addr:$dst, EDX, EAX)]>, TB, Requires<[In64BitMode]>;
+}
+let Predicates = [HasXSAVES] in {
+ def XSAVES : I<0xC7, MRM5m, (outs), (ins opaque512mem:$dst),
+ "xsaves\t$dst",
+ [(int_x86_xsaves addr:$dst, EDX, EAX)]>, TB;
+ def XSAVES64 : RI<0xC7, MRM5m, (outs), (ins opaque512mem:$dst),
+ "xsaves64\t$dst",
+ [(int_x86_xsaves64 addr:$dst, EDX, EAX)]>, TB, Requires<[In64BitMode]>;
def XRSTORS : I<0xC7, MRM3m, (outs), (ins opaque512mem:$dst),
- "xrstors\t$dst", []>, TB;
+ "xrstors\t$dst",
+ [(int_x86_xrstors addr:$dst, EDX, EAX)]>, TB;
def XRSTORS64 : RI<0xC7, MRM3m, (outs), (ins opaque512mem:$dst),
- "xrstors64\t$dst", []>, TB, Requires<[In64BitMode]>;
- def XSAVEC : I<0xC7, MRM4m, (outs opaque512mem:$dst), (ins),
- "xsavec\t$dst", []>, TB;
- def XSAVEC64 : RI<0xC7, MRM4m, (outs opaque512mem:$dst), (ins),
- "xsavec64\t$dst", []>, TB, Requires<[In64BitMode]>;
- def XSAVES : I<0xC7, MRM5m, (outs opaque512mem:$dst), (ins),
- "xsaves\t$dst", []>, TB;
- def XSAVES64 : RI<0xC7, MRM5m, (outs opaque512mem:$dst), (ins),
- "xsaves64\t$dst", []>, TB, Requires<[In64BitMode]>;
+ "xrstors64\t$dst",
+ [(int_x86_xrstors64 addr:$dst, EDX, EAX)]>, TB, Requires<[In64BitMode]>;
}
+} // Uses
} // SchedRW
//===----------------------------------------------------------------------===//
HasPOPCNT = false;
HasSSE4A = false;
HasAES = false;
+ HasXSAVE = false;
+ HasXSAVEOPT = false;
+ HasXSAVEC = false;
+ HasXSAVES = false;
HasPCLMUL = false;
HasFMA = false;
HasFMA4 = false;
/// Target has AES instructions
bool HasAES;
+ /// Target has XSAVE instructions
+ bool HasXSAVE;
+ /// Target has XSAVEOPT instructions
+ bool HasXSAVEOPT;
+ /// Target has XSAVEC instructions
+ bool HasXSAVEC;
+ /// Target has XSAVES instructions
+ bool HasXSAVES;
+
/// Target has carry-less multiplication
bool HasPCLMUL;
bool has3DNowA() const { return X863DNowLevel >= ThreeDNowA; }
bool hasPOPCNT() const { return HasPOPCNT; }
bool hasAES() const { return HasAES; }
+ bool hasXSAVE() const { return HasXSAVE; }
+ bool hasXSAVEOPT() const { return HasXSAVEOPT; }
+ bool hasXSAVEC() const { return HasXSAVEC; }
+ bool hasXSAVES() const { return HasXSAVES; }
bool hasPCLMUL() const { return HasPCLMUL; }
bool hasFMA() const { return HasFMA; }
// FIXME: Favor FMA when both are enabled. Is this the right thing to do?
--- /dev/null
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+xsave | FileCheck %s\r
+\r
+define void @test_xsave(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsave\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xsave (%rdi)\r
+ call void @llvm.x86.xsave(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsave(i8*, i32, i32)\r
+\r
+define void @test_xsave64(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsave64\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xsave64 (%rdi)\r
+ call void @llvm.x86.xsave64(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsave64(i8*, i32, i32)\r
+\r
+define void @test_xrstor(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xrstor\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xrstor (%rdi)\r
+ call void @llvm.x86.xrstor(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xrstor(i8*, i32, i32)\r
+\r
+define void @test_xrstor64(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xrstor64\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xrstor64 (%rdi)\r
+ call void @llvm.x86.xrstor64(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xrstor64(i8*, i32, i32)\r
--- /dev/null
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+xsave,+xsavec | FileCheck %s\r
+\r
+define void @test_xsavec(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsavec\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xsavec (%rdi)\r
+ call void @llvm.x86.xsavec(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsavec(i8*, i32, i32)\r
+\r
+define void @test_xsavec64(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsavec64\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xsavec64 (%rdi)\r
+ call void @llvm.x86.xsavec64(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsavec64(i8*, i32, i32)\r
--- /dev/null
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+xsaveopt | FileCheck %s\r
+\r
+define void @test_xsaveopt(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsaveopt\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xsaveopt (%rdi)\r
+ call void @llvm.x86.xsaveopt(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsaveopt(i8*, i32, i32)\r
+\r
+define void @test_xsaveopt64(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsaveopt64\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xsaveopt64 (%rdi)\r
+ call void @llvm.x86.xsaveopt64(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsaveopt64(i8*, i32, i32)\r
--- /dev/null
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+xsave,+xsaves | FileCheck %s\r
+\r
+define void @test_xsaves(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsaves\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xsaves (%rdi)\r
+ call void @llvm.x86.xsaves(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsaves(i8*, i32, i32)\r
+\r
+define void @test_xsaves64(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsaves64\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xsaves64 (%rdi)\r
+ call void @llvm.x86.xsaves64(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsaves64(i8*, i32, i32)\r
+\r
+define void @test_xrstors(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xrstors\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xrstors (%rdi)\r
+ call void @llvm.x86.xrstors(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xrstors(i8*, i32, i32)\r
+\r
+define void @test_xrstors64(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xrstors64\r
+; CHECK: movl %edx, %eax\r
+; CHECK: movl %esi, %edx\r
+; CHECK: xrstors64 (%rdi)\r
+ call void @llvm.x86.xrstors64(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xrstors64(i8*, i32, i32)\r
--- /dev/null
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+xsave | FileCheck %s\r
+\r
+define void @test_xsave(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsave\r
+; CHECK: movl 8(%esp), %edx\r
+; CHECK: movl 12(%esp), %eax\r
+; CHECK: movl 4(%esp), %ecx\r
+; CHECK: xsave (%ecx)\r
+ call void @llvm.x86.xsave(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsave(i8*, i32, i32)\r
+\r
+define void @test_xrstor(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xrstor\r
+; CHECK: movl 8(%esp), %edx\r
+; CHECK: movl 12(%esp), %eax\r
+; CHECK: movl 4(%esp), %ecx\r
+; CHECK: xrstor (%ecx)\r
+ call void @llvm.x86.xrstor(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xrstor(i8*, i32, i32)\r
--- /dev/null
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+xsave,+xsavec | FileCheck %s\r
+\r
+define void @test_xsavec(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsavec\r
+; CHECK: movl 8(%esp), %edx\r
+; CHECK: movl 12(%esp), %eax\r
+; CHECK: movl 4(%esp), %ecx\r
+; CHECK: xsavec (%ecx)\r
+ call void @llvm.x86.xsavec(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsavec(i8*, i32, i32)\r
--- /dev/null
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+xsave,+xsaveopt | FileCheck %s\r
+\r
+define void @test_xsaveopt(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsaveopt\r
+; CHECK: movl 8(%esp), %edx\r
+; CHECK: movl 12(%esp), %eax\r
+; CHECK: movl 4(%esp), %ecx\r
+; CHECK: xsaveopt (%ecx)\r
+ call void @llvm.x86.xsaveopt(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsaveopt(i8*, i32, i32)\r
--- /dev/null
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+xsave,+xsaves | FileCheck %s\r
+\r
+define void @test_xsaves(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xsaves\r
+; CHECK: movl 8(%esp), %edx\r
+; CHECK: movl 12(%esp), %eax\r
+; CHECK: movl 4(%esp), %ecx\r
+; CHECK: xsaves (%ecx)\r
+ call void @llvm.x86.xsaves(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xsaves(i8*, i32, i32)\r
+\r
+define void @test_xrstors(i8* %ptr, i32 %hi, i32 %lo) {\r
+; CHECK-LABEL: test_xrstors\r
+; CHECK: movl 8(%esp), %edx\r
+; CHECK: movl 12(%esp), %eax\r
+; CHECK: movl 4(%esp), %ecx\r
+; CHECK: xrstors (%ecx)\r
+ call void @llvm.x86.xrstors(i8* %ptr, i32 %hi, i32 %lo)\r
+ ret void;\r
+}\r
+declare void @llvm.x86.xrstors(i8*, i32, i32)\r