[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