diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2014-05-13 01:23:21 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2014-05-13 01:23:21 +0000 |
commit | e2b37447b715b1eaa507de117fcb18beea6a4601 (patch) | |
tree | 766fd323916778752ac2837f3bbbbf606fafd7cf /lib/IR | |
parent | 0449d522a66512af6e7b999d46445c7f7e4b8536 (diff) | |
download | llvm-e2b37447b715b1eaa507de117fcb18beea6a4601.tar.gz llvm-e2b37447b715b1eaa507de117fcb18beea6a4601.tar.bz2 llvm-e2b37447b715b1eaa507de117fcb18beea6a4601.tar.xz |
Assert that we don't RAUW a Constant with a ConstantExpr that contains it.
We already had an assert for foo->RAUW(foo), but not for something like
foo->RAUW(GEP(foo)) and would go in an infinite loop trying to apply
the replacement.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208663 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/IR')
-rw-r--r-- | lib/IR/Value.cpp | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 2ebdb702cf..9a79e43359 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -301,10 +301,45 @@ void Value::takeName(Value *V) { ST->reinsertValue(this); } +#ifndef NDEBUG +static bool contains(SmallPtrSet<ConstantExpr *, 4> &Cache, ConstantExpr *Expr, + Constant *C) { + if (!Cache.insert(Expr)) + return false; + + for (auto &O : Expr->operands()) { + if (O == C) + return true; + auto *CE = dyn_cast<ConstantExpr>(O); + if (!CE) + continue; + if (contains(Cache, CE, C)) + return true; + } + return false; +} + +static bool contains(Value *Expr, Value *V) { + if (Expr == V) + return true; + + auto *C = dyn_cast<Constant>(V); + if (!C) + return false; + + auto *CE = dyn_cast<ConstantExpr>(Expr); + if (!CE) + return false; + + SmallPtrSet<ConstantExpr *, 4> Cache; + return contains(Cache, CE, C); +} +#endif void Value::replaceAllUsesWith(Value *New) { assert(New && "Value::replaceAllUsesWith(<null>) is invalid!"); - assert(New != this && "this->replaceAllUsesWith(this) is NOT valid!"); + assert(!contains(New, this) && + "this->replaceAllUsesWith(expr(this)) is NOT valid!"); assert(New->getType() == getType() && "replaceAllUses of value with new value of different type!"); |