liberty/lib/ExternICallProm/ExternICallProm.cpp
/*
 * promote the instruction with profiled symbols
 * for each instruction, get the callsite, and create N compare and call BBs
 */
promote the instruction with profiled symbols
for each instruction, get the callsite, and create N compare and call BBs
promote the instruction with profiled symbols for each instruction get the callsite and create N compare and call BBs
bool ExternICallPromote::promoteExternalCallsite(Instruction *inst, SymbolList &symbols, Module &M) {
  CallSite cs(inst);
  const unsigned NumDirectCalls = symbols.size();
  const unsigned N_alternatives = RequiresDefaultCase ? (NumDirectCalls +1) : NumDirectCalls;
  LLVM_DEBUG(errs() << "Transforming callsite (" << N_alternatives
      << ") ``" << *inst << "'':\n");
  if( NumDirectCalls == 0 ){
    LLVM_DEBUG(errs() << "-- No candidates found :(\n");
    return false;
  }
  BasicBlock *before = inst->getParent();
  BasicBlock *after = before->splitBasicBlock(inst, "after_indirect_call");
  PHINode *return_value_phi = 0;
  if( ! inst->use_empty() ){
    return_value_phi = PHINode::Create(
        inst->getType(), N_alternatives, "result_of_indirect_call");
    InstInsertPt::Beginning(after) << return_value_phi;
  }
  Value *fcn_ptr = cs.getCalledValue();
  Function *fcn = before->getParent();
  LLVMContext &ctx = fcn->getContext();
  BasicBlock *default_case = 0;
  BlockList alternatives(NumDirectCalls);
  vector<Value *> callees(NumDirectCalls);
  for(unsigned i=0; i<NumDirectCalls; ++i) {
    string &symbol = symbols[i];
    alternatives[i] = BasicBlock::Create(
        ctx, "direct_call_to_" + symbol, fcn, after);
    callees[i] = makeNewCall(cs, &symbol, alternatives[i], after, return_value_phi, M);
    default_case = alternatives[i]; 
  }
  if (RequiresDefaultCase){
    default_case = BasicBlock::Create(ctx, "default_indirect", fcn, after);
    makeNewCall(cs, nullptr, default_case, after, return_value_phi, M);
  }
  BlockList compare_and_branch(NumDirectCalls);
  for(unsigned i=0; i<NumDirectCalls; ++i)
  {
    compare_and_branch[i] = BasicBlock::Create(
        ctx, "compare_to_" + symbols[i], fcn, after);
    compare_and_branch[i]->moveBefore( alternatives[i] );
  }
  before->getTerminator()->setSuccessor(0, compare_and_branch[0]);
  for(unsigned i=0; i<NumDirectCalls; ++i)
  {
    BasicBlock *next = (i == NumDirectCalls-1) ? default_case : compare_and_branch[i+1];
    Constant *callee = dyn_cast<Constant>(callees[i]);
    if (!callee) {
      errs() << "Cast from Function to Constant  not success?\n";
      return false;
    }
    Instruction *cmp = new ICmpInst(ICmpInst::ICMP_EQ, fcn_ptr, callee);
    InstInsertPt::Beginning(compare_and_branch[i])
      << cmp << BranchInst::Create(alternatives[i], next, cmp);
  }
  if( return_value_phi )
    inst->replaceAllUsesWith( return_value_phi );
  if( InvokeInst *invoke = dyn_cast< InvokeInst >(inst) )
  {
    BasicBlock *normal = invoke->getNormalDest(),
               *exceptional = invoke->getUnwindDest();
    exceptional->removePredecessor(after);
    invoke->eraseFromParent();
    InstInsertPt::End(after) << BranchInst::Create(normal);
  }
  else
    inst->eraseFromParent();
  return true;
}
bool ExternICallPromote :: promoteExternalCallsite ( Instruction * inst , SymbolList & symbols , Module & M ) { CallSite cs ( inst ) ; const unsigned NumDirectCalls = symbols . size ( ) ; const unsigned N_alternatives = RequiresDefaultCase ? ( NumDirectCalls + 1 ) : NumDirectCalls ; LLVM_DEBUG ( errs ( ) << " " << N_alternatives << " " << * inst << " \n " ) ; if ( NumDirectCalls == 0 ) { LLVM_DEBUG ( errs ( ) << " \n " ) ; return false ; } BasicBlock * before = inst -> getParent ( ) ; BasicBlock * after = before -> splitBasicBlock ( inst , " " ) ; PHINode * return_value_phi = 0 ; if ( ! inst -> use_empty ( ) ) { return_value_phi = PHINode :: Create ( inst -> getType ( ) , N_alternatives , " " ) ; InstInsertPt :: Beginning ( after ) << return_value_phi ; } Value * fcn_ptr = cs . getCalledValue ( ) ; Function * fcn = before -> getParent ( ) ; LLVMContext & ctx = fcn -> getContext ( ) ; BasicBlock * default_case = 0 ; BlockList alternatives ( NumDirectCalls ) ; vector < Value * > callees ( NumDirectCalls ) ; for ( unsigned i = 0 ; i < NumDirectCalls ; ++ i ) { string & symbol = symbols [ i ] ; alternatives [ i ] = BasicBlock :: Create ( ctx , " " + symbol , fcn , after ) ; callees [ i ] = makeNewCall ( cs , & symbol , alternatives [ i ] , after , return_value_phi , M ) ; default_case = alternatives [ i ] ; } if ( RequiresDefaultCase ) { default_case = BasicBlock :: Create ( ctx , " " , fcn , after ) ; makeNewCall ( cs , nullptr , default_case , after , return_value_phi , M ) ; } BlockList compare_and_branch ( NumDirectCalls ) ; for ( unsigned i = 0 ; i < NumDirectCalls ; ++ i ) { compare_and_branch [ i ] = BasicBlock :: Create ( ctx , " " + symbols [ i ] , fcn , after ) ; compare_and_branch [ i ] -> moveBefore ( alternatives [ i ] ) ; } before -> getTerminator ( ) -> setSuccessor ( 0 , compare_and_branch [ 0 ] ) ; for ( unsigned i = 0 ; i < NumDirectCalls ; ++ i ) { BasicBlock * next = ( i == NumDirectCalls - 1 ) ? default_case : compare_and_branch [ i + 1 ] ; Constant * callee = dyn_cast < Constant > ( callees [ i ] ) ; if ( ! callee ) { errs ( ) << " \n " ; return false ; } Instruction * cmp = new ICmpInst ( ICmpInst :: ICMP_EQ , fcn_ptr , callee ) ; InstInsertPt :: Beginning ( compare_and_branch [ i ] ) << cmp << BranchInst :: Create ( alternatives [ i ] , next , cmp ) ; } if ( return_value_phi ) inst -> replaceAllUsesWith ( return_value_phi ) ; if ( InvokeInst * invoke = dyn_cast < InvokeInst > ( inst ) ) { BasicBlock * normal = invoke -> getNormalDest ( ) , * exceptional = invoke -> getUnwindDest ( ) ; exceptional -> removePredecessor ( after ) ; invoke -> eraseFromParent ( ) ; InstInsertPt :: End ( after ) << BranchInst :: Create ( normal ) ; } else inst -> eraseFromParent ( ) ; return true ; }
promote the instruction with profiled symbols
 for each instruction, get the callsite, and create N compare and call BBs
promote the instruction with profiled symbols for each instruction get the callsite and create N compare and call BBs
// Split the basic block BEFORE the indirect function // call into two basic blocks: 'before' and 'after' // If the function has a return value, we will need to // PHI over each alternative.  This PHI will appear // at the top of 'after' // We will create a separate basic block 'alternatives[i]' for each of // the possible callees 'callees[i]'.  We populate those blocks with // a direct call, and then a branch to 'after' // arbitrary default case // In all cases for external indirect call, we must emit a default case, which // falls-back to an indirect call. // Add instructions to dispatch to the appropriate direct call. // a sequence of compare and branch instructions. // Stitch the compare-and-branch sequences together // Replace all uses with the PHI. // Remove the old call. // if it was an Invoke, then we need to put // a new terminator instruction in 'after'.