From: Jakob Stoklund Olesen Date: Sat, 8 Aug 2009 21:42:22 +0000 (+0000) Subject: Add support for READCYCLECOUNTER in Blackfin back-end. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=46151de6a0d08184c1bfc90bb39657ff1e21729e;p=oota-llvm.git Add support for READCYCLECOUNTER in Blackfin back-end. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78506 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Blackfin/BlackfinISelLowering.cpp b/lib/Target/Blackfin/BlackfinISelLowering.cpp index ebfd61cc55f..fe06d57acf5 100644 --- a/lib/Target/Blackfin/BlackfinISelLowering.cpp +++ b/lib/Target/Blackfin/BlackfinISelLowering.cpp @@ -111,6 +111,9 @@ BlackfinTargetLowering::BlackfinTargetLowering(TargetMachine &TM) setOperationAction(ISD::CTLZ, MVT::i32, Expand); setOperationAction(ISD::CTTZ, MVT::i32, Expand); + // READCYCLECOUNTER needs special type legalization. + setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom); + // We don't have line number support yet. setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand); setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); @@ -463,6 +466,34 @@ SDValue BlackfinTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { } } +void +BlackfinTargetLowering::ReplaceNodeResults(SDNode *N, + SmallVectorImpl &Results, + SelectionDAG &DAG) { + DebugLoc dl = N->getDebugLoc(); + switch (N->getOpcode()) { + default: + llvm_unreachable("Do not know how to custom type legalize this operation!"); + return; + case ISD::READCYCLECOUNTER: { + // The low part of the cycle counter is in CYCLES, the high part in + // CYCLES2. Reading CYCLES will latch the value of CYCLES2, so we must read + // CYCLES2 last. + SDValue TheChain = N->getOperand(0); + SDValue lo = DAG.getCopyFromReg(TheChain, dl, BF::CYCLES, MVT::i32); + SDValue hi = DAG.getCopyFromReg(lo.getValue(1), dl, BF::CYCLES2, MVT::i32); + // Use a buildpair to merge the two 32-bit values into a 64-bit one. + Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, lo, hi)); + // Outgoing chain. If we were to use the chain from lo instead, it would be + // possible to entirely eliminate the CYCLES2 read in (i32 (trunc + // readcyclecounter)). Unfortunately this could possibly delay the CYCLES2 + // read beyond the next CYCLES read, leading to invalid results. + Results.push_back(hi.getValue(1)); + return; + } + } +} + /// getFunctionAlignment - Return the Log2 alignment of this function. unsigned BlackfinTargetLowering::getFunctionAlignment(const Function *F) const { return 2; diff --git a/lib/Target/Blackfin/BlackfinISelLowering.h b/lib/Target/Blackfin/BlackfinISelLowering.h index c1ad11fc91d..fd0d30cb3a8 100644 --- a/lib/Target/Blackfin/BlackfinISelLowering.h +++ b/lib/Target/Blackfin/BlackfinISelLowering.h @@ -35,6 +35,9 @@ namespace llvm { BlackfinTargetLowering(TargetMachine &TM); virtual MVT getSetCCResultType(MVT VT) const; virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG); + virtual void ReplaceNodeResults(SDNode *N, + SmallVectorImpl &Results, + SelectionDAG &DAG); int getVarArgsFrameOffset() const { return VarArgsFrameOffset; } diff --git a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp index 37fa4c9e3aa..86a955079fe 100644 --- a/lib/Target/Blackfin/BlackfinRegisterInfo.cpp +++ b/lib/Target/Blackfin/BlackfinRegisterInfo.cpp @@ -74,6 +74,7 @@ BlackfinRegisterInfo::getReservedRegs(const MachineFunction &MF) const { Reserved.set(AV1S); Reserved.set(V); Reserved.set(VS); + Reserved.set(CYCLES).set(CYCLES2); Reserved.set(L0); Reserved.set(L1); Reserved.set(L2); diff --git a/test/CodeGen/Blackfin/cycles.ll b/test/CodeGen/Blackfin/cycles.ll index 042cb57ffc9..745e25947b0 100644 --- a/test/CodeGen/Blackfin/cycles.ll +++ b/test/CodeGen/Blackfin/cycles.ll @@ -1,11 +1,17 @@ -; RUN: llvm-as < %s | llc -march=bfin | grep cycles -; XFAIL: * -; ExpandIntegerResult #0: 0x181a60c: i64,ch = ReadCycleCounter 0x1104b08 -; Do not know how to expand the result of this operator! +; RUN: llvm-as < %s | llc -march=bfin | FileCheck %s declare i64 @llvm.readcyclecounter() -define i64 @foo() { +; CHECK: cycles +; CHECK: cycles2 +define i64 @cyc64() { %tmp.1 = call i64 @llvm.readcyclecounter() ret i64 %tmp.1 } + +; CHECK: cycles +define i32@cyc32() { + %tmp.1 = call i64 @llvm.readcyclecounter() + %s = trunc i64 %tmp.1 to i32 + ret i32 %s +}