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

Evan Cheng evan.cheng at apple.com
Wed Feb 15 13:59:16 PST 2006



Changes in directory llvm/lib/CodeGen/SelectionDAG:

SelectionDAGISel.cpp updated: 1.160 -> 1.161
---
Log message:

Turn a memcpy from string constant into a series of stores of constant values.


---
Diffs of the changes:  (+69 -47)

 SelectionDAGISel.cpp |  116 ++++++++++++++++++++++++++++++---------------------
 1 files changed, 69 insertions(+), 47 deletions(-)


Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.160 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.161
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.160	Tue Feb 14 19:54:51 2006
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	Wed Feb 15 15:59:04 2006
@@ -807,36 +807,15 @@
 /// getStringValue - Turn an LLVM constant pointer that eventually points to a
 /// global into a string value.  Return an empty string if we can't do it.
 ///
-static std::string getStringValue(Value *V, unsigned Offset = 0) {
-  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
-    if (GV->hasInitializer() && isa<ConstantArray>(GV->getInitializer())) {
-      ConstantArray *Init = cast<ConstantArray>(GV->getInitializer());
-      if (Init->isString()) {
-        std::string Result = Init->getAsString();
-        if (Offset < Result.size()) {
-          // If we are pointing INTO The string, erase the beginning...
-          Result.erase(Result.begin(), Result.begin()+Offset);
-
-          // Take off the null terminator, and any string fragments after it.
-          std::string::size_type NullPos = Result.find_first_of((char)0);
-          if (NullPos != std::string::npos)
-            Result.erase(Result.begin()+NullPos, Result.end());
-          return Result;
-        }
-      }
-    }
-  } else if (Constant *C = dyn_cast<Constant>(V)) {
-    if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
-      return getStringValue(GV, Offset);
-    else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
-      if (CE->getOpcode() == Instruction::GetElementPtr) {
-        // Turn a gep into the specified offset.
-        if (CE->getNumOperands() == 3 &&
-            cast<Constant>(CE->getOperand(1))->isNullValue() &&
-            isa<ConstantInt>(CE->getOperand(2))) {
-          return getStringValue(CE->getOperand(0),
-                   Offset+cast<ConstantInt>(CE->getOperand(2))->getRawValue());
-        }
+static std::string getStringValue(GlobalVariable *GV, unsigned Offset = 0) {
+  if (GV->hasInitializer() && isa<ConstantArray>(GV->getInitializer())) {
+    ConstantArray *Init = cast<ConstantArray>(GV->getInitializer());
+    if (Init->isString()) {
+      std::string Result = Init->getAsString();
+      if (Offset < Result.size()) {
+        // If we are pointing INTO The string, erase the beginning...
+        Result.erase(Result.begin(), Result.begin()+Offset);
+        return Result;
       }
     }
   }
@@ -1523,13 +1502,10 @@
   DAG.setRoot(Result.second);
 }
 
-/// getMemSetValue - Vectorized representation of the memset value
+/// getMemsetValue - Vectorized representation of the memset value
 /// operand.
 static SDOperand getMemsetValue(SDOperand Value, MVT::ValueType VT,
-                                SelectionDAG &DAG) {
-  if (VT == MVT::i8)
-    return Value;
-
+                                SelectionDAG &DAG, TargetLowering &TLI) {
   MVT::ValueType CurVT = VT;
   if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Value)) {
     uint64_t Val   = C->getValue() & 255;
@@ -1556,6 +1532,24 @@
   }
 }
 
