[llvm-commits] [llvm] r127741 - in /llvm/trunk: include/llvm/IntrinsicsXCore.td lib/Target/XCore/XCoreISelDAGToDAG.cpp lib/Target/XCore/XCoreInstrInfo.td test/CodeGen/XCore/events.ll

Richard Osborne richard at xmos.com
Wed Mar 16 11:34:00 PDT 2011


Author: friedgold
Date: Wed Mar 16 13:34:00 2011
New Revision: 127741

URL: http://llvm.org/viewvc/llvm-project?rev=127741&view=rev
Log:
Add checkevent intrinsic to check if any resources owned by the current thread
can event.

Modified:
    llvm/trunk/include/llvm/IntrinsicsXCore.td
    llvm/trunk/lib/Target/XCore/XCoreISelDAGToDAG.cpp
    llvm/trunk/lib/Target/XCore/XCoreInstrInfo.td
    llvm/trunk/test/CodeGen/XCore/events.ll

Modified: llvm/trunk/include/llvm/IntrinsicsXCore.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IntrinsicsXCore.td?rev=127741&r1=127740&r2=127741&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IntrinsicsXCore.td (original)
+++ llvm/trunk/include/llvm/IntrinsicsXCore.td Wed Mar 16 13:34:00 2011
@@ -56,5 +56,11 @@
 
   // Intrinsics for events.
   def int_xcore_waitevent : Intrinsic<[llvm_ptr_ty],[], [IntrReadMem]>;
+
+  // If any of the resources owned by the thread are ready this returns the
+  // vector of one of the ready resources. If no resources owned by the thread
+  // are ready then the operand passed to the intrinsic is returned.
+  def int_xcore_checkevent : Intrinsic<[llvm_ptr_ty],[llvm_ptr_ty]>;
+
   def int_xcore_clre : Intrinsic<[],[],[]>;
 }

Modified: llvm/trunk/lib/Target/XCore/XCoreISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/XCore/XCoreISelDAGToDAG.cpp?rev=127741&r1=127740&r2=127741&view=diff
==============================================================================
--- llvm/trunk/lib/Target/XCore/XCoreISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/XCore/XCoreISelDAGToDAG.cpp Wed Mar 16 13:34:00 2011
@@ -49,7 +49,8 @@
         Subtarget(*TM.getSubtargetImpl()) { }
 
     SDNode *Select(SDNode *N);
