mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[X86] Add xgetbv/xsetbv intrinsics to non-windows platforms
Differential Revision: https://reviews.llvm.org/D21958 llvm-svn: 278782
This commit is contained in:
parent
4ca4b42bf0
commit
6b866e2b9c
@ -4130,6 +4130,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
|
||||
def int_x86_xsaves64 :
|
||||
Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], []>;
|
||||
def int_x86_xgetbv :
|
||||
Intrinsic<[llvm_i64_ty], [llvm_i32_ty], []>;
|
||||
def int_x86_xsetbv :
|
||||
Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -18480,6 +18480,51 @@ static SDValue getPrefetchNode(unsigned Opc, SDValue Op, SelectionDAG &DAG,
|
||||
return SDValue(Res, 0);
|
||||
}
|
||||
|
||||
/// Handles the lowering of builtin intrinsic that return the value
|
||||
/// of the extended control register.
|
||||
static void getExtendedControlRegister(SDNode *N, const SDLoc &DL,
|
||||
SelectionDAG &DAG,
|
||||
const X86Subtarget &Subtarget,
|
||||
SmallVectorImpl<SDValue> &Results) {
|
||||
assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
|
||||
SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue);
|
||||
SDValue LO, HI;
|
||||
|
||||
// The ECX register is used to select the index of the XCR register to
|
||||
// return.
|
||||
SDValue Chain =
|
||||
DAG.getCopyToReg(N->getOperand(0), DL, X86::ECX, N->getOperand(2));
|
||||
SDNode *N1 = DAG.getMachineNode(X86::XGETBV, DL, Tys, Chain);
|
||||
Chain = SDValue(N1, 0);
|
||||
|
||||
// Reads the content of XCR and returns it in registers EDX:EAX.
|
||||
if (Subtarget.is64Bit()) {
|
||||
LO = DAG.getCopyFromReg(Chain, DL, X86::RAX, MVT::i64, SDValue(N1, 1));
|
||||
HI = DAG.getCopyFromReg(LO.getValue(1), DL, X86::RDX, MVT::i64,
|
||||
LO.getValue(2));
|
||||
} else {
|
||||
LO = DAG.getCopyFromReg(Chain, DL, X86::EAX, MVT::i32, SDValue(N1, 1));
|
||||
HI = DAG.getCopyFromReg(LO.getValue(1), DL, X86::EDX, MVT::i32,
|
||||
LO.getValue(2));
|
||||
}
|
||||
Chain = HI.getValue(1);
|
||||
|
||||
if (Subtarget.is64Bit()) {
|
||||
// Merge the two 32-bit values into a 64-bit one..
|
||||
SDValue Tmp = DAG.getNode(ISD::SHL, DL, MVT::i64, HI,
|
||||
DAG.getConstant(32, DL, MVT::i8));
|
||||
Results.push_back(DAG.getNode(ISD::OR, DL, MVT::i64, LO, Tmp));
|
||||
Results.push_back(Chain);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use a buildpair to merge the two 32-bit values into a 64-bit one.
|
||||
SDValue Ops[] = { LO, HI };
|
||||
SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Ops);
|
||||
Results.push_back(Pair);
|
||||
Results.push_back(Chain);
|
||||
}
|
||||
|
||||
/// Handles the lowering of builtin intrinsics that read performance monitor
|
||||
/// counters (x86_rdpmc).
|
||||
static void getReadPerformanceCounter(SDNode *N, const SDLoc &DL,
|
||||
@ -18722,6 +18767,12 @@ static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget &Subtarget,
|
||||
getReadPerformanceCounter(Op.getNode(), dl, DAG, Subtarget, Results);
|
||||
return DAG.getMergeValues(Results, dl);
|
||||
}
|
||||
// Get Extended Control Register.
|
||||
case XGETBV: {
|
||||
SmallVector<SDValue, 2> Results;
|
||||
getExtendedControlRegister(Op.getNode(), dl, DAG, Subtarget, Results);
|
||||
return DAG.getMergeValues(Results, dl);
|
||||
}
|
||||
// XTEST intrinsics.
|
||||
case XTEST: {
|
||||
SDVTList VTs = DAG.getVTList(Op->getValueType(0), MVT::Other);
|
||||
@ -22176,6 +22227,9 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N,
|
||||
Results);
|
||||
case Intrinsic::x86_rdpmc:
|
||||
return getReadPerformanceCounter(N, dl, DAG, Subtarget, Results);
|
||||
|
||||
case Intrinsic::x86_xgetbv:
|
||||
return getExtendedControlRegister(N, dl, DAG, Subtarget, Results);
|
||||
}
|
||||
}
|
||||
case ISD::INTRINSIC_WO_CHAIN: {
|
||||
|
@ -481,8 +481,11 @@ 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;
|
||||
}
|
||||
def XSETBV : I<0x01, MRM_D1, (outs), (ins),
|
||||
"xsetbv",
|
||||
[(int_x86_xsetbv ECX, EDX, EAX)]>, TB;
|
||||
|
||||
} // HasXSAVE
|
||||
|
||||
let Uses = [EDX, EAX] in {
|
||||
let Predicates = [HasXSAVE] in {
|
||||
|
@ -21,7 +21,7 @@ namespace llvm {
|
||||
|
||||
enum IntrinsicType : uint16_t {
|
||||
INTR_NO_TYPE,
|
||||
GATHER, SCATTER, PREFETCH, RDSEED, RDRAND, RDPMC, RDTSC, XTEST, ADX, FPCLASS, FPCLASSS,
|
||||
GATHER, SCATTER, PREFETCH, RDSEED, RDRAND, RDPMC, RDTSC, XTEST, XGETBV, ADX, FPCLASS, FPCLASSS,
|
||||
INTR_TYPE_1OP, INTR_TYPE_2OP, INTR_TYPE_2OP_IMM8, INTR_TYPE_3OP, INTR_TYPE_4OP,
|
||||
CMP_MASK, CMP_MASK_CC,CMP_MASK_SCALAR_CC, VSHIFT, COMI, COMI_RM,
|
||||
INTR_TYPE_1OP_MASK, INTR_TYPE_1OP_MASK_RM,
|
||||
@ -228,6 +228,7 @@ static const IntrinsicData IntrinsicsWithChain[] = {
|
||||
|
||||
X86_INTRINSIC_DATA(subborrow_u32, ADX, X86ISD::SBB, 0),
|
||||
X86_INTRINSIC_DATA(subborrow_u64, ADX, X86ISD::SBB, 0),
|
||||
X86_INTRINSIC_DATA(xgetbv, XGETBV, X86::XGETBV, 0),
|
||||
X86_INTRINSIC_DATA(xtest, XTEST, X86ISD::XTEST, 0),
|
||||
};
|
||||
|
||||
|
21
test/CodeGen/X86/system-intrinsics-xgetbv.ll
Normal file
21
test/CodeGen/X86/system-intrinsics-xgetbv.ll
Normal file
@ -0,0 +1,21 @@
|
||||
; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+xsave | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+xsave | FileCheck %s --check-prefix=CHECK64
|
||||
|
||||
define i64 @test_xgetbv(i32 %in) {
|
||||
; CHECK-LABEL: test_xgetbv
|
||||
; CHECK: movl 4(%esp), %ecx
|
||||
; CHECK: xgetbv
|
||||
; CHECK: ret
|
||||
|
||||
; CHECK64-LABEL: test_xgetbv
|
||||
; CHECK64: movl %edi, %ecx
|
||||
; CHECK64: xgetbv
|
||||
; CHECK64: shlq $32, %rdx
|
||||
; CHECK64: orq %rdx, %rax
|
||||
; CHECK64: ret
|
||||
|
||||
%1 = call i64 @llvm.x86.xgetbv(i32 %in)
|
||||
ret i64 %1;
|
||||
}
|
||||
|
||||
declare i64 @llvm.x86.xgetbv(i32)
|
23
test/CodeGen/X86/system-intrinsics-xsetbv.ll
Normal file
23
test/CodeGen/X86/system-intrinsics-xsetbv.ll
Normal file
@ -0,0 +1,23 @@
|
||||
; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+xsave | FileCheck %s
|
||||
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+xsave | FileCheck %s --check-prefix=CHECK64
|
||||
|
||||
define void @test_xsetbv(i32 %in, i32 %high, i32 %low) {
|
||||
; CHECK-LABEL: test_xsetbv
|
||||
; CHECK: movl 4(%esp), %ecx
|
||||
; CHECK: movl 8(%esp), %edx
|
||||
; CHECK: movl 12(%esp), %eax
|
||||
; CHECK: xsetbv
|
||||
; CHECK: ret
|
||||
|
||||
; CHECK64-LABEL: test_xsetbv
|
||||
; CHECK64: movl %edx, %eax
|
||||
; CHECK64: movl %edi, %ecx
|
||||
; CHECK64: movl %esi, %edx
|
||||
; CHECK64: xsetbv
|
||||
; CHECK64: ret
|
||||
|
||||
call void @llvm.x86.xsetbv(i32 %in, i32 %high, i32 %low)
|
||||
ret void;
|
||||
}
|
||||
declare void @llvm.x86.xsetbv(i32, i32, i32)
|
||||
|
Loading…
Reference in New Issue
Block a user