about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-rw-r--r--lib/Expr/ExprBuilder.cpp84
-rw-r--r--test/Expr/Parser/ConstantFolding.pc75
2 files changed, 159 insertions, 0 deletions
diff --git a/lib/Expr/ExprBuilder.cpp b/lib/Expr/ExprBuilder.cpp
index d36614d6..0c8ce06e 100644
--- a/lib/Expr/ExprBuilder.cpp
+++ b/lib/Expr/ExprBuilder.cpp
@@ -765,6 +765,90 @@ namespace {
 
       return Base->Add(LHS, RHS);
     }
+
+    ref<Expr> Sub(const ref<ConstantExpr> &LHS,
+                  const ref<NonConstantExpr> &RHS) {
+      switch (RHS->getKind()) {
+      default: break;
+
+      case Expr::Add: {
+        BinaryExpr *BE = cast<BinaryExpr>(RHS);
+        // C_0 - (C_1 + X) ==> (C_0 - C1) - X
+        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
+          return Builder->Sub(LHS->Sub(CE), BE->right);
+        // C_0 - (X + C_1) ==> (C_0 + C1) + X
+        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
+          return Builder->Sub(LHS->Sub(CE), BE->left);
+        break;
+      }
+
+      case Expr::Sub: {
+        BinaryExpr *BE = cast<BinaryExpr>(RHS);
+        // C_0 - (C_1 - X) ==> (C_0 - C1) + X
+        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
+          return Builder->Add(LHS->Sub(CE), BE->right);
+        // C_0 - (X - C_1) ==> (C_0 + C1) - X
+        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
+          return Builder->Sub(LHS->Add(CE), BE->left);
+        break;
+      }
+      }
+
+      return Base->Sub(LHS, RHS);
+    }
+
+    ref<Expr> Sub(const ref<NonConstantExpr> &LHS,
+                  const ref<ConstantExpr> &RHS) {
+        // X - C_0 ==> -C_0 + X
+      return Add(RHS->Neg(), LHS);
+    }
+
+    ref<Expr> Sub(const ref<NonConstantExpr> &LHS,
+                  const ref<NonConstantExpr> &RHS) {
+      switch (LHS->getKind()) {
+      default: break;
+
+      case Expr::Add: {
+        BinaryExpr *BE = cast<BinaryExpr>(LHS);
+        // (X + Y) - Z ==> X + (Y - Z)
+        return Builder->Add(BE->left, Builder->Sub(BE->right, RHS));
+      }
+
+      case Expr::Sub: {
+        BinaryExpr *BE = cast<BinaryExpr>(LHS);
+        // (X - Y) - Z ==> X - (Y + Z)
+        return Builder->Sub(BE->left, Builder->Add(BE->right, RHS));
+      }
+      }
+
+      switch (RHS->getKind()) {
+      default: break;
+
+      case Expr::Add: {
+        BinaryExpr *BE = cast<BinaryExpr>(RHS);
+        // X - (C + Y) ==> -C + (X - Y)
+        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
+          return Builder->Add(CE->Neg(), Builder->Sub(LHS, BE->right));
+        // X - (Y + C) ==> -C + (X + Y);
+        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
+          return Builder->Add(CE->Neg(), Builder->Sub(LHS, BE->left));
+        break;
+      }
+
+      case Expr::Sub: {
+        BinaryExpr *BE = cast<BinaryExpr>(RHS);
+        // X - (C - Y) ==> -C + (X + Y)
+        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->left))
+          return Builder->Add(CE->Neg(), Builder->Add(LHS, BE->right));
+        // X - (Y - C) ==> C + (X - Y)
+        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(BE->right))
+          return Builder->Add(CE, Builder->Sub(LHS, BE->left));
+        break;
+      }
+      }
+
+      return Base->Sub(LHS, RHS);
+    }
   };
 
   typedef ConstantSpecializedExprBuilder<ConstantFoldingBuilder>
diff --git a/test/Expr/Parser/ConstantFolding.pc b/test/Expr/Parser/ConstantFolding.pc
index 9e4a981d..95bc361a 100644
--- a/test/Expr/Parser/ConstantFolding.pc
+++ b/test/Expr/Parser/ConstantFolding.pc
@@ -70,3 +70,78 @@ array a[64] : w32 -> w8 = symbolic
 # RUN: grep                          \"(Add w8 (Read w8 0 a) (Read w8 1 a)\" %t2
 (query [] false [(Add w8 (Read w8 0 a) (Sub w8 (Read w8 1 a) 10))])
 
