[llvm] r341698 - [X86] Modify the the rdtscp intrinsic to return values instead of taking a pointer argument

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 7 12:14:15 PDT 2018


Author: ctopper
Date: Fri Sep  7 12:14:15 2018
New Revision: 341698

URL: http://llvm.org/viewvc/llvm-project?rev=341698&view=rev
Log:
[X86] Modify the the rdtscp intrinsic to return values instead of taking a pointer argument

Similar to what was recently done for addcarry/subborrow and has been done for rdrand/rdseed for a while. It's better to use two results and an explicit store in IR when the store isn't part of the semantics of the instruction. This allows store->load forwarding to happen in the middle end. Or the store to be removed if its never loaded.

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

Added:
    llvm/trunk/test/CodeGen/X86/rdtsc-upgrade.ll
Modified:
    llvm/trunk/include/llvm/IR/IntrinsicsX86.td
    llvm/trunk/lib/IR/AutoUpgrade.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/test/CodeGen/X86/rdtsc.ll

Modified: llvm/trunk/include/llvm/IR/IntrinsicsX86.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/IntrinsicsX86.td?rev=341698&r1=341697&r2=341698&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/IntrinsicsX86.td (original)
+++ llvm/trunk/include/llvm/IR/IntrinsicsX86.td Fri Sep  7 12:14:15 2018
@@ -53,8 +53,8 @@ let TargetPrefix = "x86" in {
 let TargetPrefix = "x86" in {
   def int_x86_rdtsc : GCCBuiltin<"__builtin_ia32_rdtsc">,
               Intrinsic<[llvm_i64_ty], [], []>;
-  def int_x86_rdtscp : GCCBuiltin<"__builtin_ia32_rdtscp">,
-              Intrinsic<[llvm_i64_ty], [llvm_ptr_ty], [IntrArgMemOnly]>;
+  def int_x86_rdtscp :
+              Intrinsic<[llvm_i64_ty, llvm_i32_ty], [], []>;
 }
 
 // Read Performance-Monitoring Counter.

Modified: llvm/trunk/lib/IR/AutoUpgrade.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AutoUpgrade.cpp?rev=341698&r1=341697&r2=341698&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AutoUpgrade.cpp (original)
+++ llvm/trunk/lib/IR/AutoUpgrade.cpp Fri Sep  7 12:14:15 2018
@@ -395,6 +395,17 @@ static bool UpgradeX86IntrinsicFunction(
   if (Name == "subborrow.u64")
     return UpgradeADCSBBIntrinsic(F, Intrinsic::x86_subborrow_u64, NewFn);
 
+  if (Name == "rdtscp") {
+    // If this intrinsic has 0 operands, it's the new version.
+    if (F->getFunctionType()->getNumParams() == 0)
+      return false;
+
+    rename(F);
+    NewFn = Intrinsic::getDeclaration(F->getParent(),
+                                      Intrinsic::x86_rdtscp);
+    return true;
+  }
+
   // SSE4.1 ptest functions may have an old signature.
   if (Name.startswith("sse41.ptest")) { // Added in 3.2
     if (Name.substr(11) == "c")
@@ -3441,6 +3452,32 @@ void llvm::UpgradeIntrinsicCall(CallInst
     break;
   }
 
+  case Intrinsic::x86_rdtscp: {
+    // This used to take 1 arguments. If we have no arguments, it is already
+    // upgraded.
+    if (CI->getNumOperands() == 0)
+      return;
+
+    NewCall = Builder.CreateCall(NewFn);
+    // Extract the second result and store it.
+    Value *Data = Builder.CreateExtractValue(NewCall, 1);
+    // Cast the pointer to the right type.
+    Value *Ptr = Builder.CreateBitCast(CI->getArgOperand(0),
+                                 llvm::PointerType::getUnqual(Data->getType()));
+    Builder.CreateAlignedStore(Data, Ptr, 1);
+    // Replace the original call result with the first result of the new call.
+    Value *TSC = Builder.CreateExtractValue(NewCall, 0);
+
+    std::string Name = CI->getName();
+    if (!Name.empty()) {
+      CI->setName(Name + ".old");
+      NewCall->setName(Name);
+    }
+    CI->replaceAllUsesWith(TSC);
+    CI->eraseFromParent();
+    return;
+  }
+
   case Intrinsic::x86_addcarryx_u32:
   case Intrinsic::x86_addcarryx_u64:
   case Intrinsic::x86_addcarry_u32:

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=341698&r1=341697&r2=341698&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Fri Sep  7 12:14:15 2018
@@ -21746,39 +21746,39 @@ static void getReadTimeStampCounter(SDNo
   }
   SDValue Chain = HI.getValue(1);
 
+  SDValue TSC;
+  if (Subtarget.is64Bit()) {
+    // The EDX register is loaded with the high-order 32 bits of the MSR, and
+    // the EAX register is loaded with the low-order 32 bits.
+    TSC = DAG.getNode(ISD::SHL, DL, MVT::i64, HI,
+                      DAG.getConstant(32, DL, MVT::i8));
+    TSC = DAG.getNode(ISD::OR, DL, MVT::i64, LO, TSC);
+  } else {
+    // Use a buildpair to merge the two 32-bit values into a 64-bit one.
+    TSC = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, { LO, HI });
+  }
+
   if (Opcode == X86ISD::RDTSCP_DAG) {
-    assert(N->getNumOperands() == 3 && "Unexpected number of operands!");
+    assert(N->getNumOperands() == 2 && "Unexpected number of operands!");
 
     // Instruction RDTSCP loads the IA32:TSC_AUX_MSR (address C000_0103H) into
     // the ECX register. Add 'ecx' explicitly to the chain.
     SDValue ecx = DAG.getCopyFromReg(Chain, DL, X86::ECX, MVT::i32,
                                      HI.getValue(2));
-    // Explicitly store the content of ECX at the location passed in input
-    // to the 'rdtscp' intrinsic.
-    Chain = DAG.getStore(ecx.getValue(1), DL, ecx, N->getOperand(2),
-                         MachinePointerInfo());
-  }
 
-  if (Subtarget.is64Bit()) {
-    // The EDX register is loaded with the high-order 32 bits of the MSR, and
-    // the EAX register is loaded with the low-order 32 bits.
-    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);
+    Results.push_back(TSC);
+    Results.push_back(ecx);
+    Results.push_back(ecx.getValue(1));
     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(TSC);
   Results.push_back(Chain);
 }
 
 static SDValue LowerREADCYCLECOUNTER(SDValue Op, const X86Subtarget &Subtarget,
                                      SelectionDAG &DAG) {
-  SmallVector<SDValue, 2> Results;
+  SmallVector<SDValue, 3> Results;
   SDLoc DL(Op);
   getReadTimeStampCounter(Op.getNode(), DL, X86ISD::RDTSC_DAG, DAG, Subtarget,
                           Results);

Added: llvm/trunk/test/CodeGen/X86/rdtsc-upgrade.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/rdtsc-upgrade.ll?rev=341698&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/rdtsc-upgrade.ll (added)
+++ llvm/trunk/test/CodeGen/X86/rdtsc-upgrade.ll Fri Sep  7 12:14:15 2018
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mcpu=generic | FileCheck %s --check-prefix=X86
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=generic | FileCheck %s --check-prefix=X64
+
+; Verify upgrading of the old form of the rdtscp intrinsic.
+
+define i64 @test_builtin_rdtscp(i8* %A) {
+; X86-LABEL: test_builtin_rdtscp:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 8
+; X86-NEXT:    .cfi_offset %esi, -8
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X86-NEXT:    rdtscp
+; X86-NEXT:    movl %ecx, (%esi)
+; X86-NEXT:    popl %esi
+; X86-NEXT:    .cfi_def_cfa_offset 4
+; X86-NEXT:    retl
+;
+; X64-LABEL: test_builtin_rdtscp:
+; X64:       # %bb.0:
+; X64-NEXT:    rdtscp
+; X64-NEXT:    shlq $32, %rdx
+; X64-NEXT:    orq %rdx, %rax
+; X64-NEXT:    movl %ecx, (%rdi)
+; X64-NEXT:    retq
+  %1 = tail call i64 @llvm.x86.rdtscp(i8* %A)
+  ret i64 %1
+}
+
+declare i64 @llvm.x86.rdtscp(i8*)

Modified: llvm/trunk/test/CodeGen/X86/rdtsc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/rdtsc.ll?rev=341698&r1=341697&r2=341698&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/rdtsc.ll (original)
+++ llvm/trunk/test/CodeGen/X86/rdtsc.ll Fri Sep  7 12:14:15 2018
@@ -56,15 +56,19 @@ define i64 @test_builtin_rdtscp(i8* %A)
 ; X64-LABEL: test_builtin_rdtscp:
 ; X64:       # %bb.0:
 ; X64-NEXT:    rdtscp
-; X64-NEXT:    movl %ecx, (%rdi)
 ; X64-NEXT:    shlq $32, %rdx
 ; X64-NEXT:    orq %rdx, %rax
+; X64-NEXT:    movl %ecx, (%rdi)
 ; X64-NEXT:    retq
-  %1 = tail call i64 @llvm.x86.rdtscp(i8* %A)
-  ret i64 %1
+  %1 = call { i64, i32 } @llvm.x86.rdtscp()
+  %2 = extractvalue { i64, i32 } %1, 1
+  %3 = bitcast i8* %A to i32*
+  store i32 %2, i32* %3, align 1
+  %4 = extractvalue { i64, i32 } %1, 0
+  ret i64 %4
 }
 
 declare i64 @llvm.readcyclecounter()
-declare i64 @llvm.x86.rdtscp(i8*)
+declare { i64, i32 } @llvm.x86.rdtscp()
 declare i64 @llvm.x86.rdtsc()
 




More information about the llvm-commits mailing list