<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>
</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">
// 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",
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:
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.
}
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";
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(),
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:
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> {
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
//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
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;
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:
--- /dev/null
+; 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
+}
+