+# Check -- C_0 - (C_1 + X) ==> (C_0 - C1) - X
+# RUN: grep -A 2 \"# Query 14\" %t > %t2
+# RUN: grep \"(query .. false .(Sub w8 10 (Read w8 0 a))\" %t2
+(query [] false [(Sub w8 20 (Add w8 10 (Read w8 0 a)))])
+
+# Check -- C_0 - (X + C_1) ==> (C_0 + C1) + X
+# RUN: grep -A 2 \"# Query 15\" %t > %t2
+# RUN: grep \"(query .. false .(Sub w8 10 (Read w8 0 a))\" %t2
+(query [] false [(Sub w8 20 (Add w8 (Read w8 0 a) 10))])
+
+# Check -- C_0 - (C_1 - X) ==> (C_0 - C1) + X
+# RUN: grep -A 2 \"# Query 16\" %t > %t2
+# RUN: grep \"(query .. false .(Add w8 10 (Read w8 0 a))\" %t2
+(query [] false [(Sub w8 20 (Sub w8 10 (Read w8 0 a)))])
+
+# Check -- C_0 - (X - C_1) ==> (C_0 + C1) - X
+# RUN: grep -A 2 \"# Query 17\" %t > %t2
+# RUN: grep \"(query .. false .(Sub w8 30 (Read w8 0 a))\" %t2
+(query [] false [(Sub w8 20 (Sub w8 (Read w8 0 a) 10))])
+
+# Check -- (C_0 + X) - C_1 ==> (C_0 - C1) + X
+# RUN: grep -A 2 \"# Query 18\" %t > %t2
+# RUN: grep \"(query .. false .(Add w8 246 (Read w8 0 a))\" %t2
+(query [] false [(Sub w8 (Add w8 10 (Read w8 0 a)) 20)])
+
+# Check -- (X + C_0) - C_1 ==> (C_0 - C1) + X
+# RUN: grep -A 2 \"# Query 19\" %t > %t2
+# RUN: grep \"(query .. false .(Add w8 246 (Read w8 0 a))\" %t2
+(query [] false [(Sub w8 (Add w8 (Read w8 0 a) 10) 20)])
+
+# Check -- (C_0 - X) - C_1 ==> (C_0 - C1) - X
+# RUN: grep -A 2 \"# Query 20\" %t > %t2
+# RUN: grep \"(query .. false .(Sub w8 246 (Read w8 0 a))\" %t2
+(query [] false [(Sub w8 (Sub w8 10 (Read w8 0 a)) 20)])
+
+# Check -- (X - C_0) - C_1 ==> -(C_0 + C1) + X
+# RUN: grep -A 2 \"# Query 21\" %t > %t2
+# RUN: grep \"(query .. false .(Add w8 226 (Read w8 0 a))\" %t2
+(query [] false [(Sub w8 (Sub w8 (Read w8 0 a) 10) 20)])
+
+# Check -- (X + Y) - Z ==> X + (Y - Z)
+# RUN: grep -A 3 \"# Query 22\" %t > %t2
+# RUN: grep \"(query .. false .(Add w8 (Read w8 0 a)\" %t2
+# RUN: grep                          \"(Sub w8 (Read w8 1 a) (Read w8 2 a)\" %t2
+(query [] false [(Sub w8 (Add w8 (Read w8 0 a) (Read w8 1 a)) (Read w8 2 a))])
+
+# Check -- (X - Y) - Z ==> X - (Y + Z)
+# RUN: grep -A 3 \"# Query 23\" %t > %t2
+# RUN: grep \"(query .. false .(Sub w8 (Read w8 0 a)\" %t2
+# RUN: grep                          \"(Add w8 (Read w8 1 a) (Read w8 2 a)\" %t2
+(query [] false [(Sub w8 (Sub w8 (Read w8 0 a) (Read w8 1 a)) (Read w8 2 a))])
+
+# Check -- X - (C + Y) ==> -C + (X - Y)
+# RUN: grep -A 3 \"# Query 24\" %t > %t2
+# RUN: grep \"(query .. false .(Add w8 246\" %t2
+# RUN: grep                          \"(Sub w8 (Read w8 0 a) (Read w8 1 a)\" %t2
+(query [] false [(Sub w8 (Read w8 0 a) (Add w8 10 (Read w8 1 a)))])
+
+# Check -- X - (Y + C) ==> -C + (X - Y)
+# RUN: grep -A 3 \"# Query 25\" %t > %t2
+# RUN: grep \"(query .. false .(Add w8 246\" %t2
+# RUN: grep                          \"(Sub w8 (Read w8 0 a) (Read w8 1 a)\" %t2
+(query [] false [(Sub w8 (Read w8 0 a) (Add w8 (Read w8 1 a) 10))])
+
+# Check -- X - (C - Y) ==> -C + (X + Y)
+# RUN: grep -A 3 \"# Query 26\" %t > %t2
+# RUN: grep \"(query .. false .(Add w8 246\" %t2
+# RUN: grep                          \"(Add w8 (Read w8 0 a) (Read w8 1 a)\" %t2
+(query [] false [(Sub w8 (Read w8 0 a) (Sub w8 10 (Read w8 1 a)))])
+
+# Check -- X - (Y - C) ==> C + (X - Y)
+# RUN: grep -A 3 \"# Query 27\" %t > %t2
+# RUN: grep \"(query .. false .(Add w8 10\" %t2
+# RUN: grep                          \"(Sub w8 (Read w8 0 a) (Read w8 1 a)\" %t2
+(query [] false [(Sub w8 (Read w8 0 a) (Sub w8 (Read w8 1 a) 10))])