From 1e3d28e825f936060833c09883f93990586a992a Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Mon, 15 Jun 2009 00:52:24 +0000 Subject: Support partial folding for Add in new constant folding builder. git-svn-id: https://llvm.org/svn/llvm-project/klee/trunk@73363 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/klee/Expr.h | 4 +- lib/Expr/Expr.cpp | 6 + lib/Expr/ExprBuilder.cpp | 495 +++++++++++++++++++++++++++++++----- lib/Expr/ExprPPrinter.cpp | 2 +- test/Expr/Parser/ConstantFolding.pc | 67 +++++ 5 files changed, 511 insertions(+), 63 deletions(-) diff --git a/include/klee/Expr.h b/include/klee/Expr.h index 79a8ec6f..24a1cb2e 100644 --- a/include/klee/Expr.h +++ b/include/klee/Expr.h @@ -411,7 +411,6 @@ public: ref Shl(const ref &RHS); ref LShr(const ref &RHS); ref AShr(const ref &RHS); - ref Not(); ref Eq(const ref &RHS); ref Ne(const ref &RHS); ref Ult(const ref &RHS); @@ -422,6 +421,9 @@ public: ref Sle(const ref &RHS); ref Sgt(const ref &RHS); ref Sge(const ref &RHS); + + ref Neg(); + ref Not(); }; diff --git a/lib/Expr/Expr.cpp b/lib/Expr/Expr.cpp index 5ef71d8c..b6833f24 100644 --- a/lib/Expr/Expr.cpp +++ b/lib/Expr/Expr.cpp @@ -373,6 +373,12 @@ ref ConstantExpr::Add(const ref &RHS) { getWidth()); } +ref ConstantExpr::Neg() { + return ConstantExpr::create(ints::sub(0, + getConstantValue(), getWidth()), + getWidth()); +} + ref ConstantExpr::Sub(const ref &RHS) { return ConstantExpr::create(ints::sub(getConstantValue(), RHS->getConstantValue(), getWidth()), diff --git a/lib/Expr/ExprBuilder.cpp b/lib/Expr/ExprBuilder.cpp index 0445222d..d36614d6 100644 --- a/lib/Expr/ExprBuilder.cpp +++ b/lib/Expr/ExprBuilder.cpp @@ -147,21 +147,172 @@ namespace { } }; - class ConstantFoldingExprBuilder : public ExprBuilder { + /// ChainedBuilder - Helper class for construct specialized expression + /// builders, which implements (non-virtual) methods which forward to a base + /// expression builder, for all expressions. + class ChainedBuilder { + protected: + /// Builder - The builder that this specialized builder is contained + /// within. Provided for convenience to clients. + ExprBuilder *Builder; + + /// Base - The base builder class for constructing expressions. ExprBuilder *Base; public: - ConstantFoldingExprBuilder(ExprBuilder *_Base) : Base(_Base) {} - ~ConstantFoldingExprBuilder() { - delete Base; + ChainedBuilder(ExprBuilder *_Builder, ExprBuilder *_Base) + : Builder(_Builder), Base(_Base) {} + ~ChainedBuilder() { delete Base; } + + ref Constant(uint64_t Value, Expr::Width W) { + return Base->Constant(Value, W); + } + + ref NotOptimized(const ref &Index) { + return Base->NotOptimized(Index); + } + + ref Read(const UpdateList &Updates, + const ref &Index) { + return Base->Read(Updates, Index); + } + + ref Select(const ref &Cond, + const ref &LHS, const ref &RHS) { + return Base->Select(Cond, LHS, RHS); + } + + ref Concat(const ref &LHS, const ref &RHS) { + return Base->Concat(LHS, RHS); + } + + ref Extract(const ref &LHS, + unsigned Offset, Expr::Width W) { + return Base->Extract(LHS, Offset, W); + } + + ref ZExt(const ref &LHS, Expr::Width W) { + return Base->ZExt(LHS, W); + } + + ref SExt(const ref &LHS, Expr::Width W) { + return Base->SExt(LHS, W); + } + + ref Add(const ref &LHS, const ref &RHS) { + return Base->Add(LHS, RHS); + } + + ref Sub(const ref &LHS, const ref &RHS) { + return Base->Sub(LHS, RHS); + } + + ref Mul(const ref &LHS, const ref &RHS) { + return Base->Mul(LHS, RHS); + } + + ref UDiv(const ref &LHS, const ref &RHS) { + return Base->UDiv(LHS, RHS); + } + + ref SDiv(const ref &LHS, const ref &RHS) { + return Base->SDiv(LHS, RHS); + } + + ref URem(const ref &LHS, const ref &RHS) { + return Base->URem(LHS, RHS); + } + + ref SRem(const ref &LHS, const ref &RHS) { + return Base->SRem(LHS, RHS); + } + + ref And(const ref &LHS, const ref &RHS) { + return Base->And(LHS, RHS); + } + + ref Or(const ref &LHS, const ref &RHS) { + return Base->Or(LHS, RHS); + } + + ref Xor(const ref &LHS, const ref &RHS) { + return Base->Xor(LHS, RHS); + } + + ref Shl(const ref &LHS, const ref &RHS) { + return Base->Shl(LHS, RHS); + } + + ref LShr(const ref &LHS, const ref &RHS) { + return Base->LShr(LHS, RHS); + } + + ref AShr(const ref &LHS, const ref &RHS) { + return Base->AShr(LHS, RHS); + } + + ref Eq(const ref &LHS, const ref &RHS) { + return Base->Eq(LHS, RHS); + } + + ref Ne(const ref &LHS, const ref &RHS) { + return Base->Ne(LHS, RHS); + } + + ref Ult(const ref &LHS, const ref &RHS) { + return Base->Ult(LHS, RHS); + } + + ref Ule(const ref &LHS, const ref &RHS) { + return Base->Ule(LHS, RHS); + } + + ref Ugt(const ref &LHS, const ref &RHS) { + return Base->Ugt(LHS, RHS); + } + + ref Uge(const ref &LHS, const ref &RHS) { + return Base->Uge(LHS, RHS); + } + + ref Slt(const ref &LHS, const ref &RHS) { + return Base->Slt(LHS, RHS); } + ref Sle(const ref &LHS, const ref &RHS) { + return Base->Sle(LHS, RHS); + } + + ref Sgt(const ref &LHS, const ref &RHS) { + return Base->Sgt(LHS, RHS); + } + + ref Sge(const ref &LHS, const ref &RHS) { + return Base->Sge(LHS, RHS); + } + }; + + /// ConstantSpecializedExprBuilder - A base expression builder class which + /// handles dispatching to a helper class, based on whether the arguments are + /// constant or not. + /// + /// The SpecializedBuilder template argument should be a helper class which + /// implements methods for all the expression construction functions. These + /// methods can be specialized to take [Non]ConstantExpr when desired. + template + class ConstantSpecializedExprBuilder : public ExprBuilder { + SpecializedBuilder Builder; + + public: + ConstantSpecializedExprBuilder(ExprBuilder *Base) : Builder(this, Base) {} + ~ConstantSpecializedExprBuilder() {} + virtual ref Constant(uint64_t Value, Expr::Width W) { - return Base->Constant(Value, W); + return Builder.Constant(Value, W); } virtual ref NotOptimized(const ref &Index) { - return Base->NotOptimized(Index); + return Builder.NotOptimized(Index); } virtual ref Read(const UpdateList &Updates, @@ -170,8 +321,11 @@ namespace { const UpdateNode *UN = Updates.head; while (UN && Eq(Index, UN->index)->isFalse()) UN = UN->next; - - return Base->Read(UpdateList(Updates.root, UN), Index); + + if (ConstantExpr *CE = dyn_cast(Index)) + return Builder.Read(UpdateList(Updates.root, UN), CE); + + return Builder.Read(UpdateList(Updates.root, UN), Index); } virtual ref Select(const ref &Cond, @@ -179,15 +333,20 @@ namespace { if (ConstantExpr *CE = dyn_cast(Cond)) return CE->isTrue() ? LHS : RHS; - return Base->Select(Cond, LHS, RHS); + return Builder.Select(cast(Cond), LHS, RHS); } virtual ref Concat(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Concat(RCE); + return Builder.Concat(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Concat(cast(LHS), RCE); + } - return Base->Concat(LHS, RHS); + return Builder.Concat(cast(LHS), + cast(RHS)); } virtual ref Extract(const ref &LHS, @@ -195,214 +354,428 @@ namespace { if (ConstantExpr *CE = dyn_cast(LHS)) return CE->Extract(Offset, W); - return Base->Extract(LHS, Offset, W); + return Builder.Extract(cast(LHS), Offset, W); } virtual ref ZExt(const ref &LHS, Expr::Width W) { if (ConstantExpr *CE = dyn_cast(LHS)) return CE->ZExt(W); - return Base->ZExt(LHS, W); + return Builder.ZExt(cast(LHS), W); } virtual ref SExt(const ref &LHS, Expr::Width W) { if (ConstantExpr *CE = dyn_cast(LHS)) return CE->SExt(W); - return Base->SExt(LHS, W); + return Builder.SExt(cast(LHS), W); } virtual ref Add(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Add(RCE); + return Builder.Add(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Add(cast(LHS), RCE); + } - return Base->Add(LHS, RHS); + return Builder.Add(cast(LHS), + cast(RHS)); } virtual ref Sub(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Sub(RCE); + return Builder.Sub(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Sub(cast(LHS), RCE); + } - return Base->Sub(LHS, RHS); + return Builder.Sub(cast(LHS), + cast(RHS)); } virtual ref Mul(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Mul(RCE); + return Builder.Mul(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Mul(cast(LHS), RCE); + } - return Base->Mul(LHS, RHS); + return Builder.Mul(cast(LHS), + cast(RHS)); } virtual ref UDiv(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->UDiv(RCE); + return Builder.UDiv(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.UDiv(cast(LHS), RCE); + } - return Base->UDiv(LHS, RHS); + return Builder.UDiv(cast(LHS), + cast(RHS)); } virtual ref SDiv(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->SDiv(RCE); + return Builder.SDiv(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.SDiv(cast(LHS), RCE); + } - return Base->SDiv(LHS, RHS); + return Builder.SDiv(cast(LHS), + cast(RHS)); } virtual ref URem(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->URem(RCE); + return Builder.URem(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.URem(cast(LHS), RCE); + } - return Base->URem(LHS, RHS); + return Builder.URem(cast(LHS), + cast(RHS)); } virtual ref SRem(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->SRem(RCE); + return Builder.SRem(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.SRem(cast(LHS), RCE); + } - return Base->SRem(LHS, RHS); + return Builder.SRem(cast(LHS), + cast(RHS)); } virtual ref And(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->And(RCE); + return Builder.And(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.And(cast(LHS), RCE); + } - return Base->And(LHS, RHS); + return Builder.And(cast(LHS), + cast(RHS)); } virtual ref Or(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Or(RCE); + return Builder.Or(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Or(cast(LHS), RCE); + } - return Base->Or(LHS, RHS); + return Builder.Or(cast(LHS), + cast(RHS)); } virtual ref Xor(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Xor(RCE); + return Builder.Xor(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Xor(cast(LHS), RCE); + } - return Base->Xor(LHS, RHS); + return Builder.Xor(cast(LHS), + cast(RHS)); } virtual ref Shl(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Shl(RCE); + return Builder.Shl(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Shl(cast(LHS), RCE); + } - return Base->Shl(LHS, RHS); + return Builder.Shl(cast(LHS), + cast(RHS)); } virtual ref LShr(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->LShr(RCE); + return Builder.LShr(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.LShr(cast(LHS), RCE); + } - return Base->LShr(LHS, RHS); + return Builder.LShr(cast(LHS), + cast(RHS)); } virtual ref AShr(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->AShr(RCE); + return Builder.AShr(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.AShr(cast(LHS), RCE); + } - return Base->AShr(LHS, RHS); + return Builder.AShr(cast(LHS), + cast(RHS)); } virtual ref Eq(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Eq(RCE); + return Builder.Eq(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Eq(cast(LHS), RCE); + } - return Base->Eq(LHS, RHS); + return Builder.Eq(cast(LHS), + cast(RHS)); } virtual ref Ne(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Ne(RCE); + return Builder.Ne(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Ne(cast(LHS), RCE); + } - return Base->Ne(LHS, RHS); + return Builder.Ne(cast(LHS), + cast(RHS)); } virtual ref Ult(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Ult(RCE); + return Builder.Ult(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Ult(cast(LHS), RCE); + } - return Base->Ult(LHS, RHS); + return Builder.Ult(cast(LHS), + cast(RHS)); } virtual ref Ule(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Ule(RCE); + return Builder.Ule(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Ule(cast(LHS), RCE); + } - return Base->Ule(LHS, RHS); + return Builder.Ule(cast(LHS), + cast(RHS)); } virtual ref Ugt(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Ugt(RCE); + return Builder.Ugt(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Ugt(cast(LHS), RCE); + } - return Base->Ugt(LHS, RHS); + return Builder.Ugt(cast(LHS), + cast(RHS)); } virtual ref Uge(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Uge(RCE); + return Builder.Uge(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Uge(cast(LHS), RCE); + } - return Base->Uge(LHS, RHS); + return Builder.Uge(cast(LHS), + cast(RHS)); } virtual ref Slt(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Slt(RCE); + return Builder.Slt(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Slt(cast(LHS), RCE); + } - return Base->Slt(LHS, RHS); + return Builder.Slt(cast(LHS), + cast(RHS)); } virtual ref Sle(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Sle(RCE); + return Builder.Sle(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Sle(cast(LHS), RCE); + } - return Base->Sle(LHS, RHS); + return Builder.Sle(cast(LHS), + cast(RHS)); } virtual ref Sgt(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Sgt(RCE); + return Builder.Sgt(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Sgt(cast(LHS), RCE); + } - return Base->Sgt(LHS, RHS); + return Builder.Sgt(cast(LHS), + cast(RHS)); } virtual ref Sge(const ref &LHS, const ref &RHS) { - if (ConstantExpr *LCE = dyn_cast(LHS)) + if (ConstantExpr *LCE = dyn_cast(LHS)) { if (ConstantExpr *RCE = dyn_cast(RHS)) return LCE->Sge(RCE); + return Builder.Sge(LCE, cast(RHS)); + } else if (ConstantExpr *RCE = dyn_cast(RHS)) { + return Builder.Sge(cast(LHS), RCE); + } - return Base->Sge(LHS, RHS); + return Builder.Sge(cast(LHS), + cast(RHS)); } }; + class ConstantFoldingBuilder : + public ChainedBuilder { + public: + ConstantFoldingBuilder(ExprBuilder *Builder, ExprBuilder *Base) + : ChainedBuilder(Builder, Base) {} + + ref Add(const ref &LHS, + const ref &RHS) { + // 0 + X ==> X + if (LHS->isZero()) + return RHS; + + switch (RHS->getKind()) { + default: break; + + case Expr::Add: { + BinaryExpr *BE = cast(RHS); + // C_0 + (C_1 + X) ==> (C_0 + C1) + X + if (ConstantExpr *CE = dyn_cast(BE->left)) + return Builder->Add(LHS->Add(CE), BE->right); + // C_0 + (X + C_1) ==> (C_0 + C1) + X + if (ConstantExpr *CE = dyn_cast(BE->right)) + return Builder->Add(LHS->Add(CE), BE->left); + break; + } + + case Expr::Sub: { + BinaryExpr *BE = cast(RHS); + // C_0 + (C_1 - X) ==> (C_0 + C1) - X + if (ConstantExpr *CE = dyn_cast(BE->left)) + return Builder->Sub(LHS->Add(CE), BE->right); + // C_0 + (X - C_1) ==> (C_0 - C1) + X + if (ConstantExpr *CE = dyn_cast(BE->right)) + return Builder->Add(LHS->Sub(CE), BE->left); + break; + } + } + + return Base->Add(LHS, RHS); + } + + ref Add(const ref &LHS, + const ref &RHS) { + return Add(RHS, LHS); + } + + ref Add(const ref &LHS, + const ref &RHS) { + switch (LHS->getKind()) { + default: break; + + case Expr::Add: { + BinaryExpr *BE = cast(LHS); + // (X + Y) + Z ==> X + (Y + Z) + return Builder->Add(BE->left, + Builder->Add(BE->right, RHS)); + } + + case Expr::Sub: { + BinaryExpr *BE = cast(LHS); + // (X - Y) + Z ==> X + (Z - Y) + return Builder->Add(BE->left, + Builder->Sub(RHS, BE->right)); + } + } + + switch (RHS->getKind()) { + default: break; + + case Expr::Add: { + BinaryExpr *BE = cast(RHS); + // X + (C_0 + Y) ==> C_0 + (X + Y) + if (ConstantExpr *CE = dyn_cast(BE->left)) + return Builder->Add(CE, Builder->Add(LHS, BE->right)); + // X + (Y + C_0) ==> C_0 + (X + Y) + if (ConstantExpr *CE = dyn_cast(BE->right)) + return Builder->Add(CE, Builder->Add(LHS, BE->left)); + break; + } + + case Expr::Sub: { + BinaryExpr *BE = cast(RHS); + // X + (C_0 - Y) ==> C_0 + (X - Y) + if (ConstantExpr *CE = dyn_cast(BE->left)) + return Builder->Add(CE, Builder->Sub(LHS, BE->right)); + // X + (Y - C_0) ==> -C_0 + (X + Y) + if (ConstantExpr *CE = dyn_cast(BE->right)) + return Builder->Add(CE->Neg(), Builder->Add(LHS, BE->left)); + break; + } + } + + return Base->Add(LHS, RHS); + } + }; + + typedef ConstantSpecializedExprBuilder + ConstantFoldingExprBuilder; + class SimplifyingExprBuilder : public ExprBuilder { ExprBuilder *Base; public: SimplifyingExprBuilder(ExprBuilder *_Base) : Base(_Base) {} - ~SimplifyingExprBuilder() { + ~SimplifyingExprBuilder() { delete Base; } diff --git a/lib/Expr/ExprPPrinter.cpp b/lib/Expr/ExprPPrinter.cpp index d7c77fb0..c78791ef 100644 --- a/lib/Expr/ExprPPrinter.cpp +++ b/lib/Expr/ExprPPrinter.cpp @@ -566,7 +566,7 @@ void ExprPPrinter::printQuery(std::ostream &os, // Print expressions to obtain values for, if any. if (evalExprsBegin != evalExprsEnd) { - PC.breakLine(indent - 1); + p.printSeparator(PC, q->isFalse(), indent-1); PC << '['; for (const ref *it = evalExprsBegin; it != evalExprsEnd; ++it) { p.print(*it, PC); diff --git a/test/Expr/Parser/ConstantFolding.pc b/test/Expr/Parser/ConstantFolding.pc index 6c345b47..9e4a981d 100644 --- a/test/Expr/Parser/ConstantFolding.pc +++ b/test/Expr/Parser/ConstantFolding.pc @@ -1,5 +1,72 @@ # RUN: %kleaver --builder=constant-folding -print-ast %s > %t +array a[64] : w32 -> w8 = symbolic + # RUN: grep -A 2 \"# Query 1\" %t > %t2 # RUN: grep \"(query .. false)\" %t2 (query [] (Not (Ult (w32 0) (w32 1)))) + +# Check -- 0 + X ==> X +# RUN: grep -A 2 \"# Query 2\" %t > %t2 +# RUN: grep \"(query .. false .(Read w8 0 a).)\" %t2 +(query [] false [(Add w8 0 (Read w8 0 a))]) +# RUN: grep -A 2 \"# Query 3\" %t > %t2 +# RUN: grep \"(query .. false .(Read w8 0 a).)\" %t2 +(query [] false [(Add w8 (Read w8 0 a) 0)]) + +# Check -- C_0 + (C_1 + X) ==> (C_0 + C_1) + X +# RUN: grep -A 2 \"# Query 4\" %t > %t2 +# RUN: grep \"(query .. false .(Add w8 30 (Read w8 0 a)).)\" %t2 +(query [] false [(Add w8 10 (Add w8 20 (Read w8 0 a)))]) + +# Check -- C_0 + (X + C_1) ==> (C_0 + C_1) + X +# RUN: grep -A 2 \"# Query 5\" %t > %t2 +# RUN: grep \"(query .. false .(Add w8 30 (Read w8 0 a)).)\" %t2 +(query [] false [(Add w8 10 (Add w8 (Read w8 0 a) 20))]) + +# Check -- C_0 + (C_1 - X) ==> (C_0 + C_1) - X +# RUN: grep -A 2 \"# Query 6\" %t > %t2 +# RUN: grep \"(query .. false .(Sub w8 30 (Read w8 0 a)).)\" %t2 +(query [] false [(Add w8 10 (Sub w8 20 (Read w8 0 a)))]) + +# Check -- C_0 + (X - C_1) ==> (C_0 - C_1) + X +# RUN: grep -A 2 \"# Query 7\" %t > %t2 +# RUN: grep \"(query .. false .(Add w8 246 (Read w8 0 a)).)\" %t2 +(query [] false [(Add w8 10 (Sub w8 (Read w8 0 a) 20))]) + +# Check -- (X + Y) + Z ==> X + (Y + Z) +# RUN: grep -A 3 \"# Query 8\" %t > %t2 +# RUN: grep \"(query .. false .(Add w8 (Read w8 0 a)\" %t2 +# RUN: grep \"(Add w8 (Read w8 1 a) (Read w8 2 a)\" %t2 +(query [] false [(Add w8 (Add w8 (Read w8 0 a) (Read w8 1 a)) (Read w8 2 a))]) + +# Check -- (X - Y) + Z ==> X + (Z - Y) +# RUN: grep -A 3 \"# Query 9\" %t > %t2 +# RUN: grep \"(query .. false .(Add w8 (Read w8 0 a)\" %t2 +# RUN: grep \"(Sub w8 (Read w8 2 a) (Read w8 1 a)\" %t2 +(query [] false [(Add 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 10\" %t > %t2 +# RUN: grep \"(query .. false .(Add w8 10\" %t2 +# RUN: grep \"(Add w8 (Read w8 0 a) (Read w8 1 a)\" %t2 +(query [] false [(Add w8 (Read w8 0 a) (Add w8 10 (Read w8 1 a)))]) + +# Check -- X + (Y + C) ==> C + (X + Y) +# RUN: grep -A 3 \"# Query 11\" %t > %t2 +# RUN: grep \"(query .. false .(Add w8 10\" %t2 +# RUN: grep \"(Add w8 (Read w8 0 a) (Read w8 1 a)\" %t2 +(query [] false [(Add w8 (Read w8 0 a) (Add w8 (Read w8 1 a) 10))]) + +# Check -- X + (C - Y) ==> C + (X - Y) +# RUN: grep -A 3 \"# Query 12\" %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 [(Add w8 (Read w8 0 a) (Sub w8 10 (Read w8 1 a)))]) + +# Check -- X + (Y - C) ==> -C + (X + Y) +# RUN: grep -A 3 \"# Query 13\" %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 [(Add w8 (Read w8 0 a) (Sub w8 (Read w8 1 a) 10))]) + -- cgit 1.4.1