diff options
-rw-r--r-- | docs/LangRef.html | 34 | ||||
-rw-r--r-- | lib/Analysis/BasicAliasAnalysis.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/IntrinsicLowering.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 3 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaISelPattern.cpp | 5 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaInstrFormats.td | 9 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaInstrInfo.td | 3 | ||||
-rw-r--r-- | lib/VMCore/Function.cpp | 7 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 8 | ||||
-rw-r--r-- | test/CodeGen/Alpha/rpcc.ll | 10 |
12 files changed, 88 insertions, 4 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html index 72dfd88c1b..dd02a9e4a2 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -128,6 +128,7 @@ <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"> diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index 86cc5646be..ef0a685adb 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -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", diff --git a/lib/CodeGen/IntrinsicLowering.cpp b/lib/CodeGen/IntrinsicLowering.cpp index a570ef54c4..256f0ffa56 100644 --- a/lib/CodeGen/IntrinsicLowering.cpp +++ b/lib/CodeGen/IntrinsicLowering.cpp @@ -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: diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 56ab18c773..03813d0f94 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -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. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 3c0baf0563..7b8046ea0f 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -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"; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index e954f15d54..ae61e20896 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -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(), diff --git a/lib/Target/Alpha/AlphaISelPattern.cpp b/lib/Target/Alpha/AlphaISelPattern.cpp index eb13486c7f..791fcedccd 100644 --- a/lib/Target/Alpha/AlphaISelPattern.cpp +++ b/lib/Target/Alpha/AlphaISelPattern.cpp @@ -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: diff --git a/lib/Target/Alpha/AlphaInstrFormats.td b/lib/Target/Alpha/AlphaInstrFormats.td index c34b624dcc..7180409ef5 100644 --- a/lib/Target/Alpha/AlphaInstrFormats.td +++ b/lib/Target/Alpha/AlphaInstrFormats.td @@ -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> { diff --git a/lib/Target/Alpha/AlphaInstrInfo.td b/lib/Target/Alpha/AlphaInstrInfo.td index 55842964a1..e1ae7d13d5 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.td +++ b/lib/Target/Alpha/AlphaInstrInfo.td @@ -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 diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 1e68289f65..291e70a8f4 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -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; diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 0b1670ee71..39800b11bb 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -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 index 0000000000..fbf97ad60c --- /dev/null +++ b/test/CodeGen/Alpha/rpcc.ll @@ -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 +} + |