Implement x86 support for @llvm.prefetch. It corresponds to prefetcht{0|1|2} and...
authorEvan Cheng <evan.cheng@apple.com>
Sat, 8 Mar 2008 00:58:38 +0000 (00:58 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Sat, 8 Mar 2008 00:58:38 +0000 (00:58 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48042 91177308-0d34-0410-b5e6-96231b3b80d8

15 files changed:
include/llvm/CodeGen/SelectionDAGNodes.h
lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/Alpha/AlphaISelLowering.cpp
lib/Target/CellSPU/SPUISelLowering.cpp
lib/Target/IA64/IA64ISelLowering.cpp
lib/Target/Mips/MipsISelLowering.cpp
lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/Sparc/SparcISelDAGToDAG.cpp
lib/Target/TargetSelectionDAG.td
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86InstrSSE.td
test/CodeGen/X86/prefetch.ll [new file with mode: 0644]

index 025e9ecea7cfe956d695233728bcf6dfc3022a49..0d0158ac3a9ef15c45a502d108ac7d9bb27878f6 100644 (file)
@@ -591,6 +591,11 @@ namespace ISD {
     // TRAP - Trapping instruction
     TRAP,
 
+    // PREFETCH - This corresponds to a prefetch intrinsic. It takes chains are
+    // their first operand. The other operands are the address to prefetch,
+    // read / write specifier, and locality specifier.
+    PREFETCH,
+
     // OUTCHAIN = MEMBARRIER(INCHAIN, load-load, load-store, store-load, 
     //                       store-store, device)
     // This corresponds to the memory.barrier intrinsic.
index fd9cf1544361be82ba10830dcf44470abf8c3fcb..8e59b53d1cb5b0c75207acecae004312aa4b00f9 100644 (file)
@@ -1142,6 +1142,24 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     }
     break;
 
+  case ISD::PREFETCH:
+    assert(Node->getNumOperands() == 4 && "Invalid Prefetch node!");
+    switch (TLI.getOperationAction(ISD::PREFETCH, MVT::Other)) {
+    default: assert(0 && "This action is not supported yet!");
+    case TargetLowering::Legal:
+      Tmp1 = LegalizeOp(Node->getOperand(0));  // Legalize the chain.
+      Tmp2 = LegalizeOp(Node->getOperand(1));  // Legalize the address.
+      Tmp3 = LegalizeOp(Node->getOperand(2));  // Legalize the rw specifier.
+      Tmp4 = LegalizeOp(Node->getOperand(3));  // Legalize locality specifier.
+      Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4);
+      break;
+    case TargetLowering::Expand:
+      // It's a noop.
+      Result = LegalizeOp(Node->getOperand(0));
+      break;
+    }
+    break;
+
   case ISD::MEMBARRIER: {
     assert(Node->getNumOperands() == 6 && "Invalid MemBarrier node!");
     switch (TLI.getOperationAction(ISD::MEMBARRIER, MVT::Other)) {
index 1db78fe2a405c6e9fe9d29691f41641041538432..b3251b066a4d03a27e64ccc4d2bb94b949e31e91 100644 (file)
@@ -3788,6 +3788,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
       return "<<Unknown Target Node>>";
     }
    
+  case ISD::PREFETCH:      return "Prefetch";
   case ISD::MEMBARRIER:    return "MemBarrier";
   case ISD::ATOMIC_LCS:    return "AtomicLCS";
   case ISD::ATOMIC_LAS:    return "AtomicLAS";
index 016bb1058464b243df950568ae3c03ee9996ad9a..1140e20a44003c6b7f76d5c0cfbb748ae4365856 100644 (file)
@@ -2996,10 +2996,6 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
     DAG.setRoot(DAG.getNode(ISD::STACKRESTORE, MVT::Other, getRoot(), Tmp));
     return 0;
   }
-  case Intrinsic::prefetch:
-    // FIXME: Currently discarding prefetches.
-    return 0;
-  
   case Intrinsic::var_annotation:
     // Discard annotate attributes
     return 0;
@@ -3050,6 +3046,16 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
     DAG.setRoot(DAG.getNode(ISD::TRAP, MVT::Other, getRoot()));
     return 0;
   }
+  case Intrinsic::prefetch: {
+    SDOperand Ops[4];
+    Ops[0] = getRoot();
+    Ops[1] = getValue(I.getOperand(1));
+    Ops[2] = getValue(I.getOperand(2));
+    Ops[3] = getValue(I.getOperand(3));
+    DAG.setRoot(DAG.getNode(ISD::PREFETCH, MVT::Other, &Ops[0], 4));
+    return 0;
+  }
+  
   case Intrinsic::memory_barrier: {
     SDOperand Ops[6];
     Ops[0] = getRoot();
index 92ab18d5775a9218a888d42b4df35eb265519b9a..2e7d985bf8e1a4ff0374b02d198f09b1e70d58a5 100644 (file)
@@ -211,6 +211,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::STACKRESTORE,       MVT::Other, Expand);
   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Expand);
   setOperationAction(ISD::MEMBARRIER        , MVT::Other, Expand);
