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 --- lib/Expr/Expr.cpp | 6 + lib/Expr/ExprBuilder.cpp | 495 ++++++++++++++++++++++++++++++++++++++++------ lib/Expr/ExprPPrinter.cpp | 2 +- 3 files changed, 441 insertions(+), 62 deletions(-) (limited to 'lib') 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); -- cgit 1.4.1