Handle subtract in expression classifier
authorChris Lattner <sabre@nondot.org>
Tue, 11 Sep 2001 04:27:34 +0000 (04:27 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 11 Sep 2001 04:27:34 +0000 (04:27 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@548 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 0471fb21a677ff1a50f95820078093c80bc4a5b2..9ddd5863b59bd7e3cc17dcf4e48f144b7c3446bc 100644 (file)
@@ -11,6 +11,7 @@
 #define LLVM_ANALYSIS_EXPRESSIONS_H
 
 #include <assert.h>
+class Type;
 class Value;
 class ConstPoolInt;
 
@@ -42,15 +43,13 @@ struct ExprType {
     Offset = CPV; Var = 0; Scale = 0;
     ExprTy = Constant;
   }
-  inline ExprType(Value *Val) {
-    Var = Val; Offset = Scale = 0;
-    ExprTy = Var ? Linear : Constant;
-  }
-  inline ExprType(const ConstPoolInt *scale, Value *var, 
-                 const ConstPoolInt *offset) {
-    Scale = scale; Var = var; Offset = offset;
-    ExprTy = Scale ? ScaledLinear : (Var ? Linear : Constant);
-  }
+  ExprType(Value *Val);        // Create a linear or constant expression
+  ExprType(const ConstPoolInt *scale, Value *var, const ConstPoolInt *offset);
+
+  // If this expression has an intrinsic type, return it.  If it is zero, return
+  // the specified type.
+  //
+  const Type *getExprType(const Type *Default) const;
 };
 
 } // End namespace analysis
index e41182a08491431eb80dfcfd66729e3e54ed58bc..2235cdaa37bc1834bac28f9a61a84fa6b4ff1476 100644 (file)
 using namespace opt;  // Get all the constant handling stuff
 using namespace analysis;
 
