More functionality, renamed API
authorChris Lattner <sabre@nondot.org>
Sat, 21 Jul 2001 19:07:19 +0000 (19:07 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 21 Jul 2001 19:07:19 +0000 (19:07 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/Expressions.h
lib/Analysis/Expressions.cpp

index c21599f18e883589eb7b1cc9944040bc7a55a285..0471fb21a677ff1a50f95820078093c80bc4a5b2 100644 (file)
 #include <assert.h>
 class Value;
 class ConstPoolInt;
-struct ExprAnalysisResult;
+
+namespace analysis {
+
+struct ExprType;
 
 // ClassifyExpression: Analyze an expression to determine the complexity of the
 // expression, and which other values it depends on.  
 //
-ExprAnalysisResult ClassifyExpression(Value *Expr);
+ExprType ClassifyExpression(Value *Expr);
 
-// ExprAnalysisResult - Represent an expression of the form CONST*VAR+CONST
+// ExprType - Represent an expression of the form CONST*VAR+CONST
 // or simpler.  The expression form that yields the least information about the
 // expression is just the Linear form with no offset.
 //
-struct ExprAnalysisResult {
+struct ExprType {
   enum ExpressionType {
     Constant,            // Expr is a simple constant, Offset is value
     Linear,              // Expr is linear expr, Value is Var+Offset
     ScaledLinear,        // Expr is scaled linear exp, Value is Scale*Var+Offset
-  } ExprType;
+  } ExprTy;
 
   const ConstPoolInt *Offset;  // Offset of expr, or null if 0
   Value              *Var;     // Var referenced, if Linear or above (null if 0)
   const ConstPoolInt *Scale;   // Scale of var if ScaledLinear expr (null if 1)
 
-  inline ExprAnalysisResult(const ConstPoolInt *CPV = 0) {
+  inline ExprType(const ConstPoolInt *CPV = 0) {
     Offset = CPV; Var = 0; Scale = 0;
-    ExprType = Constant;
+    ExprTy = Constant;
   }
-  inline ExprAnalysisResult(Value *Val) {
+  inline ExprType(Value *Val) {
     Var = Val; Offset = Scale = 0;
-    ExprType = Var ? Linear : Constant;
+    ExprTy = Var ? Linear : Constant;
   }
-  inline ExprAnalysisResult(const ConstPoolInt *scale, Value *var, 
-                           const ConstPoolInt *offset) {
-    assert(!(Scale && !Var) && "Can't have scaled nonvariable!");
+  inline ExprType(const ConstPoolInt *scale, Value *var, 
+                 const ConstPoolInt *offset) {
     Scale = scale; Var = var; Offset = offset;
-    ExprType = Scale ? ScaledLinear : (Var ? Linear : Constant);
+    ExprTy = Scale ? ScaledLinear : (Var ? Linear : Constant);
   }
-
-
-private:
-  friend ExprAnalysisResult ClassifyExpression(Value *);
-  inline ExprAnalysisResult operator+(const ConstPoolInt *Offset);
-  
 };
 
+} // End namespace analysis
+
 #endif
index ac6bdc1105a91f90f5323a09564c1144707b8666..07fb8c4ff15f2335c01dd05ea4b6f89dc0c21dd6 100644 (file)
 #include "llvm/BasicBlock.h"
 
 using namespace opt;  // Get all the constant handling stuff
+using namespace analysis;
+
+class DefVal {
+  const ConstPoolInt * const Val;
+  ConstantPool &CP;
+  const Type * const Ty;
+protected:
+  inline DefVal(const ConstPoolInt *val, ConstantPool &cp, const Type *ty)
+    : Val(val), CP(cp), Ty(ty) {}
+public:
+  inline const Type *getType() const { return Ty; }
+  inline ConstantPool &getCP() const { return CP; }
+  inline const ConstPoolInt *getVal() const { return Val; }
+  inline operator const ConstPoolInt * () const { return Val; }
+  inline const ConstPoolInt *operator->() const { return Val; }
+};
+
+struct DefZero : public DefVal {
+  inline DefZero(const ConstPoolInt *val, ConstantPool &cp, const Type *ty)
+    : DefVal(val, cp, ty) {}
+  inline DefZero(const ConstPoolInt *val)
+    : DefVal(val, (ConstantPool&)val->getParent()->getConstantPool(),
+            val->getType()) {}
+};
+
+struct DefOne : public DefVal {
+  inline DefOne(const ConstPoolInt *val, ConstantPool &cp, const Type *ty)
+    : DefVal(val, cp, ty) {}
+};
+
 
 // getIntegralConstant - Wrapper around the ConstPoolInt member of the same
 // name.  This method first checks to see if the desired constant is already in
@@ -29,15 +59,16 @@ static ConstPoolInt *getIntegralConstant(ConstantPool &CP, unsigned char V,
   return CPI;
 }
 
-static ConstPoolUInt *getUnsignedConstant(ConstantPool &CP, uint64_t V) {
+static ConstPoolInt *getUnsignedConstant(ConstantPool &CP, uint64_t V,
+                                        const Type *Ty) {
   // FIXME: Lookup prexisting constant in table!
 
-  ConstPoolUInt *CPUI = new ConstPoolUInt(Type::ULongTy, V);
-  CP.insert(CPUI);
-  return CPUI;
+  ConstPoolInt *CPI;
+  CPI = Ty->isSigned() ? new ConstPoolSInt(Ty, V) : new ConstPoolUInt(Ty, V);
+  CP.insert(CPI);
+  return CPI;
 }
 
-
 // Add - Helper function to make later code simpler.  Basically it just adds
 // the two constants together, inserts the result into the constant pool, and
 // returns it.  Of course life is not simple, and this is no exception.  Factors
@@ -50,29 +81,20 @@ static ConstPoolUInt *getUnsignedConstant(ConstantPool &CP, uint64_t V) {
 //   3. If DefOne is true, a null return value indicates a value of 1, if DefOne
 //      is false, a null return value indicates a value of 0.
 //
-inline const ConstPoolInt *Add(ConstantPool &CP, const ConstPoolInt *Arg1, 
-                              const ConstPoolInt *Arg2, bool DefOne = false) {
-  if (DefOne == false) { // Handle degenerate cases first...
-    if (Arg1 == 0) return Arg2; // Also handles case of Arg1 == Arg2 == 0
-    if (Arg2 == 0) return Arg1;
-  } else {               // These aren't degenerate... :(
-    if (Arg1 == 0 && Arg2 == 0) return getIntegralConstant(CP, 2, Type::UIntTy);
-    if (Arg1 == 0) Arg1 = getIntegralConstant(CP, 1, Arg2->getType());
-    if (Arg2 == 0) Arg2 = getIntegralConstant(CP, 1, Arg2->getType());
-  }
-
+static const ConstPoolInt *Add(ConstantPool &CP, const ConstPoolInt *Arg1,
+                              const ConstPoolInt *Arg2, bool DefOne) {
   assert(Arg1 && Arg2 && "No null arguments should exist now!");
-
-  // FIXME: Make types compatible!
+  assert(Arg1->getType() == Arg2->getType() && "Types must be compatible!");
 
   // Actually perform the computation now!
   ConstPoolVal *Result = *Arg1 + *Arg2;
-  assert(Result && Result->getType()->isIntegral() && "Couldn't perform add!");
+  assert(Result && Result->getType() == Arg1->getType() &&
+        "Couldn't perform addition!");
   ConstPoolInt *ResultI = (ConstPoolInt*)Result;
 
   // Check to see if the result is one of the special cases that we want to
   // recognize...
-  if (ResultI->equals(DefOne ? 1 : 0)) {
+  if (ResultI->equalsInt(DefOne ? 1 : 0)) {
     // Yes it is, simply delete the constant and return null.
     delete ResultI;
     return 0;
@@ -82,16 +104,28 @@ inline const ConstPoolInt *Add(ConstantPool &CP, const ConstPoolInt *Arg1,
   return ResultI;
 }
 
+inline const ConstPoolInt *operator+(const DefZero &L, const DefZero &R) {
+  if (L == 0) return R;
+  if (R == 0) return L;
+  return Add(L.getCP(), L, R, false);
+}
 
-ExprAnalysisResult ExprAnalysisResult::operator+(const ConstPoolInt *NewOff) {
-  if (NewOff == 0) return *this;   // No change!
-
-  ConstantPool &CP = (ConstantPool&)NewOff->getParent()->getConstantPool();
-  return ExprAnalysisResult(Scale, Var, Add(CP, Offset, NewOff));
+inline const ConstPoolInt *operator+(const DefOne &L, const DefOne &R) {
+  if (L == 0) {
+    if (R == 0)
+      return getIntegralConstant(L.getCP(), 2, L.getType());
+    else
+      return Add(L.getCP(), getIntegralConstant(L.getCP(), 1, L.getType()),
+                R, true);
+  } else if (R == 0) {
+    return Add(L.getCP(), L,
+              getIntegralConstant(L.getCP(), 1, L.getType()), true);
+  }
+  return Add(L.getCP(), L, R, true);
 }
 
 
-// Mult - Helper function to make later code simpler.  Basically it just
+// Mul - Helper function to make later code simpler.  Basically it just
 // multiplies the two constants together, inserts the result into the constant
 // pool, and returns it.  Of course life is not simple, and this is no
 // exception.  Factors that complicate matters:
@@ -103,26 +137,20 @@ ExprAnalysisResult ExprAnalysisResult::operator+(const ConstPoolInt *NewOff) {
 //   3. If DefOne is true, a null return value indicates a value of 1, if DefOne
 //      is false, a null return value indicates a value of 0.
 //
-inline const ConstPoolInt *Mult(ConstantPool &CP, const ConstPoolInt *Arg1, 
-                               const ConstPoolInt *Arg2, bool DefOne = false) {
-  if (DefOne == false) { // Handle degenerate cases first...
-    if (Arg1 == 0 || Arg2 == 0) return 0;  // 0 * x == 0
-  } else {               // These aren't degenerate... :(
-    if (Arg1 == 0) return Arg2; // Also handles case of Arg1 == Arg2 == 0
-    if (Arg2 == 0) return Arg1;
-  }
+inline const ConstPoolInt *Mul(ConstantPool &CP, const ConstPoolInt *Arg1, 
+                              const ConstPoolInt *Arg2, bool DefOne = false) {
   assert(Arg1 && Arg2 && "No null arguments should exist now!");
-
-  // FIXME: Make types compatible!
+  assert(Arg1->getType() == Arg2->getType() && "Types must be compatible!");
 
   // Actually perform the computation now!
   ConstPoolVal *Result = *Arg1 * *Arg2;
-  assert(Result && Result->getType()->isIntegral() && "Couldn't perform mult!");
+  assert(Result && Result->getType() == Arg1->getType() && 
+        "Couldn't perform mult!");
   ConstPoolInt *ResultI = (ConstPoolInt*)Result;
 
   // Check to see if the result is one of the special cases that we want to
   // recognize...
-  if (ResultI->equals(DefOne ? 1 : 0)) {
+  if (ResultI->equalsInt(DefOne ? 1 : 0)) {
     // Yes it is, simply delete the constant and return null.
     delete ResultI;
     return 0;
@@ -132,6 +160,20 @@ inline const ConstPoolInt *Mult(ConstantPool &CP, const ConstPoolInt *Arg1,
   return ResultI;
 }
 
+inline const ConstPoolInt *operator*(const DefZero &L, const DefZero &R) {
+  if (L == 0 || R == 0) return 0;
+  return Mul(L.getCP(), L, R, false);
+}
+inline const ConstPoolInt *operator*(const DefOne &L, const DefZero &R) {
+  if (R == 0) return getIntegralConstant(L.getCP(), 0, L.getType());
+  if (L == 0) return R->equalsInt(1) ? 0 : R.getVal();
+  return Mul(L.getCP(), L, R, false);
+}
+inline const ConstPoolInt *operator*(const DefZero &L, const DefOne &R) {
+  return R*L;
+}
+
+
 
 // ClassifyExpression: Analyze an expression to determine the complexity of the
 // expression, and which other values it depends on.  
@@ -139,7 +181,7 @@ inline const ConstPoolInt *Mult(ConstantPool &CP, const ConstPoolInt *Arg1,
 // Note that this analysis cannot get into infinite loops because it treats PHI
 // nodes as being an unknown linear expression.
 //
-ExprAnalysisResult ClassifyExpression(Value *Expr) {
+ExprType analysis::ClassifyExpression(Value *Expr) {
   assert(Expr != 0 && "Can't classify a null expression!");
   switch (Expr->getValueType()) {
   case Value::InstructionVal: break;    // Instruction... hmmm... investigate.
@@ -152,56 +194,89 @@ ExprAnalysisResult ClassifyExpression(Value *Expr) {
     ConstPoolVal *CPV = Expr->castConstantAsserting();
     if (CPV->getType()->isIntegral()) { // It's an integral constant!
       ConstPoolInt *CPI = (ConstPoolInt*)Expr;
-      return ExprAnalysisResult(CPI->equals(0) ? 0 : (ConstPoolInt*)Expr);
+      return ExprType(CPI->equalsInt(0) ? 0 : (ConstPoolInt*)Expr);
     }
     return Expr;
   }
   
   Instruction *I = Expr->castInstructionAsserting();
   ConstantPool &CP = I->getParent()->getParent()->getConstantPool();
+  const Type *Ty = I->getType();
 
   switch (I->getOpcode()) {       // Handle each instruction type seperately
   case Instruction::Add: {
-    ExprAnalysisResult LeftTy (ClassifyExpression(I->getOperand(0)));
-    ExprAnalysisResult RightTy(ClassifyExpression(I->getOperand(1)));
-    if (LeftTy.ExprType > RightTy.ExprType)
-      swap(LeftTy, RightTy);   // Make left be simpler than right
-
-    switch (LeftTy.ExprType) {
-    case ExprAnalysisResult::Constant:
-      return RightTy + LeftTy.Offset;
-    case ExprAnalysisResult::Linear:        // RHS side must be linear or scaled
-    case ExprAnalysisResult::ScaledLinear:  // RHS must be scaled
-      if (LeftTy.Var != RightTy.Var)        // Are they the same variables?
-       return ExprAnalysisResult(I);       //   if not, we don't know anything!
-
-      const ConstPoolInt *NewScale  = Add(CP, LeftTy.Scale, RightTy.Scale,true);
-      const ConstPoolInt *NewOffset = Add(CP, LeftTy.Offset, RightTy.Offset);
-      return ExprAnalysisResult(NewScale, LeftTy.Var, NewOffset);
+    ExprType Left (ClassifyExpression(I->getOperand(0)));
+    ExprType Right(ClassifyExpression(I->getOperand(1)));
+    if (Left.ExprTy > Right.ExprTy)
+      swap(Left, Right);   // Make left be simpler than right
+
+    switch (Left.ExprTy) {
+    case ExprType::Constant:
+      return ExprType(Right.Scale, Right.Var,
+                     DefZero(Right.Offset,CP,Ty) + DefZero(Left.Offset, CP,Ty));
+    case ExprType::Linear:        // RHS side must be linear or scaled
+    case ExprType::ScaledLinear:  // RHS must be scaled
+      if (Left.Var != Right.Var)        // Are they the same variables?
+       return ExprType(I);       //   if not, we don't know anything!
+
+      return ExprType(DefOne(Left.Scale  ,CP,Ty) + DefOne(Right.Scale  , CP,Ty),
+                     Left.Var,
+                     DefZero(Left.Offset,CP,Ty) + DefZero(Right.Offset, CP,Ty));
     }
   }  // end case Instruction::Add
 
   case Instruction::Shl: { 
-    ExprAnalysisResult RightTy(ClassifyExpression(I->getOperand(1)));
-    if (RightTy.ExprType != ExprAnalysisResult::Constant)
-      break;  // TODO: Can get some info if it's (<unsigned> X + <offset>)
-
-    ExprAnalysisResult LeftTy (ClassifyExpression(I->getOperand(0)));
-    if (RightTy.Offset == 0) return LeftTy;   // shl x, 0 = x
-    assert(RightTy.Offset->getType() == Type::UByteTy &&
+    ExprType Right(ClassifyExpression(I->getOperand(1)));
+    if (Right.ExprTy != ExprType::Constant) break;
+    ExprType Left(ClassifyExpression(I->getOperand(0)));
+    if (Right.Offset == 0) return Left;   // shl x, 0 = x
+    assert(Right.Offset->getType() == Type::UByteTy &&
           "Shift amount must always be a unsigned byte!");
-    uint64_t ShiftAmount = ((ConstPoolUInt*)RightTy.Offset)->getValue();
-    ConstPoolUInt *Multiplier = getUnsignedConstant(CP, 1ULL << ShiftAmount);
+    uint64_t ShiftAmount = ((ConstPoolUInt*)Right.Offset)->getValue();
+    ConstPoolInt *Multiplier = getUnsignedConstant(CP, 1ULL << ShiftAmount, Ty);
     
-    return ExprAnalysisResult(Mult(CP, LeftTy.Scale, Multiplier, true),
-                             LeftTy.Var,
-                             Mult(CP, LeftTy.Offset, Multiplier));
+    return ExprType(DefOne(Left.Scale, CP, Ty) * Multiplier,
+                   Left.Var,
+                   DefZero(Left.Offset, CP, Ty) * Multiplier);
   }  // end case Instruction::Shl
 
-    // TODO: Handle CAST, SUB, MULT (at least!)
+  case Instruction::Mul: {
+    ExprType Left (ClassifyExpression(I->getOperand(0)));
+    ExprType Right(ClassifyExpression(I->getOperand(1)));
+    if (Left.ExprTy > Right.ExprTy)
+      swap(Left, Right);   // Make left be simpler than right
+
+    if (Left.ExprTy != ExprType::Constant)  // RHS must be > constant
+      return I;         // Quadratic eqn! :(
+
+    const ConstPoolInt *Offs = Left.Offset;
+    if (Offs == 0) return ExprType();
+    return ExprType(DefOne(Right.Scale, CP, Ty) * Offs,
+                   Right.Var,
+                   DefZero(Right.Offset, CP, Ty) * Offs);
+  } // end case Instruction::Mul
+
+  case Instruction::Cast: {
+    ExprType Src(ClassifyExpression(I->getOperand(0)));
+    if (Src.ExprTy != ExprType::Constant)
+      return I;
+    const ConstPoolInt *Offs = Src.Offset;
+    if (Offs == 0) return ExprType();
+
+    if (I->getType()->isPointerType())
+      return Offs;  // Pointer types do not lose precision
+
+    assert(I->getType()->isIntegral() && "Can only handle integral types!");
+
+    const ConstPoolVal *CPV = ConstRules::get(*Offs)->castTo(Offs, I->getType());
+    if (!CPV) return I;
+    assert(CPV->getType()->isIntegral() && "Must have an integral type!");
+    return (ConstPoolInt*)CPV;
+  } // end case Instruction::Cast
+    // TODO: Handle SUB (at least!)
 
   }  // end switch
 
   // Otherwise, I don't know anything about this value!
-  return ExprAnalysisResult(I);
+  return I;
 }