-    
+    SDNode *SelectBRIND(SDNode *N);
+
     /// getI32Imm - Return a target constant with the specified value, of type
     /// i32.
     inline SDValue getI32Imm(unsigned Imm) {
@@ -154,62 +155,133 @@
 
 SDNode *XCoreDAGToDAGISel::Select(SDNode *N) {
   DebugLoc dl = N->getDebugLoc();
-  EVT NVT = N->getValueType(0);
-  if (NVT == MVT::i32) {
-    switch (N->getOpcode()) {
-    default: break;
-    case ISD::Constant: {
-      uint64_t Val = cast<ConstantSDNode>(N)->getZExtValue();
-      if (immMskBitp(N)) {
-        // Transformation function: get the size of a mask
-        // Look for the first non-zero bit
-        SDValue MskSize = getI32Imm(32 - CountLeadingZeros_32(Val));
-        return CurDAG->getMachineNode(XCore::MKMSK_rus, dl,
-                                      MVT::i32, MskSize);
-      }
-      else if (!isUInt<16>(Val)) {
-        SDValue CPIdx =
-          CurDAG->getTargetConstantPool(ConstantInt::get(
-                                Type::getInt32Ty(*CurDAG->getContext()), Val),
-                                        TLI.getPointerTy());
-        return CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32, 
-                                      MVT::Other, CPIdx, 
-                                      CurDAG->getEntryNode());
-      }
-      break;
-    }
-    case XCoreISD::LADD: {
-      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
-                          N->getOperand(2) };
-      return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
-                                    Ops, 3);
-    }
-    case XCoreISD::LSUB: {
-      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
-                          N->getOperand(2) };
-      return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
-                                    Ops, 3);
-    }
-    case XCoreISD::MACCU: {
-      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
-                        N->getOperand(2), N->getOperand(3) };
-      return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32,
-                                    Ops, 4);
-    }
-    case XCoreISD::MACCS: {
-      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
-                        N->getOperand(2), N->getOperand(3) };
-      return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32,
-                                    Ops, 4);
-    }
-    case XCoreISD::LMUL: {
-      SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
-                        N->getOperand(2), N->getOperand(3) };
-      return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32,
-                                    Ops, 4);
-    }
-    // Other cases are autogenerated.
-    }
+  switch (N->getOpcode()) {
+  default: break;
+  case ISD::Constant: {
+    uint64_t Val = cast<ConstantSDNode>(N)->getZExtValue();
+    if (immMskBitp(N)) {
+      // Transformation function: get the size of a mask
+      // Look for the first non-zero bit
+      SDValue MskSize = getI32Imm(32 - CountLeadingZeros_32(Val));
+      return CurDAG->getMachineNode(XCore::MKMSK_rus, dl,
+                                    MVT::i32, MskSize);
+    }
+    else if (!isUInt<16>(Val)) {
+      SDValue CPIdx =
+        CurDAG->getTargetConstantPool(ConstantInt::get(
+                              Type::getInt32Ty(*CurDAG->getContext()), Val),
+                                      TLI.getPointerTy());
+      return CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32, 
+                                    MVT::Other, CPIdx, 
+                                    CurDAG->getEntryNode());
+    }
+    break;
+  }
+  case XCoreISD::LADD: {
+    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
+                        N->getOperand(2) };
+    return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
+                                  Ops, 3);
+  }
+  case XCoreISD::LSUB: {
+    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
+                        N->getOperand(2) };
+    return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
+                                  Ops, 3);
+  }
+  case XCoreISD::MACCU: {
+    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
+                      N->getOperand(2), N->getOperand(3) };
+    return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32,
+                                  Ops, 4);
+  }
+  case XCoreISD::MACCS: {
+    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
+                      N->getOperand(2), N->getOperand(3) };
+    return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32,
+                                  Ops, 4);
+  }
+  case XCoreISD::LMUL: {
+    SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
+                      N->getOperand(2), N->getOperand(3) };
+    return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32,
+                                  Ops, 4);
+  }
+  case ISD::BRIND:
+    if (SDNode *ResNode = SelectBRIND(N))
+      return ResNode;
+    break;
+  // Other cases are autogenerated.
   }
   return SelectCode(N);
 }
