[llvm-commits] CVS: llvm/lib/VMCore/ConstantFolding.cpp

Chris Lattner lattner at cs.uiuc.edu
Mon Jan 12 16:08:05 PST 2004


Changes in directory llvm/lib/VMCore:

ConstantFolding.cpp updated: 1.48 -> 1.49

---
Log message:

Rearrange and comment code better.  No functionality changes


---
Diffs of the changes:  (+177 -160)

Index: llvm/lib/VMCore/ConstantFolding.cpp
diff -u llvm/lib/VMCore/ConstantFolding.cpp:1.48 llvm/lib/VMCore/ConstantFolding.cpp:1.49
--- llvm/lib/VMCore/ConstantFolding.cpp:1.48	Mon Jan 12 15:13:12 2004
+++ llvm/lib/VMCore/ConstantFolding.cpp	Mon Jan 12 16:07:24 2004
@@ -11,6 +11,11 @@
 // (internal) ConstantFolding.h interface, which is used by the
 // ConstantExpr::get* methods to automatically fold constants when possible.
 //
+// The current constant folding implementation is implemented in two pieces: the
+// template-based folder for simple primitive constants like ConstantInt, and
+// the special case hackery that we use to symbolically evaluate expressions
+// that use ConstantExprs.
+//
 //===----------------------------------------------------------------------===//
 
 #include "ConstantFolding.h"
@@ -22,11 +27,6 @@
 #include <cmath>
 using namespace llvm;
 