+/// getMemsetStringVal - Similar to getMemsetValue. Except this is only
+/// used when a memcpy is turned into a memset when the source is a constant
+/// string ptr.
+static SDOperand getMemsetStringVal(MVT::ValueType VT,
+                                    SelectionDAG &DAG, TargetLowering &TLI,
+                                    std::string &Str, unsigned Offset) {
+  MVT::ValueType CurVT = VT;
+  uint64_t Val = 0;
+  unsigned MSB = getSizeInBits(VT) / 8;
+  if (TLI.isLittleEndian())
+    Offset = Offset + MSB - 1;
+  for (unsigned i = 0; i != MSB; ++i) {
+    Val = (Val << 8) | Str[Offset];
+    Offset += TLI.isLittleEndian() ? -1 : 1;
+  }
+  return DAG.getConstant(Val, VT);
+}
+
 /// getMemBasePlusOffset - Returns base and offset node for the 
 static SDOperand getMemBasePlusOffset(SDOperand Base, unsigned Offset,
                                       SelectionDAG &DAG, TargetLowering &TLI) {
@@ -1640,7 +1634,7 @@
         for (unsigned i = 0; i < NumMemOps; i++) {
           MVT::ValueType VT = MemOps[i];
           unsigned VTSize = getSizeInBits(VT) / 8;
-          SDOperand Value = getMemsetValue(Op2, VT, DAG);
+          SDOperand Value = getMemsetValue(Op2, VT, DAG, TLI);
           SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, getRoot(),
                                         Value,
                                         getMemBasePlusOffset(Op1, Offset, DAG, TLI),
@@ -1655,21 +1649,49 @@
       if (MeetsMaxMemopRequirement(MemOps, TLI.getMaxStoresPerMemcpy(),
                                    Size->getValue(), Align, TLI)) {
         unsigned NumMemOps = MemOps.size();
-        unsigned Offset = 0;
+        unsigned SrcOff = 0, DstOff = 0;
+        GlobalAddressSDNode *G = NULL;
+        std::string Str;
+
+        if (Op2.getOpcode() == ISD::GlobalAddress)
+          G = cast<GlobalAddressSDNode>(Op2);
+        else if (Op2.getOpcode() == ISD::ADD &&
+                 Op2.getOperand(0).getOpcode() == ISD::GlobalAddress &&
+                 Op2.getOperand(1).getOpcode() == ISD::Constant) {
+          G = cast<GlobalAddressSDNode>(Op2.getOperand(0));
+          SrcOff += cast<ConstantSDNode>(Op2.getOperand(1))->getValue();
+        }
+        if (G) {
+          GlobalVariable *GV = dyn_cast<GlobalVariable>(G->getGlobal());
+          if (GV)
+            Str = getStringValue(GV);
+        }
+
         for (unsigned i = 0; i < NumMemOps; i++) {
           MVT::ValueType VT = MemOps[i];
           unsigned VTSize = getSizeInBits(VT) / 8;
-          SDOperand Value =
-            DAG.getLoad(VT, getRoot(),
-                        getMemBasePlusOffset(Op2, Offset, DAG, TLI),
-                        DAG.getSrcValue(I.getOperand(2), Offset));
-          SDOperand Store =
-            DAG.getNode(ISD::STORE, MVT::Other, Value.getValue(1),
-                        Value,
-                        getMemBasePlusOffset(Op1, Offset, DAG, TLI),
-                        DAG.getSrcValue(I.getOperand(1), Offset));
+          SDOperand Value, Chain, Store;
+
+          if (!Str.empty()) {
+            Value = getMemsetStringVal(VT, DAG, TLI, Str, SrcOff);
+            Chain = getRoot();
+            Store =
+              DAG.getNode(ISD::STORE, MVT::Other, Chain, Value,
+                          getMemBasePlusOffset(Op1, DstOff, DAG, TLI),
+                          DAG.getSrcValue(I.getOperand(1), DstOff));
+          } else {
+            Value = DAG.getLoad(VT, getRoot(),
+                        getMemBasePlusOffset(Op2, SrcOff, DAG, TLI),
+                        DAG.getSrcValue(I.getOperand(2), SrcOff));
+            Chain = Value.getValue(1);
+            Store =
+              DAG.getNode(ISD::STORE, MVT::Other, Chain, Value,
+                          getMemBasePlusOffset(Op1, DstOff, DAG, TLI),
+                          DAG.getSrcValue(I.getOperand(1), DstOff));
+          }
           OutChains.push_back(Store);
-          Offset += VTSize;
+          SrcOff += VTSize;
+          DstOff += VTSize;
         }
       }
       break;






More information about the llvm-commits mailing list