Significant improvement: GEP used by a load or store no longer generates
authorVikram S. Adve <vadve@cs.uiuc.edu>
Mon, 14 Oct 2002 16:30:55 +0000 (16:30 +0000)
committerVikram S. Adve <vadve@cs.uiuc.edu>
Mon, 14 Oct 2002 16:30:55 +0000 (16:30 +0000)
a separate ADD; instead just use the indexed load/store instruction!
Also, a bug fix: folding a GEP with a leading non-zero index with
its predecessor was incorrect: now it only happens if the predecessor
is pointing to an indexable type (aka SequentialType).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4168 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp
lib/Target/SparcV9/InstrSelection/InstrSelectionSupport.cpp

index aff6c30e22652e84e66a1b2acbdfc8d703d62ec7..731f3355af1bc655f6656360c2efe1e37b924554 100644 (file)
@@ -154,14 +154,14 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
       assert((*firstIdx)->getType() == Type::LongTy &&
              "INTERNAL ERROR: Structure index for a pointer type!");
 
-      // If the last instruction had a leading non-zero index,
-      // check if the current one ends with an array index.  If not,
-      // the code is not type-safe and we would create an illegal GEP
+      // If the last instruction had a leading non-zero index, check if the
+      // current one references a sequential (i.e., indexable) type.
+      // If not, the code is not type-safe and we would create an illegal GEP
       // by folding them, so don't fold any more instructions.
       // 
       if (lastInstHasLeadingNonZero)
-        if (firstIdx != lastIdx && (*(lastIdx-1))->getType() != Type::LongTy)
-          break; // cannot fold in any preceding getElementPtr instrs.
+        if (! isa<SequentialType>(gepInst->getType()->getElementType()))
+          break;   // cannot fold in any preceding getElementPtr instrs.
 
       // Check that all offsets are constant for this instruction
       for (OI = firstIdx; allConstantOffsets && OI != lastIdx; ++OI)
@@ -197,6 +197,56 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
 }
 
 
+//---------------------------------------------------------------------------
+// Function: GetGEPInstArgs
+// 
+// Purpose:
+//   Helper function for GetMemInstArgs that handles the final getElementPtr
+//   instruction used by (or same as) the memory operation.
+//   Extracts the indices of the current instruction and tries to fold in
+//   preceding ones if all indices of the current one are constant.
+//---------------------------------------------------------------------------
+
+Value*
+GetGEPInstArgs(InstructionNode* gepNode,
+               vector<Value*>& idxVec,
+               bool& allConstantIndices)
+{
+  allConstantIndices = true;
+  GetElementPtrInst* gepI = cast<GetElementPtrInst>(gepNode->getInstruction());
+
+  // Default pointer is the one from the current instruction.
+  Value* ptrVal = gepI->getPointerOperand();
+  InstrTreeNode* ptrChild = gepNode->leftChild(); 
+
+  // Extract the index vector of the GEP instructin.
+  // If all indices are constant and first index is zero, try to fold
+  // in preceding GEPs with all constant indices.
+  for (User::op_iterator OI=gepI->idx_begin(),  OE=gepI->idx_end();
+       allConstantIndices && OI != OE; ++OI)
+    if (! isa<Constant>(*OI))
+      allConstantIndices = false;     // note: this also terminates loop!
+
+  // If we have only constant indices, fold chains of constant indices
+  // in this and any preceding GetElemPtr instructions.
+  bool foldedGEPs = false;
+  bool leadingNonZeroIdx = gepI && ! IsZero(*gepI->idx_begin());
+  if (allConstantIndices)
+    if (Value* newPtr = FoldGetElemChain(ptrChild, idxVec, leadingNonZeroIdx))
+      {
+        ptrVal = newPtr;
+        foldedGEPs = true;
+      }
+
+  // Append the index vector of the current instruction.
+  // Skip the leading [0] index if preceding GEPs were folded into this.
+  idxVec.insert(idxVec.end(),
+                gepI->idx_begin() + (foldedGEPs && !leadingNonZeroIdx),
+                gepI->idx_end());
+
+  return ptrVal;
+}
+
 //---------------------------------------------------------------------------
 // Function: GetMemInstArgs
 // 
@@ -215,11 +265,11 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
 //---------------------------------------------------------------------------
 
 Value*