-static unsigned getSize(const Type *Ty) {
-  unsigned S = Ty->getPrimitiveSize();
-  return S ? S : 8;  // Treat pointers at 8 bytes
-}
-
 namespace {
   struct ConstRules {
     ConstRules() {}
@@ -71,158 +71,6 @@
 }
 
 
-Constant *llvm::ConstantFoldCastInstruction(const Constant *V,
-                                            const Type *DestTy) {
-  if (V->getType() == DestTy) return (Constant*)V;
-
-  if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
-    if (CE->getOpcode() == Instruction::Cast) {
-      Constant *Op = const_cast<Constant*>(CE->getOperand(0));
-      // Try to not produce a cast of a cast, which is almost always redundant.
-      if (!Op->getType()->isFloatingPoint() &&
-          !CE->getType()->isFloatingPoint() &&
-          !DestTy->getType()->isFloatingPoint()) {
-        unsigned S1 = getSize(Op->getType()), S2 = getSize(CE->getType());
-        unsigned S3 = getSize(DestTy);
-        if (Op->getType() == DestTy && S3 >= S2)
-          return Op;
-        if (S1 >= S2 && S2 >= S3)
-          return ConstantExpr::getCast(Op, DestTy);
-        if (S1 <= S2 && S2 >= S3 && S1 <= S3)
-          return ConstantExpr::getCast(Op, DestTy);
-      }
-    } else if (CE->getOpcode() == Instruction::GetElementPtr) {
-      // If all of the indexes in the GEP are null values, there is no pointer
-      // adjustment going on.  We might as well cast the source pointer.
-      bool isAllNull = true;
-      for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i)
-        if (!CE->getOperand(i)->isNullValue()) {
-          isAllNull = false;
-          break;
-        }
-      if (isAllNull)
-        return ConstantExpr::getCast(CE->getOperand(0), DestTy);
-    }
-
-  ConstRules &Rules = ConstRules::get(V, V);
-
-  switch (DestTy->getPrimitiveID()) {
-  case Type::BoolTyID:    return Rules.castToBool(V);
-  case Type::UByteTyID:   return Rules.castToUByte(V);
-  case Type::SByteTyID:   return Rules.castToSByte(V);
-  case Type::UShortTyID:  return Rules.castToUShort(V);
-  case Type::ShortTyID:   return Rules.castToShort(V);
-  case Type::UIntTyID:    return Rules.castToUInt(V);
-  case Type::IntTyID:     return Rules.castToInt(V);
-  case Type::ULongTyID:   return Rules.castToULong(V);
-  case Type::LongTyID:    return Rules.castToLong(V);
-  case Type::FloatTyID:   return Rules.castToFloat(V);
-  case Type::DoubleTyID:  return Rules.castToDouble(V);
-  case Type::PointerTyID:
-    return Rules.castToPointer(V, cast<PointerType>(DestTy));
-  default: return 0;
-  }
-}
-
-Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
-                                              const Constant *V1,
-                                              const Constant *V2) {
-  Constant *C;
-  switch (Opcode) {
-  default:                   return 0;
-  case Instruction::Add:     return ConstRules::get(V1, V2).add(V1, V2);
-  case Instruction::Sub:     return ConstRules::get(V1, V2).sub(V1, V2);
-  case Instruction::Mul:     return ConstRules::get(V1, V2).mul(V1, V2);
-  case Instruction::Div:     return ConstRules::get(V1, V2).div(V1, V2);
-  case Instruction::Rem:     return ConstRules::get(V1, V2).rem(V1, V2);
-  case Instruction::And:     return ConstRules::get(V1, V2).op_and(V1, V2);
-  case Instruction::Or:      return ConstRules::get(V1, V2).op_or (V1, V2);
-  case Instruction::Xor:     return ConstRules::get(V1, V2).op_xor(V1, V2);
-
-  case Instruction::Shl:     return ConstRules::get(V1, V2).shl(V1, V2);
-  case Instruction::Shr:     return ConstRules::get(V1, V2).shr(V1, V2);
-
-  case Instruction::SetEQ:   return ConstRules::get(V1, V2).equalto(V1, V2);
-  case Instruction::SetLT:   return ConstRules::get(V1, V2).lessthan(V1, V2);
-  case Instruction::SetGT:   return ConstRules::get(V1, V2).lessthan(V2, V1);
-  case Instruction::SetNE:   // V1 != V2  ===  !(V1 == V2)
-    C = ConstRules::get(V1, V2).equalto(V1, V2);
-    break;
-  case Instruction::SetLE:   // V1 <= V2  ===  !(V2 < V1)
-    C = ConstRules::get(V1, V2).lessthan(V2, V1);
-    break;
-  case Instruction::SetGE:   // V1 >= V2  ===  !(V1 < V2)
-    C = ConstRules::get(V1, V2).lessthan(V1, V2);
-    break;
-  }
-
-  // If the folder broke out of the switch statement, invert the boolean
-  // constant value, if it exists, and return it.
-  if (!C) return 0;
-  return ConstantExpr::get(Instruction::Xor, ConstantBool::True, C);
-}
-
-Constant *llvm::ConstantFoldGetElementPtr(const Constant *C,
-                                        const std::vector<Constant*> &IdxList) {
-  if (IdxList.size() == 0 ||
-      (IdxList.size() == 1 && IdxList[0]->isNullValue()))
-    return const_cast<Constant*>(C);
-
-  // TODO If C is null and all idx's are null, return null of the right type.
-
-
-  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(const_cast<Constant*>(C))) {
-    // Combine Indices - If the source pointer to this getelementptr instruction
-    // is a getelementptr instruction, combine the indices of the two
-    // getelementptr instructions into a single instruction.
-    //
-    if (CE->getOpcode() == Instruction::GetElementPtr) {
-      const Type *LastTy = 0;
-      for (gep_type_iterator I = gep_type_begin(CE), E = gep_type_end(CE);
-           I != E; ++I)
-        LastTy = *I;
-
-      if ((LastTy && isa<ArrayType>(LastTy)) || IdxList[0]->isNullValue()) {
-        std::vector<Constant*> NewIndices;
-        NewIndices.reserve(IdxList.size() + CE->getNumOperands());
-        for (unsigned i = 1, e = CE->getNumOperands()-1; i != e; ++i)
-          NewIndices.push_back(cast<Constant>(CE->getOperand(i)));
-
-        // Add the last index of the source with the first index of the new GEP.
-        // Make sure to handle the case when they are actually different types.
-        Constant *Combined = CE->getOperand(CE->getNumOperands()-1);
-        if (!IdxList[0]->isNullValue())   // Otherwise it must be an array
-          Combined = 
-            ConstantExpr::get(Instruction::Add,
-                              ConstantExpr::getCast(IdxList[0], Type::LongTy),
-                              ConstantExpr::getCast(Combined, Type::LongTy));
-        
-        NewIndices.push_back(Combined);
-        NewIndices.insert(NewIndices.end(), IdxList.begin()+1, IdxList.end());
-        return ConstantExpr::getGetElementPtr(CE->getOperand(0), NewIndices);
-      }
-    }
-
-    // Implement folding of:
-    //    int* getelementptr ([2 x int]* cast ([3 x int]* %X to [2 x int]*),
-    //                        long 0, long 0)
-    // To: int* getelementptr ([3 x int]* %X, long 0, long 0)
-    //
-    if (CE->getOpcode() == Instruction::Cast && IdxList.size() > 1 &&
-        IdxList[0]->isNullValue())
-      if (const PointerType *SPT = 
-          dyn_cast<PointerType>(CE->getOperand(0)->getType()))
-        if (const ArrayType *SAT = dyn_cast<ArrayType>(SPT->getElementType()))
-          if (const ArrayType *CAT =
-              dyn_cast<ArrayType>(cast<PointerType>(C->getType())->getElementType()))
-            if (CAT->getElementType() == SAT->getElementType())
-              return ConstantExpr::getGetElementPtr(
-                      (Constant*)CE->getOperand(0), IdxList);
-  }
-  return 0;
-}
-
-
 //===----------------------------------------------------------------------===//
 //                             TemplateRules Class
 //===----------------------------------------------------------------------===//
