continued readcyclecounter support
authorAndrew Lenharth <andrewl@lenharth.org>
Fri, 11 Nov 2005 16:47:30 +0000 (16:47 +0000)
committerAndrew Lenharth <andrewl@lenharth.org>
Fri, 11 Nov 2005 16:47:30 +0000 (16:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24300 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
docs/LangRef.html
lib/Analysis/BasicAliasAnalysis.cpp
lib/CodeGen/IntrinsicLowering.cpp
lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/Target/Alpha/AlphaISelPattern.cpp
lib/Target/Alpha/AlphaInstrFormats.td
lib/Target/Alpha/AlphaInstrInfo.td
lib/VMCore/Function.cpp
lib/VMCore/Verifier.cpp
test/CodeGen/Alpha/rpcc.ll [new file with mode: 0644]

index 72dfd88c1b6019a1073356da0322b96137768b8d..dd02a9e4a297956f6327a4a9f76e4e26bf6fba3c 100644 (file)
           <li><a href="#i_frameaddress">'<tt>llvm.frameaddress</tt>'   Intrinsic</a></li>
           <li><a href="#i_prefetch">'<tt>llvm.prefetch</tt>' Intrinsic</a></li>
           <li><a href="#i_pcmarker">'<tt>llvm.pcmarker</tt>' Intrinsic</a></li>
+          <li><a href="#i_readcyclecounter"><tt>llvm.readcyclecounter</tt>' Intrinsic</a></li>
         </ol>
       </li>
       <li><a href="#int_os">Operating System Intrinsics</a>
@@ -2811,6 +2812,39 @@ support this intrinisic may ignore it.
 
 </div>
 
+<!-- _______________________________________________________________________ -->
+<div class="doc_subsubsection">
+  <a name="i_readcyclecounter">'<tt>llvm.readcyclecounter</tt>' Intrinsic</a>
+</div>
+
+<div class="doc_text">
+
+<h5>Syntax:</h5>
+<pre>
+  declare ulong %llvm.readcyclecounter( )
+</pre>
+
+<h5>Overview:</h5>
+
+
+<p>
+The '<tt>llvm.readcyclecounter</tt>' intrinsic provides access to the cycle 
+counter register (or similar low latency, high accuracy clocks) on those targets
+that support it.  On X86, it should map to RDTSC.  On Alpha, it should map to RPCC.
+As the backing counters overflow quickly (on the order of 9 seconds on alpha), this
+should only be used for small timings.  
+</p>
+
+<h5>Semantics:</h5>
+
+<p>
+When directly supported, reading the cycle counter should not modify any memory.  
+Implementations are allowed to either return a application specific value or a
+system wide value.  On backends without support, this is lowered to a constant 0.
+</p>
+
+</div>
+
 
 <!-- ======================================================================= -->
 <div class="doc_subsection">
index 86cc5646be66a398ad8523ca0179984397c2bb53..ef0a685adb9222090d109bdd82f3f184f3dc49c3 100644 (file)
@@ -709,6 +709,7 @@ static const char *DoesntAccessMemoryTable[] = {
   // LLVM intrinsics:
   "llvm.frameaddress", "llvm.returnaddress", "llvm.readport",
   "llvm.isunordered", "llvm.sqrt", "llvm.ctpop", "llvm.ctlz", "llvm.cttz",
+  "llvm.readcyclecounter",
 
   "abs", "labs", "llabs", "imaxabs", "fabs", "fabsf", "fabsl",
   "trunc", "truncf", "truncl", "ldexp",
index a570ef54c4582a1e26f088d52cc1f6d64746efcc..256f0ffa56758ddebaa847fd2d38ee4e717e5be7 100644 (file)
@@ -262,6 +262,12 @@ void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
 
   case Intrinsic::pcmarker:
     break;    // Simply strip out pcmarker on unsupported architectures
+  case Intrinsic::readcyclecounter: {
+    std::cerr << "WARNING: this target does not support the llvm.readcyclecounter"
+              << " intrinsic.  It is being lowered to a constant 0\n";
+    CI->replaceAllUsesWith(ConstantUInt::get(Type::ULongTy, 0));
+    break;
+  }
 
   case Intrinsic::dbg_stoppoint:
   case Intrinsic::dbg_region_start:
index 56ab18c773d515969268b4ad8511e77c2dc3d8bb..03813d0f94d1c48a41f217c21c6a9fa55317bbcc 100644 (file)
@@ -1122,6 +1122,11 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     if (Tmp1 != Node->getOperand(0))
       Result = DAG.getNode(ISD::PCMARKER, MVT::Other, Tmp1,Node->getOperand(1));
     break;
+  case ISD::READCYCLECOUNTER:
+    Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain
+    if (Tmp1 != Node->getOperand(0))
+      Result = DAG.getNode(ISD::READCYCLECOUNTER, MVT::i64, Tmp1);
+    break;
   case ISD::TRUNCSTORE:
     Tmp1 = LegalizeOp(Node->getOperand(0));  // Legalize the chain.
     Tmp3 = LegalizeOp(Node->getOperand(2));  // Legalize the pointer.
index 3c0baf056315671fa9fb50d317df4b164eba0560..7b8046ea0f8519eae9116bbb7755dfb1a79d7eb5 100644 (file)
@@ -1624,6 +1624,7 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const {
     }
    
   case ISD::PCMARKER:      return "PCMarker";
+  case ISD::READCYCLECOUNTER: return "ReadCycleCounter";
   case ISD::SRCVALUE:      return "SrcValue";
   case ISD::VALUETYPE:     return "ValueType";
   case ISD::EntryToken:    return "EntryToken";
index e954f15d5424c6bcdb90080e24ca41408c12592e..ae61e208963e4854cb761189efc68b6753053de5 100644 (file)
@@ -804,6 +804,9 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
     DAG.setRoot(DAG.getNode(ISD::PCMARKER, MVT::Other, getRoot(), Tmp));
     return 0;
   }
+  case Intrinsic::readcyclecounter: 
+    setValue(&I, DAG.getNode(ISD::READCYCLECOUNTER, MVT::i64, getRoot()));
+    return 0;
   case Intrinsic::cttz:
     setValue(&I, DAG.getNode(ISD::CTTZ,
                              getValue(I.getOperand(1)).getValueType(),
index eb13486c7f2e67a3bd9d5afb93587754cf7f1583..791fcedccdeacb8077be78a17f4c2237e697950a 100644 (file)
@@ -549,6 +549,11 @@ unsigned AlphaISel::SelectExpr(SDOperand N) {
     Node->dump();
     assert(0 && "Node not handled!\n");
 
+  case ISD::READCYCLECOUNTER:
+    Select(N.getOperand(0)); //Select chain
+    BuildMI(BB, Alpha::RPCC, 1, Result).addReg(Alpha::R31);
+    return Result;
+
   case ISD::CTPOP:
   case ISD::CTTZ:
   case ISD::CTLZ:
index c34b624dcc344ecb00b672d16e2bd7eaa5f3600d..7180409ef5113f697be7c954332ea9a13406cc85 100644 (file)
@@ -50,6 +50,15 @@ class MForm<bits<6> opcode, string asmstr>
   let Inst{20-16} = Rb;
   let Inst{15-0} = disp;
 }
+class MfcForm<bits<6> opcode, bits<16> fc, string asmstr> 
+        : InstAlpha<opcode, (ops GPRC:$RA, GPRC:$RB), asmstr> {
+  bits<5> Ra;
+  bits<5> Rb;
+
+  let Inst{25-21} = Ra;
+  let Inst{20-16} = Rb;
+  let Inst{15-0} = fc;
+}
 
 class MgForm<bits<6> opcode, string asmstr> 
         : InstAlpha<opcode, (ops GPRC:$RA, s16imm:$DISP, GPRC:$RB, s16imm:$NUM), asmstr> {
index 55842964a1598ffbdd973f0606b5ed4051b58186..e1ae7d13d5c4c369c851c567db57fd5478b2c0b6 100644 (file)
@@ -465,6 +465,8 @@ def FBLE : FBForm<0x33, "fble $RA,$DISP">; //Floating branch if <= zero
 def FBLT : FBForm<0x32, "fblt $RA,$DISP">; //Floating branch if < zero
 def FBNE : FBForm<0x35, "fbne $RA,$DISP">; //Floating branch if != zero
 
+def RPCC : MfcForm<0x18, 0xC000, "rpcc $RA">; //Read process cycle counter
+
 //Basic Floating point ops
 
 //Floats
@@ -558,7 +560,6 @@ def CVTTS : FPForm<0x16, 0x7AC, "cvtts/sui $RB,$RC",
 //LDQ_L Mem 2B Load quadword locked
 //LDQ_U Mem 0B Load unaligned quadword
 //MB Mfc 18.4000 Memory barrier
-//RPCC Mfc 18.C000 Read process cycle counter
 //STL_C Mem 2E Store longword conditional
 //STQ_C Mem 2F Store quadword conditional
 //STQ_U Mem 0F Store unaligned quadword
index 1e68289f652d657b8eeffd8cb9706c2766e42cdf..291e70a8f45b1d91f57bb47b6af44caa767933c6 100644 (file)
@@ -243,9 +243,10 @@ unsigned Function::getIntrinsicID() const {
     if (getName() == "llvm.pcmarker")  return Intrinsic::pcmarker;
     break;
   case 'r':
-    if (getName() == "llvm.returnaddress")  return Intrinsic::returnaddress;
-    if (getName() == "llvm.readport")       return Intrinsic::readport;
-    if (getName() == "llvm.readio")         return Intrinsic::readio;
+    if (getName() == "llvm.returnaddress")    return Intrinsic::returnaddress;
+    if (getName() == "llvm.readport")         return Intrinsic::readport;
+    if (getName() == "llvm.readio")           return Intrinsic::readio;
+    if (getName() == "llvm.readcyclecounter") return Intrinsic::readcyclecounter;
     break;
   case 's':
     if (getName() == "llvm.setjmp")     return Intrinsic::setjmp;
index 0b1670ee7105bc2137eeaee956f78399146632b3..39800b11bb87ec3ddee68e1b862aab495fbb0721 100644 (file)
@@ -726,6 +726,14 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
     NumArgs = 2;
     break;
 
+  case Intrinsic::readcyclecounter:
+    Assert1(FT->getNumParams() == 0,
+            "Illegal # arguments for intrinsic function!", IF);
+    Assert1(FT->getReturnType() == Type::ULongTy,
+            "Return type is not ulong!", IF);
+    NumArgs = 0;
+    break;
+
   case Intrinsic::ctpop:
   case Intrinsic::ctlz:
   case Intrinsic::cttz:
diff --git a/test/CodeGen/Alpha/rpcc.ll b/test/CodeGen/Alpha/rpcc.ll
new file mode 100644 (file)
index 0000000..fbf97ad
--- /dev/null
@@ -0,0 +1,10 @@
+; RUN: llvm-as < %s | llc -march=alpha | grep rpcc
+
+declare ulong %llvm.readcyclecounter()
+
+ulong %foo() {
+entry:
+%tmp.1 = call ulong %llvm.readcyclecounter ()
+ret ulong %tmp.1
+}
+