+  setOperationAction(ISD::PREFETCH          , MVT::Other, Expand);
 
   if (!Subtarget->hasV6Ops()) {
     setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
index 907415d73c3d29c95a61ce54a5d35bd8b594f34d..368c736a7da0a321566b4c783f61ac33c3ace8f2 100644 (file)
@@ -117,6 +117,7 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM)
   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 
   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand);
+  setOperationAction(ISD::PREFETCH, MVT::Other, Expand);
 
   // We want to legalize GlobalAddress and ConstantPool and
   // ExternalSymbols nodes into the appropriate instructions to
index 6d2a9f3d30bf31e827996f7b5e8b26153402dd4b..6d0bd779e30c878dcdc6a8ac053ec0c36ca75450 100644 (file)
@@ -321,6 +321,7 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
   setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand);
   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Expand);
   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64  , Expand);
+  setOperationAction(ISD::PREFETCH          , MVT::Other, Expand);
 
   // Cell SPU has instructions for converting between i64 and fp.
   setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
index 85db947477d966f55270d496599b021724ed082e..e4d4867888e902b397d7c4004c25600a5aff9dd6 100644 (file)
@@ -110,6 +110,7 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM)
       setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
       setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
       setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand);
+      setOperationAction(ISD::PREFETCH          , MVT::Other, Expand);
 
       // Thread Local Storage
       setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
index ed76621131b9261173912202b9ada031e4f9012d..5a0daf87646c387cfb23e44e76466d6b7f795153 100644 (file)
@@ -85,6 +85,7 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)
   setOperationAction(ISD::MEMSET, MVT::Other, Expand);
   setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
   setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
+  setOperationAction(ISD::PREFETCH, MVT::Other, Expand);
 
   setOperationAction(ISD::CTPOP, MVT::i32, Expand);
   setOperationAction(ISD::CTTZ , MVT::i32, Expand);
index 06098de063518f2eb5ab43b4fb2f592249852142..15e3f2d0f2a4baabdbf8fcc631b0fd6d66745b50 100644 (file)
@@ -82,6 +82,7 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
   setOperationAction(ISD::MEMSET, MVT::Other, Expand);
   setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
   setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
+  setOperationAction(ISD::PREFETCH, MVT::Other, Expand);
 
   // PowerPC has no SREM/UREM instructions
   setOperationAction(ISD::SREM, MVT::i32, Expand);
index 95f4e0867307624b8325e6412b8990079755f0dd..08af60779b2db9d8e60dc7577cfe51bdab7bb8b1 100644 (file)
@@ -197,6 +197,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::MEMSET, MVT::Other, Expand);
   setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
   setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
+  setOperationAction(ISD::PREFETCH, MVT::Other, Expand);
 
   setOperationAction(ISD::FSIN , MVT::f64, Expand);
   setOperationAction(ISD::FCOS , MVT::f64, Expand);
index 47d9ba48b7b66f51e4bd7cd557262b626fc986d1..dc0fcb5443ea8b890df4a67fd1b2ae8931202493 100644 (file)
@@ -185,7 +185,11 @@ def SDTVecInsert : SDTypeProfile<1, 3, [  // vector insert
   SDTCisEltOfVec<2, 1>, SDTCisSameAs<0, 1>, SDTCisPtrTy<3>
 ]>;
 
