diff options
| author | Artur Pilipenko <apilipenko@azulsystems.com> | 2016-08-10 13:08:34 +0000 | 
|---|---|---|
| committer | Artur Pilipenko <apilipenko@azulsystems.com> | 2016-08-10 13:08:34 +0000 | 
| commit | e171ea8a33198c3b257c110a5fecc97acdbb5b52 (patch) | |
| tree | d10fcd7614d9ed04a7270751c5feb03e83b16ef9 /llvm/lib/Transforms | |
| parent | dfc1b900aca0fd4aa4b8ccf45f407ea96c5bdaff (diff) | |
| download | bcm5719-llvm-e171ea8a33198c3b257c110a5fecc97acdbb5b52.tar.gz bcm5719-llvm-e171ea8a33198c3b257c110a5fecc97acdbb5b52.zip | |
Teach CorrelatedValuePropagation to mark adds as no wrap
This is a resubmission of previously reverted r277592. It was hitting overly strong assertion in getConstantRange which was relaxed in r278217.
Use LVI to prove that adds do not wrap. The change is motivated by https://llvm.org/bugs/show_bug.cgi?id=28620 bug and it's the first step to fix that problem.
Reviewed By: sanjoy
Differential Revision: http://reviews.llvm.org/D23059
llvm-svn: 278220
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp | 57 | 
1 files changed, 57 insertions, 0 deletions
| diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index c0fed053339..8b0d7e4d19a 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -18,6 +18,7 @@  #include "llvm/Analysis/InstructionSimplify.h"  #include "llvm/Analysis/LazyValueInfo.h"  #include "llvm/IR/CFG.h" +#include "llvm/IR/ConstantRange.h"  #include "llvm/IR/Constants.h"  #include "llvm/IR/Function.h"  #include "llvm/IR/Instructions.h" @@ -381,6 +382,59 @@ static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) {    return true;  } +static bool processAdd(BinaryOperator *AddOp, LazyValueInfo *LVI) { +  typedef OverflowingBinaryOperator OBO; + +  if (AddOp->getType()->isVectorTy() || hasLocalDefs(AddOp)) +    return false; + +  bool NSW = AddOp->hasNoSignedWrap(); +  bool NUW = AddOp->hasNoUnsignedWrap(); +  if (NSW && NUW) +    return false; + +  BasicBlock *BB = AddOp->getParent(); + +  Value *LHS = AddOp->getOperand(0); +  Value *RHS = AddOp->getOperand(1); + +  ConstantRange LRange = LVI->getConstantRange(LHS, BB, AddOp); + +  // Initialize RRange only if we need it. If we know that guaranteed no wrap +  // range for the given LHS range is empty don't spend time calculating the +  // range for the RHS. +  Optional<ConstantRange> RRange; +  auto LazyRRange = [&] () { +      if (!RRange) +        RRange = LVI->getConstantRange(RHS, BB, AddOp); +      return RRange.getValue(); +  }; + +  bool Changed = false; +  if (!NUW) { +    ConstantRange NUWRange = +            LRange.makeGuaranteedNoWrapRegion(BinaryOperator::Add, LRange, +                                              OBO::NoUnsignedWrap); +    if (!NUWRange.isEmptySet()) { +      bool NewNUW = NUWRange.contains(LazyRRange()); +      AddOp->setHasNoUnsignedWrap(NewNUW); +      Changed |= NewNUW; +    } +  } +  if (!NSW) { +    ConstantRange NSWRange = +            LRange.makeGuaranteedNoWrapRegion(BinaryOperator::Add, LRange, +                                              OBO::NoSignedWrap); +    if (!NSWRange.isEmptySet()) { +      bool NewNSW = NSWRange.contains(LazyRRange()); +      AddOp->setHasNoSignedWrap(NewNSW); +      Changed |= NewNSW; +    } +  } + +  return Changed; +} +  static Constant *getConstantAt(Value *V, Instruction *At, LazyValueInfo *LVI) {    if (Constant *C = LVI->getConstant(V, At->getParent(), At))      return C; @@ -436,6 +490,9 @@ static bool runImpl(Function &F, LazyValueInfo *LVI) {        case Instruction::SDiv:          BBChanged |= processSDiv(cast<BinaryOperator>(II), LVI);          break; +      case Instruction::Add: +        BBChanged |= processAdd(cast<BinaryOperator>(II), LVI); +        break;        }      } | 