+ExprType::ExprType(Value *Val) {
+  if (Val && Val->isConstant() && Val->getType()->isIntegral()) {
+    Offset = (ConstPoolInt*)Val->castConstant();
+    Var = 0;
+    ExprTy = Constant;
+  } else {
+    Var = Val; Offset = 0;
+    ExprTy = Var ? Linear : Constant;
+  }
+  Scale = 0;
+}
+
+ExprType::ExprType(const ConstPoolInt *scale, Value *var, 
+                  const ConstPoolInt *offset) {
+  Scale = scale; Var = var; Offset = offset;
+  ExprTy = Scale ? ScaledLinear : (Var ? Linear : Constant);
+  if (Scale && Scale->equalsInt(0)) {  // Simplify 0*Var + const
+    Scale = 0; Var = 0;
+    ExprTy = Constant;
+  }
+}
+
+
+const Type *ExprType::getExprType(const Type *Default) const {
+  if (Offset) return Offset->getType();
+  if (Scale) return Scale->getType();
+  return Var ? Var->getType() : Default;
+}
+
+
+
 class DefVal {
   const ConstPoolInt * const Val;
   const Type * const Ty;
@@ -37,18 +68,8 @@ struct DefOne : public DefVal {
 };
 
 
-// getIntegralConstant - Wrapper around the ConstPoolInt member of the same
-// name.  This method first checks to see if the desired constant is already in
-// the constant pool.  If it is, it is quickly recycled, otherwise a new one
-// is allocated and added to the constant pool.
-//
-static ConstPoolInt *getIntegralConstant(unsigned char V, const Type *Ty) {
-  return ConstPoolInt::get(Ty, V);
-}
-
 static ConstPoolInt *getUnsignedConstant(uint64_t V, const Type *Ty) {
   if (Ty->isPointerType()) Ty = Type::ULongTy;
-
   return Ty->isSigned() ? ConstPoolSInt::get(Ty, V) : ConstPoolUInt::get(Ty, V);
 }
 
@@ -77,11 +98,8 @@ static const ConstPoolInt *Add(const ConstPoolInt *Arg1,
 
   // Check to see if the result is one of the special cases that we want to
   // recognize...
-  if (ResultI->equalsInt(DefOne ? 1 : 0)) {
-    // Yes it is, simply delete the constant and return null.
-    delete ResultI;
-    return 0;
-  }
+  if (ResultI->equalsInt(DefOne ? 1 : 0))
+    return 0;  // Yes it is, simply return null.
 
   return ResultI;
 }
@@ -95,11 +113,11 @@ inline const ConstPoolInt *operator+(const DefZero &L, const DefZero &R) {
 inline const ConstPoolInt *operator+(const DefOne &L, const DefOne &R) {
   if (L == 0) {
     if (R == 0)
-      return getIntegralConstant(2, L.getType());
+      return getUnsignedConstant(2, L.getType());
     else
-      return Add(getIntegralConstant(1, L.getType()), R, true);
+      return Add(getUnsignedConstant(1, L.getType()), R, true);
   } else if (R == 0) {
-    return Add(L, getIntegralConstant(1, L.getType()), true);
+    return Add(L, getUnsignedConstant(1, L.getType()), true);
   }
   return Add(L, R, true);
 }
@@ -130,11 +148,8 @@ inline const ConstPoolInt *Mul(const ConstPoolInt *Arg1,
 
   // Check to see if the result is one of the special cases that we want to
   // recognize...
-  if (ResultI->equalsInt(DefOne ? 1 : 0)) {
-    // Yes it is, simply delete the constant and return null.
-    delete ResultI;
-    return 0;
-  }
+  if (ResultI->equalsInt(DefOne ? 1 : 0))
+    return 0; // Yes it is, simply return null.
 
   return ResultI;
 }
@@ -144,7 +159,7 @@ inline const ConstPoolInt *operator*(const DefZero &L, const DefZero &R) {
   return Mul(L, R, false);
 }
 inline const ConstPoolInt *operator*(const DefOne &L, const DefZero &R) {
-  if (R == 0) return getIntegralConstant(0, L.getType());
+  if (R == 0) return getUnsignedConstant(0, L.getType());
   if (L == 0) return R->equalsInt(1) ? 0 : R.getVal();
   return Mul(L, R, false);
 }
@@ -152,6 +167,45 @@ inline const ConstPoolInt *operator*(const DefZero &L, const DefOne &R) {
   return R*L;
 }
 
+// handleAddition - Add two expressions together, creating a new expression that
+// represents the composite of the two...
+//
+static ExprType handleAddition(ExprType Left, ExprType Right, Value *V) {
+  const Type *Ty = V->getType();
+  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, Ty) + DefZero(Left.Offset, 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(V);             //   if not, we don't know anything!
+
+    return ExprType(DefOne(Left.Scale  , Ty) + DefOne(Right.Scale , Ty),
+                   Left.Var,
+                   DefZero(Left.Offset, Ty) + DefZero(Right.Offset, Ty));
+  default:
+    assert(0 && "Dont' know how to handle this case!");
+    return ExprType();
+  }
+}
+
+// negate - Negate the value of the specified expression...
+//
+static inline ExprType negate(const ExprType &E, Value *V) {
+  const Type *Ty = V->getType();
+  const Type *ETy = E.getExprType(Ty);
+  ConstPoolInt *Zero   = getUnsignedConstant(0, ETy);
+  ConstPoolInt *One    = getUnsignedConstant(1, ETy);
+  ConstPoolInt *NegOne = (ConstPoolInt*)(*Zero - *One);
+  if (NegOne == 0) return V;  // Couldn't subtract values...
+
+  return ExprType(DefOne (E.Scale , Ty) * NegOne, E.Var,
+                 DefZero(E.Offset, Ty) * NegOne);
+}
 
 
 // ClassifyExpression: Analyze an expression to determine the complexity of the
@@ -174,7 +228,7 @@ ExprType analysis::ClassifyExpression(Value *Expr) {
     ConstPoolVal *CPV = Expr->castConstantAsserting();
     if (CPV->getType()->isIntegral()) { // It's an integral constant!
       ConstPoolInt *CPI = (ConstPoolInt*)Expr;
-      return ExprType(CPI->equalsInt(0) ? 0 : (ConstPoolInt*)Expr);
+      return ExprType(CPI->equalsInt(0) ? 0 : CPI);
     }
     return Expr;
   }
@@ -186,24 +240,15 @@ ExprType analysis::ClassifyExpression(Value *Expr) {
   case Instruction::Add: {
     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, Ty) + DefZero(Left.Offset, 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 , Ty) +  DefOne(Right.Scale , Ty),
-                     Left.Var,
-                     DefZero(Left.Offset, Ty) + DefZero(Right.Offset, Ty));
-    }
+    return handleAddition(Left, Right, I);
   }  // end case Instruction::Add
 
+  case Instruction::Sub: {
+    ExprType Left (ClassifyExpression(I->getOperand(0)));
+    ExprType Right(ClassifyExpression(I->getOperand(1)));
+    return handleAddition(Left, negate(Right, I), I);
+  }  // end case Instruction::Sub
+
   case Instruction::Shl: { 
     ExprType Right(ClassifyExpression(I->getOperand(1)));
     if (Right.ExprTy != ExprType::Constant) break;
@@ -240,12 +285,13 @@ ExprType analysis::ClassifyExpression(Value *Expr) {
     const ConstPoolInt *Offs = Src.Offset;
     if (Offs == 0) return ExprType();
 
-    if (I->getType()->isPointerType())
-      return Offs;  // Pointer types do not lose precision
+    const Type *DestTy = I->getType();
+    if (DestTy->isPointerType())
+      DestTy = Type::ULongTy;  // Pointer types are represented as ulong
 
-    assert(I->getType()->isIntegral() && "Can only handle integral types!");
+    assert(DestTy->isIntegral() && "Can only handle integral types!");
 
-    const ConstPoolVal *CPV =ConstRules::get(*Offs)->castTo(Offs, I->getType());
+    const ConstPoolVal *CPV =ConstRules::get(*Offs)->castTo(Offs, DestTy);
     if (!CPV) return I;
     assert(CPV->getType()->isIntegral() && "Must have an integral type!");
     return (ConstPoolInt*)CPV;