-def STDMemBarrier : SDTypeProfile<0, 5, [
+def STDPrefetch : SDTypeProfile<0, 3, [  // prefetch
+  SDTCisPtrTy<0>, SDTCisSameAs<1, 2>, SDTCisInt<1>
+]>;
+
+def STDMemBarrier : SDTypeProfile<0, 5, [ // memory barier
   SDTCisSameAs<0,1>,  SDTCisSameAs<0,2>,  SDTCisSameAs<0,3>, SDTCisSameAs<0,4>,
   SDTCisInt<0>
 ]>;
@@ -340,15 +344,20 @@ def br         : SDNode<"ISD::BR"         , SDTBr,     [SDNPHasChain]>;
 def ret        : SDNode<"ISD::RET"        , SDTNone,   [SDNPHasChain]>;
 def trap       : SDNode<"ISD::TRAP"       , SDTNone,
                         [SDNPHasChain, SDNPSideEffect]>;
-def membarrier : SDNode<"ISD::MEMBARRIER"       , STDMemBarrier,
+
+def prefetch   : SDNode<"ISD::PREFETCH"   , STDPrefetch,
+                        [SDNPHasChain, SDNPMayLoad, SDNPMayStore]>;
+
+def membarrier : SDNode<"ISD::MEMBARRIER" , STDMemBarrier,
                         [SDNPHasChain, SDNPSideEffect]>;
+
 // Do not use atomic_* directly, use atomic_*_size (see below)
-def atomic_lcs : SDNode<"ISD::ATOMIC_LCS", STDAtomic3,
-                        [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
-def atomic_las : SDNode<"ISD::ATOMIC_LAS", STDAtomic2,
-                        [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
+def atomic_lcs  : SDNode<"ISD::ATOMIC_LCS" , STDAtomic3,
+                         [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
+def atomic_las  : SDNode<"ISD::ATOMIC_LAS" , STDAtomic2,
+                         [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
 def atomic_swap : SDNode<"ISD::ATOMIC_SWAP", STDAtomic2,
-                        [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
+                         [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>;
 
 // Do not use ld, st directly. Use load, extload, sextload, zextload, store,
 // and truncst (see below).
index 22ddd832954975a5c59e182d76799b2b3bd9c6e4..7c70d043bf350c22bc7913b45a6ac2c46e3f9ad6 100644 (file)
@@ -287,6 +287,9 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
   setOperationAction(ISD::MEMSET          , MVT::Other, Custom);
   setOperationAction(ISD::MEMCPY          , MVT::Other, Custom);
 
+  if (!Subtarget->hasSSE1())
+    setOperationAction(ISD::PREFETCH      , MVT::Other, Expand);
+
   if (!Subtarget->hasSSE2())
     setOperationAction(ISD::MEMBARRIER    , MVT::Other, Expand);
 
index 3f174c08cdc7b9a1afe1bbd919ad7a21f6c39742..55d92bdfa6a7b159204126927593b678af904aa3 100644 (file)
@@ -939,12 +939,15 @@ def MOVMSKPDrr : PSI<0x50, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src),
                      "movmskpd\t{$src, $dst|$dst, $src}",
                      [(set GR32:$dst, (int_x86_sse2_movmsk_pd VR128:$src))]>;
 
-// Prefetching loads.
-// TODO: no intrinsics for these?
-def PREFETCHT0   : PSI<0x18, MRM1m, (outs), (ins i8mem:$src), "prefetcht0\t$src", []>;
-def PREFETCHT1   : PSI<0x18, MRM2m, (outs), (ins i8mem:$src), "prefetcht1\t$src", []>;
-def PREFETCHT2   : PSI<0x18, MRM3m, (outs), (ins i8mem:$src), "prefetcht2\t$src", []>;
-def PREFETCHNTA  : PSI<0x18, MRM0m, (outs), (ins i8mem:$src), "prefetchnta\t$src", []>;
+// Prefetch intrinsic.
+def PREFETCHT0   : PSI<0x18, MRM1m, (outs), (ins i8mem:$src),
+    "prefetcht0\t$src", [(prefetch addr:$src, imm, (i32 3))]>;
+def PREFETCHT1   : PSI<0x18, MRM2m, (outs), (ins i8mem:$src),
+    "prefetcht1\t$src", [(prefetch addr:$src, imm, (i32 2))]>;
+def PREFETCHT2   : PSI<0x18, MRM3m, (outs), (ins i8mem:$src),
+    "prefetcht2\t$src", [(prefetch addr:$src, imm, (i32 1))]>;
+def PREFETCHNTA  : PSI<0x18, MRM0m, (outs), (ins i8mem:$src),
+    "prefetchnta\t$src", [(prefetch addr:$src, imm, (i32 0))]>;
 
 // Non-temporal stores
 def MOVNTPSmr : PSI<0x2B, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src),
diff --git a/test/CodeGen/X86/prefetch.ll b/test/CodeGen/X86/prefetch.ll
new file mode 100644 (file)
index 0000000..bcc6e3a
--- /dev/null
@@ -0,0 +1,15 @@
+; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse1 | grep prefetchnta
+; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse1 | grep prefetcht0
+; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse1 | grep prefetcht1
+; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse1 | grep prefetcht2
+
+define void @t(i8* %ptr) nounwind  {
+entry:
+       tail call void @llvm.prefetch( i8* %ptr, i32 0, i32 1 )
+       tail call void @llvm.prefetch( i8* %ptr, i32 0, i32 2 )
+       tail call void @llvm.prefetch( i8* %ptr, i32 0, i32 3 )
+       tail call void @llvm.prefetch( i8* %ptr, i32 0, i32 0 )
+       ret void
+}
+
+declare void @llvm.prefetch(i8*, i32, i32) nounwind