-GetMemInstArgs(const InstructionNode* memInstrNode,
+GetMemInstArgs(InstructionNode* memInstrNode,
                vector<Value*>& idxVec,
                bool& allConstantIndices)
 {
-  allConstantIndices = true;
+  allConstantIndices = false;
   Instruction* memInst = memInstrNode->getInstruction();
   assert(idxVec.size() == 0 && "Need empty vector to return indices");
 
@@ -229,41 +279,29 @@ GetMemInstArgs(const InstructionNode* memInstrNode,
   InstrTreeNode* ptrChild = (memInst->getOpcode() == Instruction::Store
                              ? memInstrNode->rightChild()
                              : memInstrNode->leftChild()); 
-
+  
   // Default pointer is the one from the current instruction.
   Value* ptrVal = ptrChild->getValue(); 
 
-  // GEP is the only indexed memory instruction.  Extract its index vector.
-  // Also, if all indices are constant and first index is zero, try to fold
-  // in preceding GEPs with all constant indices.
-  GetElementPtrInst* gepI = dyn_cast<GetElementPtrInst>(memInst);
-  if (gepI)
-    for (User::op_iterator OI=gepI->idx_begin(),  OE=gepI->idx_end();
-         allConstantIndices && OI != OE; ++OI)
-      if (! isa<Constant>(*OI))
-        allConstantIndices = false;     // note: this also terminates loop!
-
-  // If we have only constant indices, fold chains of constant indices
-  // in this and any preceding GetElemPtr instructions.
-  bool foldedGEPs = false;
-  bool leadingNonZeroIdx = gepI && ! IsZero(*gepI->idx_begin());
-  if (allConstantIndices)
-    if (Value* newPtr = FoldGetElemChain(ptrChild, idxVec, leadingNonZeroIdx))
-      {
-        ptrVal = newPtr;
-        foldedGEPs = true;
-      }
-
-  // Append the index vector of the current instruction, if any.
-  // Skip the leading [0] index if preceding GEPs were folded into this.
-  if (gepI)
-    idxVec.insert(idxVec.end(),
-                  gepI->idx_begin() + (foldedGEPs && !leadingNonZeroIdx),
-                  gepI->idx_end());
+  // Find the "last" GetElemPtr instruction: this one or the immediate child.
+  // There will be none if this is a load or a store from a scalar pointer.
+  InstructionNode* gepNode = NULL;
+  if (isa<GetElementPtrInst>(memInst))
+    gepNode = memInstrNode;
+  else if (isa<InstructionNode>(ptrChild) && isa<GetElementPtrInst>(ptrVal))
+    { // Child of load/store is a GEP and memInst is its only use.
+      // Use its indices and mark it as folded.
+      gepNode = cast<InstructionNode>(ptrChild);
+      gepNode->markFoldedIntoParent();
+    }
 
-  return ptrVal;
+  // If there are no indices, return the current pointer.
+  // Else extract the pointer from the GEP and fold the indices.
+  return (gepNode)? GetGEPInstArgs(gepNode, idxVec, allConstantIndices)
+                  : ptrVal;
 }
 
+
 //------------------------------------------------------------------------ 
 // Function Set2OperandsFromInstr
 // Function Set3OperandsFromInstr
index aff6c30e22652e84e66a1b2acbdfc8d703d62ec7..731f3355af1bc655f6656360c2efe1e37b924554 100644 (file)
@@ -154,14 +154,14 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
       assert((*firstIdx)->getType() == Type::LongTy &&
              "INTERNAL ERROR: Structure index for a pointer type!");
 
-      // If the last instruction had a leading non-zero index,
-      // check if the current one ends with an array index.  If not,
-      // the code is not type-safe and we would create an illegal GEP
+      // If the last instruction had a leading non-zero index, check if the
+      // current one references a sequential (i.e., indexable) type.
+      // If not, the code is not type-safe and we would create an illegal GEP
       // by folding them, so don't fold any more instructions.
       // 
       if (lastInstHasLeadingNonZero)
-        if (firstIdx != lastIdx && (*(lastIdx-1))->getType() != Type::LongTy)
-          break; // cannot fold in any preceding getElementPtr instrs.
+        if (! isa<SequentialType>(gepInst->getType()->getElementType()))
+          break;   // cannot fold in any preceding getElementPtr instrs.
 
       // Check that all offsets are constant for this instruction
       for (OI = firstIdx; allConstantOffsets && OI != lastIdx; ++OI)
@@ -197,6 +197,56 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
 }
 
 
+//---------------------------------------------------------------------------
+// Function: GetGEPInstArgs
+// 
+// Purpose:
+//   Helper function for GetMemInstArgs that handles the final getElementPtr
+//   instruction used by (or same as) the memory operation.
+//   Extracts the indices of the current instruction and tries to fold in
+//   preceding ones if all indices of the current one are constant.
+//---------------------------------------------------------------------------
+
+Value*
+GetGEPInstArgs(InstructionNode* gepNode,
+               vector<Value*>& idxVec,
+               bool& allConstantIndices)
+{
+  allConstantIndices = true;
+  GetElementPtrInst* gepI = cast<GetElementPtrInst>(gepNode->getInstruction());
+
+  // Default pointer is the one from the current instruction.
+  Value* ptrVal = gepI->getPointerOperand();
+  InstrTreeNode* ptrChild = gepNode->leftChild(); 
+
+  // Extract the index vector of the GEP instructin.
+  // If all indices are constant and first index is zero, try to fold
+  // in preceding GEPs with all constant indices.
+  for (User::op_iterator OI=gepI->idx_begin(),  OE=gepI->idx_end();
+       allConstantIndices && OI != OE; ++OI)
+    if (! isa<Constant>(*OI))
+      allConstantIndices = false;     // note: this also terminates loop!
+
+  // If we have only constant indices, fold chains of constant indices
+  // in this and any preceding GetElemPtr instructions.
+  bool foldedGEPs = false;
+  bool leadingNonZeroIdx = gepI && ! IsZero(*gepI->idx_begin());
+  if (allConstantIndices)
+    if (Value* newPtr = FoldGetElemChain(ptrChild, idxVec, leadingNonZeroIdx))
+      {
+        ptrVal = newPtr;
+        foldedGEPs = true;
+      }
+
+  // Append the index vector of the current instruction.
+  // Skip the leading [0] index if preceding GEPs were folded into this.
+  idxVec.insert(idxVec.end(),
+                gepI->idx_begin() + (foldedGEPs && !leadingNonZeroIdx),
+                gepI->idx_end());
+
+  return ptrVal;
+}
+
 //---------------------------------------------------------------------------
 // Function: GetMemInstArgs
 // 
@@ -215,11 +265,11 @@ FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
 //---------------------------------------------------------------------------
 
 Value*
-GetMemInstArgs(const InstructionNode* memInstrNode,
+GetMemInstArgs(InstructionNode* memInstrNode,
                vector<Value*>& idxVec,
                bool& allConstantIndices)
 {
-  allConstantIndices = true;
+  allConstantIndices = false;
   Instruction* memInst = memInstrNode->getInstruction();
   assert(idxVec.size() == 0 && "Need empty vector to return indices");
 
@@ -229,41 +279,29 @@ GetMemInstArgs(const InstructionNode* memInstrNode,
   InstrTreeNode* ptrChild = (memInst->getOpcode() == Instruction::Store
                              ? memInstrNode->rightChild()
                              : memInstrNode->leftChild()); 
-
+  
   // Default pointer is the one from the current instruction.
   Value* ptrVal = ptrChild->getValue(); 
 
-  // GEP is the only indexed memory instruction.  Extract its index vector.
-  // Also, if all indices are constant and first index is zero, try to fold
-  // in preceding GEPs with all constant indices.
-  GetElementPtrInst* gepI = dyn_cast<GetElementPtrInst>(memInst);
-  if (gepI)
-    for (User::op_iterator OI=gepI->idx_begin(),  OE=gepI->idx_end();
-         allConstantIndices && OI != OE; ++OI)
-      if (! isa<Constant>(*OI))
-        allConstantIndices = false;     // note: this also terminates loop!
-
-  // If we have only constant indices, fold chains of constant indices
-  // in this and any preceding GetElemPtr instructions.
-  bool foldedGEPs = false;
-  bool leadingNonZeroIdx = gepI && ! IsZero(*gepI->idx_begin());
-  if (allConstantIndices)
-    if (Value* newPtr = FoldGetElemChain(ptrChild, idxVec, leadingNonZeroIdx))
-      {
-        ptrVal = newPtr;
-        foldedGEPs = true;
-      }
-
-  // Append the index vector of the current instruction, if any.
-  // Skip the leading [0] index if preceding GEPs were folded into this.
-  if (gepI)
-    idxVec.insert(idxVec.end(),
-                  gepI->idx_begin() + (foldedGEPs && !leadingNonZeroIdx),
-                  gepI->idx_end());
+  // Find the "last" GetElemPtr instruction: this one or the immediate child.
+  // There will be none if this is a load or a store from a scalar pointer.
+  InstructionNode* gepNode = NULL;
+  if (isa<GetElementPtrInst>(memInst))
+    gepNode = memInstrNode;
+  else if (isa<InstructionNode>(ptrChild) && isa<GetElementPtrInst>(ptrVal))
+    { // Child of load/store is a GEP and memInst is its only use.
+      // Use its indices and mark it as folded.
+      gepNode = cast<InstructionNode>(ptrChild);
+      gepNode->markFoldedIntoParent();
+    }
 
-  return ptrVal;
+  // If there are no indices, return the current pointer.
+  // Else extract the pointer from the GEP and fold the indices.
+  return (gepNode)? GetGEPInstArgs(gepNode, idxVec, allConstantIndices)
+                  : ptrVal;
 }
 
+
 //------------------------------------------------------------------------ 
 // Function Set2OperandsFromInstr
 // Function Set3OperandsFromInstr