[llvm-commits] CVS: llvm/lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp

Vikram Adve vadve at cs.uiuc.edu
Sun Sep 29 17:56:01 PDT 2002


Changes in directory llvm/lib/CodeGen/InstrSelection:

InstrSelectionSupport.cpp updated: 1.33 -> 1.34

---
Log message:

Bug fix in folding getElementPtr instructions: don't fold one into
a predecessor if it has a non-zero first index and the predecessor
ends with a struct index.


---
Diffs of the changes:

Index: llvm/lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp
diff -u llvm/lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp:1.33 llvm/lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp:1.34
--- llvm/lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp:1.33	Fri Sep 27 09:26:20 2002
+++ llvm/lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp	Sun Sep 29 17:55:05 2002
@@ -109,8 +109,17 @@
 //   FoldConstantIndices that does the actual folding. 
 //---------------------------------------------------------------------------
 
+
+// Check for a constant 0.
+inline bool
+IsZero(Value* idx)
+{
+  return (idx == ConstantSInt::getNullValue(idx->getType()));
+}
+
 static Value*
-FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec)
+FoldGetElemChain(InstrTreeNode* ptrNode, vector<Value*>& chainIdxVec,
+                 bool lastInstHasLeadingNonZero)
 {
   InstructionNode* gepNode = dyn_cast<InstructionNode>(ptrNode);
   GetElementPtrInst* gepInst =
@@ -124,11 +133,12 @@
   // Return NULL if we don't fold any instructions in.
   Value* ptrVal = NULL;
 
-  // Remember if the last instruction had a leading [0] index.
-  bool hasLeadingZero = false;
-
   // Now chase the chain of getElementInstr instructions, if any.
   // Check for any non-constant indices and stop there.
+  // Also, stop if the first index of child is a non-zero array index
+  // and the last index of the current node is a non-array index:
+  // in that case, a non-array declared type is being accessed as an array
+  // which is not type-safe, but could be legal.
   // 
   InstructionNode* ptrChild = gepNode;
   while (ptrChild && (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
@@ -140,6 +150,19 @@
       User::op_iterator lastIdx = gepInst->idx_end();
       bool allConstantOffsets = true;
 
+      // The first index of every GEP must be an array index.
+      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
+      // 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.
+
       // Check that all offsets are constant for this instruction
       for (OI = firstIdx; allConstantOffsets && OI != lastIdx; ++OI)
         allConstantOffsets = isa<ConstantInt>(*OI);
@@ -148,26 +171,26 @@
         { // Get pointer value out of ptrChild.
           ptrVal = gepInst->getPointerOperand();
 
-          // Check for a leading [0] index, if any.  It will be discarded later.
-          hasLeadingZero = (*firstIdx ==
-                              Constant::getNullValue((*firstIdx)->getType()));
+          // Remember if it has leading zero index: it will be discarded later.
+          lastInstHasLeadingNonZero = ! IsZero(*firstIdx);
 
           // Insert its index vector at the start, skipping any leading [0]
           chainIdxVec.insert(chainIdxVec.begin(),
-                             firstIdx + hasLeadingZero, lastIdx);
+                             firstIdx + !lastInstHasLeadingNonZero, lastIdx);
 
           // Mark the folded node so no code is generated for it.
           ((InstructionNode*) ptrChild)->markFoldedIntoParent();
+
+          // Get the previous GEP instruction and continue trying to fold
+          ptrChild = dyn_cast<InstructionNode>(ptrChild->leftChild());
         }
-      else // cannot fold this getElementPtr instr. or any further ones
+      else // cannot fold this getElementPtr instr. or any preceding ones
         break;
-
-      ptrChild = dyn_cast<InstructionNode>(ptrChild->leftChild());
     }
 
   // If the first getElementPtr instruction had a leading [0], add it back.
   // Note that this instruction is the *last* one successfully folded above.
-  if (ptrVal && hasLeadingZero) 
+  if (ptrVal && ! lastInstHasLeadingNonZero) 
     chainIdxVec.insert(chainIdxVec.begin(), ConstantSInt::get(Type::LongTy,0));
 
   return ptrVal;
@@ -191,14 +214,6 @@
 //   Returns true/false in allConstantIndices if all indices are/aren't const.
 //---------------------------------------------------------------------------
 
-
-// Check for a constant (uint) 0.
-inline bool
-IsZero(Value* idx)
-{
-  return (isa<ConstantInt>(idx) && cast<ConstantInt>(idx)->isNullValue());
-}
-
 Value*
 GetMemInstArgs(const InstructionNode* memInstrNode,
                vector<Value*>& idxVec,
@@ -206,6 +221,7 @@
 {
   allConstantIndices = true;
   Instruction* memInst = memInstrNode->getInstruction();
+  assert(idxVec.size() == 0 && "Need empty vector to return indices");
 
   // If there is a GetElemPtr instruction to fold in to this instr,
   // it must be in the left child for Load and GetElemPtr, and in the
@@ -217,12 +233,12 @@
   // Default pointer is the one from the current instruction.
   Value* ptrVal = ptrChild->getValue(); 
 
-  // GEP is the only indexed memory instruction.  gepI is used below.
+  // 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 memInst is a GEP, check if all indices are constant for this instruction
   if (gepI)
-    for (User::op_iterator OI=gepI->idx_begin(), OE=gepI->idx_end();
+    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!
@@ -230,18 +246,20 @@
   // 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))
+    if (Value* newPtr = FoldGetElemChain(ptrChild, idxVec, leadingNonZeroIdx))
       {
         ptrVal = newPtr;
         foldedGEPs = true;
-        assert((!gepI || IsZero(*gepI->idx_begin())) && "1st index not 0");
       }
 
   // 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, gepI->idx_end());
+    idxVec.insert(idxVec.end(),
+                  gepI->idx_begin() + (foldedGEPs && !leadingNonZeroIdx),
+                  gepI->idx_end());
 
   return ptrVal;
 }





More information about the llvm-commits mailing list