diff options
| author | Eugene Leviant <eleviant@accesssoftek.com> | 2018-07-01 11:02:07 +0000 | 
|---|---|---|
| committer | Eugene Leviant <eleviant@accesssoftek.com> | 2018-07-01 11:02:07 +0000 | 
| commit | 6e4134459bdb1e537731a16123f75c8d2ec66c5a (patch) | |
| tree | 617e94177651ab3ce9678b6c24eb985bd34a05f8 /llvm/lib/Transforms | |
| parent | 49997adc883b47999a1dfdda2da55e38ef24e2ae (diff) | |
| download | bcm5719-llvm-6e4134459bdb1e537731a16123f75c8d2ec66c5a.tar.gz bcm5719-llvm-6e4134459bdb1e537731a16123f75c8d2ec66c5a.zip | |
[Evaluator] Improve evaluation of call instruction
Recommit of r335324 after buildbot failure fix
llvm-svn: 336059
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Utils/Evaluator.cpp | 69 | 
1 files changed, 62 insertions, 7 deletions
| diff --git a/llvm/lib/Transforms/Utils/Evaluator.cpp b/llvm/lib/Transforms/Utils/Evaluator.cpp index 9440ae3ef2a..264bc21d604 100644 --- a/llvm/lib/Transforms/Utils/Evaluator.cpp +++ b/llvm/lib/Transforms/Utils/Evaluator.cpp @@ -217,6 +217,60 @@ Constant *Evaluator::ComputeLoadResult(Constant *P) {    return nullptr;  // don't know how to evaluate.  } +Function * +Evaluator::getCalleeWithFormalArgs(CallSite &CS, +                                   SmallVector<Constant *, 8> &Formals) { +  auto *V = CS.getCalledValue(); +  if (auto *Fn = dyn_cast<Function>(getVal(V))) +    return getFormalParams(CS, Fn, Formals) ? Fn : nullptr; + +  auto *CE = dyn_cast<ConstantExpr>(V); +  if (!CE || CE->getOpcode() != Instruction::BitCast || +      !getFormalParams(CS, cast<Function>(CE->getOperand(0)), Formals)) +    return nullptr; + +  return dyn_cast<Function>( +      ConstantFoldLoadThroughBitcast(CE, CE->getOperand(0)->getType(), DL)); +} + +bool Evaluator::getFormalParams(CallSite &CS, Function *F, +                                SmallVector<Constant *, 8> &Formals) { +  auto *FTy = F->getFunctionType(); +  if (FTy->getNumParams() > CS.getNumArgOperands()) { +    LLVM_DEBUG(dbgs() << "Too few arguments for function.\n"); +    return false; +  } + +  auto ArgI = CS.arg_begin(); +  for (auto ParI = FTy->param_begin(), ParE = FTy->param_end(); ParI != ParE; +       ++ParI) { +    auto *ArgC = ConstantFoldLoadThroughBitcast(getVal(*ArgI), *ParI, DL); +    if (!ArgC) { +      LLVM_DEBUG(dbgs() << "Can not convert function argument.\n"); +      return false; +    } +    Formals.push_back(ArgC); +    ++ArgI; +  } +  return true; +} + +/// If call expression contains bitcast then we may need to cast +/// evaluated return value to a type of the call expression. +Constant *Evaluator::castCallResultIfNeeded(Value *CallExpr, Constant *RV) { +  ConstantExpr *CE = dyn_cast<ConstantExpr>(CallExpr); +  if (!RV || !CE || CE->getOpcode() != Instruction::BitCast) +    return RV; + +  if (auto *FT = +          dyn_cast<FunctionType>(CE->getType()->getPointerElementType())) { +    RV = ConstantFoldLoadThroughBitcast(RV, FT->getReturnType(), DL); +    if (!RV) +      LLVM_DEBUG(dbgs() << "Failed to fold bitcast call expr\n"); +  } +  return RV; +} +  /// Evaluate all instructions in block BB, returning true if successful, false  /// if we can't evaluate it.  NewBB returns the next BB that control flows into,  /// or null upon return. @@ -465,20 +519,19 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst,        }        // Resolve function pointers. -      Function *Callee = dyn_cast<Function>(getVal(CS.getCalledValue())); +      SmallVector<Constant *, 8> Formals; +      Function *Callee = getCalleeWithFormalArgs(CS, Formals);        if (!Callee || Callee->isInterposable()) {          LLVM_DEBUG(dbgs() << "Can not resolve function pointer.\n");          return false;  // Cannot resolve.        } -      SmallVector<Constant*, 8> Formals; -      for (User::op_iterator i = CS.arg_begin(), e = CS.arg_end(); i != e; ++i) -        Formals.push_back(getVal(*i)); -        if (Callee->isDeclaration()) {          // If this is a function we can constant fold, do it.          if (Constant *C = ConstantFoldCall(CS, Callee, Formals, TLI)) { -          InstResult = C; +          InstResult = castCallResultIfNeeded(CS.getCalledValue(), C); +          if (!InstResult) +            return false;            LLVM_DEBUG(dbgs() << "Constant folded function call. Result: "                              << *InstResult << "\n");          } else { @@ -499,7 +552,9 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst,            return false;          }          ValueStack.pop_back(); -        InstResult = RetVal; +        InstResult = castCallResultIfNeeded(CS.getCalledValue(), RetVal); +        if (RetVal && !InstResult) +          return false;          if (InstResult) {            LLVM_DEBUG(dbgs() << "Successfully evaluated function. Result: " | 

