[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Evan Cheng evan.cheng at apple.com
Tue Feb 14 00:22:51 PST 2006



Changes in directory llvm/lib/CodeGen/SelectionDAG:

SelectionDAGISel.cpp updated: 1.153 -> 1.154
---
Log message:

Expand memset dst, c, size to a series of stores if size falls below the
target specific theshold, e.g. 16 for x86.


---
Diffs of the changes:  (+127 -4)

 SelectionDAGISel.cpp |  131 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 127 insertions(+), 4 deletions(-)


Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.153 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.154
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.153	Mon Feb 13 23:39:35 2006
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	Tue Feb 14 02:22:34 2006
@@ -1523,13 +1523,136 @@
   DAG.setRoot(Result.second);
 }
 
+/// getMemSetValue - Vectorized representation of the memset value
+/// operand.
+static SDOperand getMemsetValue(SDOperand Value, MVT::ValueType VT,
+                                SelectionDAG &DAG) {
+  if (VT == MVT::i8)
+    return Value;
+
+  MVT::ValueType CurVT = VT;
+  if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Value)) {
+    uint64_t Val   = C->getValue() & 255;
+    unsigned Shift = 8;
+    while (CurVT != MVT::i8) {
+      Val = (Val << Shift) | Val;
+      Shift <<= 1;
+      CurVT = (MVT::ValueType)((unsigned)CurVT - 1);
+      assert(MVT::isInteger(CurVT));
+    }
+    return DAG.getConstant(Val, VT);
+  } else {
+    Value = DAG.getNode(ISD::ZERO_EXTEND, VT, Value);
+    unsigned Shift = 8;
+    while (CurVT != MVT::i8) {
+      Value =
+        DAG.getNode(ISD::OR, VT,
+                    DAG.getNode(ISD::SHL, VT, Value,
+                                DAG.getConstant(Shift, MVT::i8)), Value);
+      Shift <<= 1;
+      CurVT = (MVT::ValueType)((unsigned)CurVT - 1);
+      assert(MVT::isInteger(CurVT));
+    }
+
+    return Value;
+  }
+}
+
+/// getMemBasePlusOffset - Returns base and offset node for the 
+static SDOperand getMemBasePlusOffset(SDOperand Base, unsigned Offset,
+                                      SelectionDAG &DAG, TargetLowering &TLI) {
+  MVT::ValueType VT = Base.getValueType();
+  return DAG.getNode(ISD::ADD, VT, Base, DAG.getConstant(Offset, VT));
+}
+
+/// getMemOpTypes - Determines the types of the sequence of 
+/// memory ops to perform memset / memcpy.
+static void getMemOpTypes(std::vector<MVT::ValueType> &MemOps,
+                          uint64_t Size, unsigned Align, TargetLowering &TLI) {
+  MVT::ValueType VT;
+
+  if (TLI.allowsUnalignedMemoryAccesses()) {
+    VT = MVT::i64;
+  } else {
+    switch (Align & 7) {
+    case 0:
+      VT = MVT::i64;
+      break;
+    case 4:
+      VT = MVT::i32;
+      break;
+    case 2:
+      VT = MVT::i16;
+      break;
+    default:
+      VT = MVT::i8;
+      break;
+    }
+  }
+
+  while (!TLI.isTypeLegal(VT)) {
+    VT = (MVT::ValueType)((unsigned)VT - 1);
+    assert(MVT::isInteger(VT));
+  }
+
+  while (Size != 0) {
+    unsigned VTSize = getSizeInBits(VT) / 8;
+    while (VTSize > Size) {
+      VT = (MVT::ValueType)((unsigned)VT - 1);
+      assert(MVT::isInteger(VT));
+      VTSize >>= 1;
+    }
+    MemOps.push_back(VT);
+    Size -= VTSize;
+  }
+}
+
 void SelectionDAGLowering::visitMemIntrinsic(CallInst &I, unsigned Op) {
+  SDOperand Op1 = getValue(I.getOperand(1));
+  SDOperand Op2 = getValue(I.getOperand(2));
+  SDOperand Op3 = getValue(I.getOperand(3));
+  SDOperand Op4 = getValue(I.getOperand(4));
+  unsigned Align = (unsigned)cast<ConstantSDNode>(Op4)->getValue();
+  if (Align == 0) Align = 1;
+
+  if (ConstantSDNode *Size = dyn_cast<ConstantSDNode>(Op3)) {
+    std::vector<MVT::ValueType> MemOps;
+    getMemOpTypes(MemOps, Size->getValue(), Align, TLI);
+    unsigned NumMemOps = MemOps.size();
+
+    // Expand memset / memcpy to a series of load / store ops
+    // if the size operand falls below a certain threshold.
+    std::vector<SDOperand> OutChains;
+    switch (Op) {
+    default: ;  // Do nothing for now.
+    case ISD::MEMSET: {
+      if (NumMemOps <= TLI.getMaxStoresPerMemSet()) {
+        unsigned Offset = 0;
+        for (unsigned i = 0; i < NumMemOps; i++) {
+          MVT::ValueType VT = MemOps[i];
+          unsigned VTSize = getSizeInBits(VT) / 8;
+          SDOperand Value = getMemsetValue(Op2, VT, DAG);
+          OutChains.
+            push_back(DAG.getNode(ISD::STORE, MVT::Other, getRoot(),
+                                  Value,
+                                  getMemBasePlusOffset(Op1, Offset, DAG, TLI),
+                                  DAG.getSrcValue(NULL)));
+          Offset += VTSize;
+        }
+
+        DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains));
+        return;
+      }
+    }
+    }
+  }
+
   std::vector<SDOperand> Ops;
   Ops.push_back(getRoot());
-  Ops.push_back(getValue(I.getOperand(1)));
-  Ops.push_back(getValue(I.getOperand(2)));
-  Ops.push_back(getValue(I.getOperand(3)));
-  Ops.push_back(getValue(I.getOperand(4)));
+  Ops.push_back(Op1);
+  Ops.push_back(Op2);
+  Ops.push_back(Op3);
+  Ops.push_back(Op4);
   DAG.setRoot(DAG.getNode(Op, MVT::Other, Ops));
 }
 






More information about the llvm-commits mailing list