@@ -604,9 +452,9 @@
 //                           DirectFPRules Class
 //===----------------------------------------------------------------------===//
 //
-// DirectFPRules provides implementations of functions that are valid on
-// floating point types, but not all types in general.
-//
+/// DirectFPRules provides implementations of functions that are valid on
+/// floating point types, but not all types in general.
+///
 template <class ConstantClass, class BuiltinType, Type **Ty>
 struct DirectFPRules
   : public DirectRules<ConstantClass, BuiltinType, Ty,
@@ -619,6 +467,9 @@
   }
 };
 
+
+/// ConstRules::get - This method returns the constant rules implementation that
+/// implements the semantics of the two specified constants.
 ConstRules &ConstRules::get(const Constant *V1, const Constant *V2) {
   static EmptyRules       EmptyR;
   static BoolRules        BoolR;
@@ -654,3 +505,169 @@
   case Type::DoubleTyID:  return DoubleR;
   }
 }
+
+
+//===----------------------------------------------------------------------===//
+//                ConstantFold*Instruction Implementations
+//===----------------------------------------------------------------------===//
+//
+// These methods contain the special case hackery required to symbolically
+// evaluate some constant expression cases, and use the ConstantRules class to
+// evaluate normal constants.
+//
+static unsigned getSize(const Type *Ty) {
+  unsigned S = Ty->getPrimitiveSize();
+  return S ? S : 8;  // Treat pointers at 8 bytes
+}
+
+Constant *llvm::ConstantFoldCastInstruction(const Constant *V,
+                                            const Type *DestTy) {
+  if (V->getType() == DestTy) return (Constant*)V;
+
+  if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+    if (CE->getOpcode() == Instruction::Cast) {
+      Constant *Op = const_cast<Constant*>(CE->getOperand(0));
+      // Try to not produce a cast of a cast, which is almost always redundant.
+      if (!Op->getType()->isFloatingPoint() &&
+          !CE->getType()->isFloatingPoint() &&
+          !DestTy->getType()->isFloatingPoint()) {
+        unsigned S1 = getSize(Op->getType()), S2 = getSize(CE->getType());
+        unsigned S3 = getSize(DestTy);
+        if (Op->getType() == DestTy && S3 >= S2)
+          return Op;
+        if (S1 >= S2 && S2 >= S3)
+          return ConstantExpr::getCast(Op, DestTy);
+        if (S1 <= S2 && S2 >= S3 && S1 <= S3)
+          return ConstantExpr::getCast(Op, DestTy);
+      }
+    } else if (CE->getOpcode() == Instruction::GetElementPtr) {
+      // If all of the indexes in the GEP are null values, there is no pointer
+      // adjustment going on.  We might as well cast the source pointer.
+      bool isAllNull = true;
+      for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i)
+        if (!CE->getOperand(i)->isNullValue()) {
+          isAllNull = false;
+          break;
+        }
+      if (isAllNull)
+        return ConstantExpr::getCast(CE->getOperand(0), DestTy);
+    }
+
+  ConstRules &Rules = ConstRules::get(V, V);
+
+  switch (DestTy->getPrimitiveID()) {
+  case Type::BoolTyID:    return Rules.castToBool(V);
+  case Type::UByteTyID:   return Rules.castToUByte(V);
+  case Type::SByteTyID:   return Rules.castToSByte(V);
+  case Type::UShortTyID:  return Rules.castToUShort(V);
+  case Type::ShortTyID:   return Rules.castToShort(V);
+  case Type::UIntTyID:    return Rules.castToUInt(V);
+  case Type::IntTyID:     return Rules.castToInt(V);
+  case Type::ULongTyID:   return Rules.castToULong(V);
+  case Type::LongTyID:    return Rules.castToLong(V);
+  case Type::FloatTyID:   return Rules.castToFloat(V);
+  case Type::DoubleTyID:  return Rules.castToDouble(V);
+  case Type::PointerTyID:
+    return Rules.castToPointer(V, cast<PointerType>(DestTy));
+  default: return 0;
+  }
+}
+
+Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
+                                              const Constant *V1,
+                                              const Constant *V2) {
+  Constant *C;
+  switch (Opcode) {
+  default:                   return 0;
+  case Instruction::Add:     return ConstRules::get(V1, V2).add(V1, V2);
+  case Instruction::Sub:     return ConstRules::get(V1, V2).sub(V1, V2);
+  case Instruction::Mul:     return ConstRules::get(V1, V2).mul(V1, V2);
+  case Instruction::Div:     return ConstRules::get(V1, V2).div(V1, V2);
+  case Instruction::Rem:     return ConstRules::get(V1, V2).rem(V1, V2);
+  case Instruction::And:     return ConstRules::get(V1, V2).op_and(V1, V2);
+  case Instruction::Or:      return ConstRules::get(V1, V2).op_or (V1, V2);
+  case Instruction::Xor:     return ConstRules::get(V1, V2).op_xor(V1, V2);
+
+  case Instruction::Shl:     return ConstRules::get(V1, V2).shl(V1, V2);
+  case Instruction::Shr:     return ConstRules::get(V1, V2).shr(V1, V2);
+
+  case Instruction::SetEQ:   return ConstRules::get(V1, V2).equalto(V1, V2);
+  case Instruction::SetLT:   return ConstRules::get(V1, V2).lessthan(V1, V2);
+  case Instruction::SetGT:   return ConstRules::get(V1, V2).lessthan(V2, V1);
+  case Instruction::SetNE:   // V1 != V2  ===  !(V1 == V2)
+    C = ConstRules::get(V1, V2).equalto(V1, V2);
+    break;
+  case Instruction::SetLE:   // V1 <= V2  ===  !(V2 < V1)
+    C = ConstRules::get(V1, V2).lessthan(V2, V1);
+    break;
+  case Instruction::SetGE:   // V1 >= V2  ===  !(V1 < V2)
+    C = ConstRules::get(V1, V2).lessthan(V1, V2);
+    break;
+  }
+
+  // If the folder broke out of the switch statement, invert the boolean
+  // constant value, if it exists, and return it.
+  if (!C) return 0;
+  return ConstantExpr::get(Instruction::Xor, ConstantBool::True, C);
+}
+
+Constant *llvm::ConstantFoldGetElementPtr(const Constant *C,
+                                        const std::vector<Constant*> &IdxList) {
+  if (IdxList.size() == 0 ||
+      (IdxList.size() == 1 && IdxList[0]->isNullValue()))
+    return const_cast<Constant*>(C);
+
+  // TODO If C is null and all idx's are null, return null of the right type.
+
+
+  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(const_cast<Constant*>(C))) {
+    // Combine Indices - If the source pointer to this getelementptr instruction
+    // is a getelementptr instruction, combine the indices of the two
+    // getelementptr instructions into a single instruction.
+    //
+    if (CE->getOpcode() == Instruction::GetElementPtr) {
+      const Type *LastTy = 0;
+      for (gep_type_iterator I = gep_type_begin(CE), E = gep_type_end(CE);
+           I != E; ++I)
+        LastTy = *I;
+
+      if ((LastTy && isa<ArrayType>(LastTy)) || IdxList[0]->isNullValue()) {
+        std::vector<Constant*> NewIndices;
+        NewIndices.reserve(IdxList.size() + CE->getNumOperands());
+        for (unsigned i = 1, e = CE->getNumOperands()-1; i != e; ++i)
+          NewIndices.push_back(cast<Constant>(CE->getOperand(i)));
+
+        // Add the last index of the source with the first index of the new GEP.
+        // Make sure to handle the case when they are actually different types.
+        Constant *Combined = CE->getOperand(CE->getNumOperands()-1);
+        if (!IdxList[0]->isNullValue())   // Otherwise it must be an array
+          Combined = 
+            ConstantExpr::get(Instruction::Add,
+                              ConstantExpr::getCast(IdxList[0], Type::LongTy),
+                              ConstantExpr::getCast(Combined, Type::LongTy));
+        
+        NewIndices.push_back(Combined);
+        NewIndices.insert(NewIndices.end(), IdxList.begin()+1, IdxList.end());
+        return ConstantExpr::getGetElementPtr(CE->getOperand(0), NewIndices);
+      }
+    }
+
+    // Implement folding of:
+    //    int* getelementptr ([2 x int]* cast ([3 x int]* %X to [2 x int]*),
+    //                        long 0, long 0)
+    // To: int* getelementptr ([3 x int]* %X, long 0, long 0)
+    //
+    if (CE->getOpcode() == Instruction::Cast && IdxList.size() > 1 &&
+        IdxList[0]->isNullValue())
+      if (const PointerType *SPT = 
+          dyn_cast<PointerType>(CE->getOperand(0)->getType()))
+        if (const ArrayType *SAT = dyn_cast<ArrayType>(SPT->getElementType()))
+          if (const ArrayType *CAT =
+              dyn_cast<ArrayType>(cast<PointerType>(C->getType())->getElementType()))
+            if (CAT->getElementType() == SAT->getElementType())
+              return ConstantExpr::getGetElementPtr(
+                      (Constant*)CE->getOperand(0), IdxList);
+  }
+  return 0;
+}
+





More information about the llvm-commits mailing list