+
+/// Given a chain return a new chain where any appearance of Old is replaced
+/// by New. There must be at most one instruction between Old and Chain and
+/// this instruction must be a TokenFactor. Returns an empty SDValue if 
+/// these conditions don't hold.
+static SDValue
+replaceInChain(SelectionDAG *CurDAG, SDValue Chain, SDValue Old, SDValue New)
+{
+  if (Chain == Old)
+    return New;
+  if (Chain->getOpcode() != ISD::TokenFactor)
+    return SDValue();
+  SmallVector<SDValue, 8> Ops;
+  bool found = false;
+  for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) {
+    if (Chain->getOperand(i) == Old) {
+      Ops.push_back(New);
+      found = true;
+    } else {
+      Ops.push_back(Chain->getOperand(i));
+    }
+  }
+  if (!found)
+    return SDValue();
+  return CurDAG->getNode(ISD::TokenFactor, Chain->getDebugLoc(), MVT::Other,
+                         &Ops[0], Ops.size());
+}
+
+SDNode *XCoreDAGToDAGISel::SelectBRIND(SDNode *N) {
+  DebugLoc dl = N->getDebugLoc();
+  // (brind (int_xcore_checkevent (addr)))
+  SDValue Chain = N->getOperand(0);
+  SDValue Addr = N->getOperand(1);
+  if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN)
+    return 0;
+  unsigned IntNo = cast<ConstantSDNode>(Addr->getOperand(1))->getZExtValue();
+  if (IntNo != Intrinsic::xcore_checkevent)
+    return 0;
+  SDValue nextAddr = Addr->getOperand(2);
+  SDValue CheckEventChainOut(Addr.getNode(), 1);
+  if (!CheckEventChainOut.use_empty()) {
+    // If the chain out of the checkevent intrinsic is an operand of the
+    // indirect branch or used in a TokenFactor which is the operand of the
+    // indirect branch then build a new chain which uses the chain coming into
+    // the checkevent intrinsic instead.
+    SDValue CheckEventChainIn = Addr->getOperand(0);
+    SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut,
+                                      CheckEventChainIn);
+    if (!NewChain.getNode())
+      return 0;
+    Chain = NewChain;
+  }
+  // Enable events on the thread using setsr 1 and then disable them immediately
+  // after with clrsr 1. If any resources owned by the thread are ready an event
+  // will be taken. If no resource is ready we branch to the address which was
+  // the operand to the checkevent intrinsic.
+  SDValue constOne = getI32Imm(1);
+  SDValue Glue =
+    SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue,
+                                   constOne, Chain), 0);
+  Glue =
+    SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue,
+                                   constOne, Glue), 0);
+  if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper &&
+      nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress) {
+    return CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other,
+                                nextAddr->getOperand(0), Glue);
+  }
+  return CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue);
+}

Modified: llvm/trunk/lib/Target/XCore/XCoreInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/XCore/XCoreInstrInfo.td?rev=127741&r1=127740&r2=127741&view=diff
==============================================================================
--- llvm/trunk/lib/Target/XCore/XCoreInstrInfo.td (original)
+++ llvm/trunk/lib/Target/XCore/XCoreInstrInfo.td Wed Mar 16 13:34:00 2011
@@ -692,6 +692,13 @@
 
 defm CLRSR : FU6_LU6_int<"clrsr", int_xcore_clrsr>;
 
+// setsr may cause a branch if it is used to enable events. clrsr may
+// branch if it is executed while events are enabled.
+let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in {
+defm SETSR_branch : FU6_LU6_np<"setsr">;
+defm CLRSR_branch : FU6_LU6_np<"clrsr">;
+}
+
 // U10
 // TODO ldwcpl, blacp
 

Modified: llvm/trunk/test/CodeGen/XCore/events.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/XCore/events.ll?rev=127741&r1=127740&r2=127741&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/XCore/events.ll (original)
+++ llvm/trunk/test/CodeGen/XCore/events.ll Wed Mar 16 13:34:00 2011
@@ -2,6 +2,7 @@
 
 declare void @llvm.xcore.setv.p1i8(i8 addrspace(1)* %r, i8* %p)
 declare i8* @llvm.xcore.waitevent()
+declare i8* @llvm.xcore.checkevent(i8*)
 declare void @llvm.xcore.clre()
 
 define i32 @f(i8 addrspace(1)* %r) nounwind {
@@ -22,3 +23,22 @@
   %retval = phi i32 [1, %L1], [2, %L2]
   ret i32 %retval
 }
+
+define i32 @g(i8 addrspace(1)* %r) nounwind {
+; CHECK: g:
+entry:
+; CHECK: clre
+  call void @llvm.xcore.clre()
+  call void @llvm.xcore.setv.p1i8(i8 addrspace(1)* %r, i8* blockaddress(@f, %L1))
+  %goto_addr = call i8* @llvm.xcore.checkevent(i8 *blockaddress(@f, %L2))
+; CHECK: setsr 1
+; CHECK: clrsr 1
+  indirectbr i8* %goto_addr, [label %L1, label %L2]
+L1:
+  br label %ret
+L2:
+  br label %ret
+ret:
+  %retval = phi i32 [1, %L1], [2, %L2]
+  ret i32 %retval
+}





More information about the llvm-commits mailing list