[llvm] r278782 - [X86] Add xgetbv/xsetbv intrinsics to non-windows platforms

Guy Blank via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 15 23:41:00 PDT 2016


Author: guyblank
Date: Tue Aug 16 01:41:00 2016
New Revision: 278782

URL: http://llvm.org/viewvc/llvm-project?rev=278782&view=rev
Log:
[X86] Add xgetbv/xsetbv intrinsics to non-windows platforms

Differential Revision: https://reviews.llvm.org/D21958

Added:
    llvm/trunk/test/CodeGen/X86/system-intrinsics-xgetbv.ll
    llvm/trunk/test/CodeGen/X86/system-intrinsics-xsetbv.ll
Modified:
    llvm/trunk/include/llvm/IR/IntrinsicsX86.td
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/lib/Target/X86/X86InstrSystem.td
    llvm/trunk/lib/Target/X86/X86IntrinsicsInfo.h

Modified: llvm/trunk/include/llvm/IR/IntrinsicsX86.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/IntrinsicsX86.td?rev=278782&r1=278781&r2=278782&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/IntrinsicsX86.td (original)
+++ llvm/trunk/include/llvm/IR/IntrinsicsX86.td Tue Aug 16 01:41:00 2016
@@ -4130,6 +4130,10 @@ let TargetPrefix = "x86" in {  // All in
               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], []>;
 }
 
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=278782&r1=278781&r2=278782&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Aug 16 01:41:00 2016
@@ -18480,6 +18480,51 @@ static SDValue getPrefetchNode(unsigned
   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(SD
     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::ReplaceNodeResul
                                      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: {

Modified: llvm/trunk/lib/Target/X86/X86InstrSystem.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSystem.td?rev=278782&r1=278781&r2=278782&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrSystem.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrSystem.td Tue Aug 16 01:41:00 2016
@@ -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 {

Modified: llvm/trunk/lib/Target/X86/X86IntrinsicsInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86IntrinsicsInfo.h?rev=278782&r1=278781&r2=278782&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86IntrinsicsInfo.h (original)
+++ llvm/trunk/lib/Target/X86/X86IntrinsicsInfo.h Tue Aug 16 01:41:00 2016
@@ -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 IntrinsicsWit
 
   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),
 };
 

Added: llvm/trunk/test/CodeGen/X86/system-intrinsics-xgetbv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/system-intrinsics-xgetbv.ll?rev=278782&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/system-intrinsics-xgetbv.ll (added)
+++ llvm/trunk/test/CodeGen/X86/system-intrinsics-xgetbv.ll Tue Aug 16 01:41:00 2016
@@ -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)
\ No newline at end of file

Added: llvm/trunk/test/CodeGen/X86/system-intrinsics-xsetbv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/system-intrinsics-xsetbv.ll?rev=278782&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/system-intrinsics-xsetbv.ll (added)
+++ llvm/trunk/test/CodeGen/X86/system-intrinsics-xsetbv.ll Tue Aug 16 01:41:00 2016
@@ -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)
+




More information about the llvm-commits mailing list