Esempio n. 1
0
// switchConvert - Convert the switch statement into a binary lookup of
// the case values. The function recursively builds this tree.
// LowerBound and UpperBound are used to keep track of the bounds for Val
// that have already been checked by a block emitted by one of the previous
// calls to switchConvert in the call stack.
BasicBlock *
LowerSwitch::switchConvert(CaseItr Begin, CaseItr End, ConstantInt *LowerBound,
                           ConstantInt *UpperBound, Value *Val,
                           BasicBlock *Predecessor, BasicBlock *OrigBlock,
                           BasicBlock *Default,
                           const std::vector<IntRange> &UnreachableRanges) {
  unsigned Size = End - Begin;

  if (Size == 1) {
    // Check if the Case Range is perfectly squeezed in between
    // already checked Upper and Lower bounds. If it is then we can avoid
    // emitting the code that checks if the value actually falls in the range
    // because the bounds already tell us so.
    if (Begin->Low == LowerBound && Begin->High == UpperBound) {
      unsigned NumMergedCases = 0;
      if (LowerBound && UpperBound)
        NumMergedCases =
            UpperBound->getSExtValue() - LowerBound->getSExtValue();
      fixPhis(Begin->BB, OrigBlock, Predecessor, NumMergedCases);
      return Begin->BB;
    }
    return newLeafBlock(*Begin, Val, OrigBlock, Default);
  }

  unsigned Mid = Size / 2;
  std::vector<CaseRange> LHS(Begin, Begin + Mid);
  DEBUG(dbgs() << "LHS: " << LHS << "\n");
  std::vector<CaseRange> RHS(Begin + Mid, End);
  DEBUG(dbgs() << "RHS: " << RHS << "\n");

  CaseRange &Pivot = *(Begin + Mid);
  DEBUG(dbgs() << "Pivot ==> "
               << Pivot.Low->getValue()
               << " -" << Pivot.High->getValue() << "\n");

  // NewLowerBound here should never be the integer minimal value.
  // This is because it is computed from a case range that is never
  // the smallest, so there is always a case range that has at least
  // a smaller value.
  ConstantInt *NewLowerBound = Pivot.Low;

  // Because NewLowerBound is never the smallest representable integer
  // it is safe here to subtract one.
  ConstantInt *NewUpperBound = ConstantInt::get(NewLowerBound->getContext(),
                                                NewLowerBound->getValue() - 1);

  if (!UnreachableRanges.empty()) {
    // Check if the gap between LHS's highest and NewLowerBound is unreachable.
    int64_t GapLow = LHS.back().High->getSExtValue() + 1;
    int64_t GapHigh = NewLowerBound->getSExtValue() - 1;
    IntRange Gap = { GapLow, GapHigh };
    if (GapHigh >= GapLow && IsInRanges(Gap, UnreachableRanges))
      NewUpperBound = LHS.back().High;
  }

  DEBUG(dbgs() << "LHS Bounds ==> ";
        if (LowerBound) {
          dbgs() << LowerBound->getSExtValue();
        } else {
          dbgs() << "NONE";
        }
        dbgs() << " - " << NewUpperBound->getSExtValue() << "\n";
        dbgs() << "RHS Bounds ==> ";
        dbgs() << NewLowerBound->getSExtValue() << " - ";
        if (UpperBound) {
          dbgs() << UpperBound->getSExtValue() << "\n";
        } else {
          dbgs() << "NONE\n";
        });
Esempio n. 2
0
void ClassHierarchyUtils::processTypeInfo(GlobalVariable* TI, Module& M) {
  if (find(classes.begin(), classes.end(), TI) == classes.end()) {
    SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Adding class " << TI->getName() << "\n");
    classes.push_back(TI);

    // First process the correspoding virtual table. We store the indexes of the primary
    // and secondary vtables, indexed by the corresponding subobject offset. This will allow
    // us to quickly jump to a particular sub-vtable.
    if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) {
      GlobalVariable* VT = typeInfoToVTable[TI]; 
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found vtable: " << VT->getName() << "\n");
      ConstantStruct* VTinit = cast<ConstantStruct>(VT->getInitializer());
      for (int i=0; i<VTinit->getNumOperands(); i++) {
        ConstantArray* VTinitElem = cast<ConstantArray>(VTinit->getOperand(i));
        for (int j=0; j<VTinitElem->getNumOperands(); j++) {
          // Each sub-vtable is preceded by a reference to the class's type_info instance.
          // (See https://mentorembedded.github.io/cxx-abi/abi.html).
          if (TI == VTinitElem->getOperand(j)->stripPointerCasts()) {
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found TI at index " << i << "\n");
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Storing mapping " << VT->getName() << " <-> " << TI->getName() << "\n");
            
            // the offset to top is the offset from the vptr pointing to this
            // sub-vtable, back to the top of the object. This will be negative,
            // but the absolute value gives us the offset from the start of the
            // object (i.e. first vptr), to the subobject.
            int offsetToTop = 0;
            if (ConstantExpr* offsetValCast = dyn_cast<ConstantExpr>(VTinitElem->getOperand(j-1)->stripPointerCasts())) {
              ConstantInt* offsetVal = cast<ConstantInt>(offsetValCast->getOperand(0));
              offsetToTop = offsetVal->getSExtValue(); // will be 0 for the primary
            }
            if (offsetToTop > 0) {
              report_fatal_error("ERROR: offsetToTop is positive!");
            }
            else {
              offsetToTop *= -1;
            }
            
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "offsetToTop: " << offsetToTop << "\n")
            vTableToSecondaryVTableMaps[VT][offsetToTop] = pair<int, int>(i, j+1);
          }
        }
      }
    }
    else {
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "No vtable found for " << TI->getName() << "\n");
    }

    // Now process the type_info struct, extract direct base class info (what
    // their subobject offsets are, or if they are virtual then their
    // virtual-base-offset-offset)
    if (TI->hasInitializer()) {
      ConstantStruct* TIinit = cast<ConstantStruct>(TI->getInitializer());

      int TInumOperands = TIinit->getNumOperands();
      if (TInumOperands > 2) { // first two operands are vptr and type name
        // we have >= 1 base class(es).
        if (TInumOperands == 3) {
          // abi::__si_class_type_info: single, public, non-virtual base at
          // offset 0
          SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "abi::__si_class_type_info\n");
          GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(2)->stripPointerCasts());
          classToSubclasses[baseTI].push_back(TI);
          //dbgs() << "  " << *baseTI << "\n";
          classToBaseOffset[TI][baseTI] = 0;
          processTypeInfo(baseTI, M);
        }
        else {
          // abi::__vmi_class_type_info: all other cases
          SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "abi::__vmi_class_type_info\n");
          // (skip over first two additional fields, which are "flags" and "base_count")
          for (int i=4; i<TInumOperands; i+=2) {
            GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(i)->stripPointerCasts());
            classToSubclasses[baseTI].push_back(TI);
            long offset_flags = cast<ConstantInt>(TIinit->getOperand(i+1))->getSExtValue();
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << TI->getName() << " -> " << baseTI->getName() << "\n");
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset_flags = " << offset_flags << "\n");
            ptrdiff_t offset = offset_flags >> offset_shift;
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset = " << offset << "\n");
            // If this a virtual base class, then we obtain the
            // vbase-offset-offset.  This is the offset from the start of the
            // derived class's (primary) vtable to the location containing the
            // vbase-offset, which is the offset from the start of the object
            // to the virtual base's subobject. Note that virtual base
            // subobjects only exist once and are laid out after all other
            // non-virtual objects. We keep track of the vbase-offset-offset,
            // so that we can find the vbase offset when going down the class
            // hierarchy. (The vbase offset may differ every time but the
            // vbase-offset-offset will remain the same relative to the current
            // class's vtable in subclasses).
            if (offset_flags & virtual_mask) { // is this a virtual base class?
              SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "virtual base class: " << baseTI->getName() << "\n");
              int vbaseOffsetOffset = offset/sizeof(long); // this should be negative
              SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "vbase-offset-offset: " << vbaseOffsetOffset << "\n");
              classToVBaseOffsetOffset[TI][baseTI] = vbaseOffsetOffset;
              if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) {
                GlobalVariable* VT = typeInfoToVTable[TI];
                int vbaseOffsetIdx = vTableToSecondaryVTableMaps[VT][0].second+vbaseOffsetOffset;
                SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "vbase-offset-idx: " << vbaseOffsetIdx << "\n");
              }
              else {
                SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "No VTable for " << TI->getName() << "\n");
              }
            }
            else {
              // In the non-virtual base class case, we just record the subobj
              // offset. This is the offset from the start of the derived
              // object to the base class's subobject. We use this information
              // together with the offset-to-top info we obtained from the
              // vtable to find the base class's subvtable. Note that the
              // relative position of the base class subobj within the current
              // derived object will always remain the same, even in
              // subclasses.
              classToBaseOffset[TI][baseTI] = offset;
            }
            //dbgs() << "  " << *baseTI << "\n";
            processTypeInfo(baseTI, M);
          }
        }
      }
    }
Esempio n. 3
0
int InductionDescriptor::getConsecutiveDirection() const {
  ConstantInt *ConstStep = getConstIntStepValue();
  if (ConstStep && (ConstStep->isOne() || ConstStep->isMinusOne()))
    return ConstStep->getSExtValue();
  return 0;
}
Esempio n. 4
0
bool InductionDescriptor::isInductionPHI(PHINode *Phi, const Loop *TheLoop,
                                         ScalarEvolution *SE,
                                         InductionDescriptor &D,
                                         const SCEV *Expr) {
  Type *PhiTy = Phi->getType();
  // We only handle integer and pointer inductions variables.
  if (!PhiTy->isIntegerTy() && !PhiTy->isPointerTy())
    return false;

  // Check that the PHI is consecutive.
  const SCEV *PhiScev = Expr ? Expr : SE->getSCEV(Phi);
  const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(PhiScev);

  if (!AR) {
    DEBUG(dbgs() << "LV: PHI is not a poly recurrence.\n");
    return false;
  }

  if (AR->getLoop() != TheLoop) {
    // FIXME: We should treat this as a uniform. Unfortunately, we
    // don't currently know how to handled uniform PHIs.
    DEBUG(dbgs() << "LV: PHI is a recurrence with respect to an outer loop.\n");
    return false;    
  }

  Value *StartValue =
    Phi->getIncomingValueForBlock(AR->getLoop()->getLoopPreheader());
  const SCEV *Step = AR->getStepRecurrence(*SE);
  // Calculate the pointer stride and check if it is consecutive.
  // The stride may be a constant or a loop invariant integer value.
  const SCEVConstant *ConstStep = dyn_cast<SCEVConstant>(Step);
  if (!ConstStep && !SE->isLoopInvariant(Step, TheLoop))
    return false;

  if (PhiTy->isIntegerTy()) {
    D = InductionDescriptor(StartValue, IK_IntInduction, Step);
    return true;
  }

  assert(PhiTy->isPointerTy() && "The PHI must be a pointer");
  // Pointer induction should be a constant.
  if (!ConstStep)
    return false;

  ConstantInt *CV = ConstStep->getValue();
  Type *PointerElementType = PhiTy->getPointerElementType();
  // The pointer stride cannot be determined if the pointer element type is not
  // sized.
  if (!PointerElementType->isSized())
    return false;

  const DataLayout &DL = Phi->getModule()->getDataLayout();
  int64_t Size = static_cast<int64_t>(DL.getTypeAllocSize(PointerElementType));
  if (!Size)
    return false;

  int64_t CVSize = CV->getSExtValue();
  if (CVSize % Size)
    return false;
  auto *StepValue = SE->getConstant(CV->getType(), CVSize / Size,
                                    true /* signed */);
  D = InductionDescriptor(StartValue, IK_PtrInduction, StepValue);
  return true;
}
Esempio n. 5
0
//
// Method: runOnModule()
//
// Description:
//  Entry point for this LLVM pass.
//  Find all GEPs, and simplify them.
//
// Inputs:
//  M - A reference to the LLVM module to transform
//
// Outputs:
//  M - The transformed LLVM module.
//
// Return value:
//  true  - The module was modified.
//  false - The module was not modified.
//
bool SimplifyGEP::runOnModule(Module& M) {
  TD = &M.getDataLayout();
  preprocess(M);
  for (Module::iterator F = M.begin(); F != M.end(); ++F){
    for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) {      
      for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE; I++) {
        if(!(isa<GetElementPtrInst>(I)))
          continue;
        GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
        Value *PtrOp = GEP->getOperand(0);
        Value *StrippedPtr = PtrOp->stripPointerCasts();
        // Check if the GEP base pointer is enclosed in a cast
        if (StrippedPtr != PtrOp) {
          const PointerType *StrippedPtrTy =cast<PointerType>(StrippedPtr->getType());
          bool HasZeroPointerIndex = false;
          if (ConstantInt *C = dyn_cast<ConstantInt>(GEP->getOperand(1)))
            HasZeroPointerIndex = C->isZero();
          // Transform: GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ...
          // into     : GEP [10 x i8]* X, i32 0, ...
          //
          // Likewise, transform: GEP (bitcast i8* X to [0 x i8]*), i32 0, ...
          //           into     : GEP i8* X, ...
          // 
          // This occurs when the program declares an array extern like "int X[];"
          if (HasZeroPointerIndex) {
            const PointerType *CPTy = cast<PointerType>(PtrOp->getType());
            if (const ArrayType *CATy =
                dyn_cast<ArrayType>(CPTy->getElementType())) {
              // GEP (bitcast i8* X to [0 x i8]*), i32 0, ... ?
              if (CATy->getElementType() == StrippedPtrTy->getElementType()) {
                // -> GEP i8* X, ...
                SmallVector<Value*, 8> Idx(GEP->idx_begin()+1, GEP->idx_end());
                GetElementPtrInst *Res =
                  GetElementPtrInst::Create(nullptr, StrippedPtr, Idx, GEP->getName(), GEP);
                Res->setIsInBounds(GEP->isInBounds());
                GEP->replaceAllUsesWith(Res);
                continue;
              }

              if (const ArrayType *XATy =
                  dyn_cast<ArrayType>(StrippedPtrTy->getElementType())){
                // GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ... ?
                if (CATy->getElementType() == XATy->getElementType()) {
                  // -> GEP [10 x i8]* X, i32 0, ...
                  // At this point, we know that the cast source type is a pointer
                  // to an array of the same type as the destination pointer
                  // array.  Because the array type is never stepped over (there
                  // is a leading zero) we can fold the cast into this GEP.
                  GEP->setOperand(0, StrippedPtr);
                  continue;
                }
              }
            }   
          } else if (GEP->getNumOperands() == 2) {
            // Transform things like:
            // %t = getelementptr i32* bitcast ([2 x i32]* %str to i32*), i32 %V
            // into:  %t1 = getelementptr [2 x i32]* %str, i32 0, i32 %V; bitcast
            Type *SrcElTy = StrippedPtrTy->getElementType();
            Type *ResElTy=cast<PointerType>(PtrOp->getType())->getElementType();
            if (TD && SrcElTy->isArrayTy() &&
                TD->getTypeAllocSize(cast<ArrayType>(SrcElTy)->getElementType()) ==
                TD->getTypeAllocSize(ResElTy)) {
              Value *Idx[2];
              Idx[0] = Constant::getNullValue(Type::getInt32Ty(GEP->getContext()));
              Idx[1] = GEP->getOperand(1);
              Value *NewGEP = GetElementPtrInst::Create(nullptr, StrippedPtr, Idx,
                                                        GEP->getName(), GEP);
              // V and GEP are both pointer types --> BitCast
              GEP->replaceAllUsesWith(new BitCastInst(NewGEP, GEP->getType(), GEP->getName(), GEP));
              continue;
            }

            // Transform things like:
            // getelementptr i8* bitcast ([100 x double]* X to i8*), i32 %tmp
            //   (where tmp = 8*tmp2) into:
            // getelementptr [100 x double]* %arr, i32 0, i32 %tmp2; bitcast

            if (TD && SrcElTy->isArrayTy() && ResElTy->isIntegerTy(8)) {
              uint64_t ArrayEltSize =
                TD->getTypeAllocSize(cast<ArrayType>(SrcElTy)->getElementType());

              // Check to see if "tmp" is a scale by a multiple of ArrayEltSize.  We
              // allow either a mul, shift, or constant here.
              Value *NewIdx = 0;
              ConstantInt *Scale = 0;
              if (ArrayEltSize == 1) {
                NewIdx = GEP->getOperand(1);
                Scale = ConstantInt::get(cast<IntegerType>(NewIdx->getType()), 1);
              } else if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(1))) {
                NewIdx = ConstantInt::get(CI->getType(), 1);
                Scale = CI;
              } else if (Instruction *Inst =dyn_cast<Instruction>(GEP->getOperand(1))){
                if (Inst->getOpcode() == Instruction::Shl &&
                    isa<ConstantInt>(Inst->getOperand(1))) {
                  ConstantInt *ShAmt = cast<ConstantInt>(Inst->getOperand(1));
                  uint32_t ShAmtVal = ShAmt->getLimitedValue(64);
                  Scale = ConstantInt::get(cast<IntegerType>(Inst->getType()),
                                           1ULL << ShAmtVal);
                  NewIdx = Inst->getOperand(0);
                } else if (Inst->getOpcode() == Instruction::Mul &&
                           isa<ConstantInt>(Inst->getOperand(1))) {
                  Scale = cast<ConstantInt>(Inst->getOperand(1));
                  NewIdx = Inst->getOperand(0);
                }
              }

              // If the index will be to exactly the right offset with the scale taken
              // out, perform the transformation. Note, we don't know whether Scale is
              // signed or not. We'll use unsigned version of division/modulo
              // operation after making sure Scale doesn't have the sign bit set.
              if (ArrayEltSize && Scale && Scale->getSExtValue() >= 0LL &&
                  Scale->getZExtValue() % ArrayEltSize == 0) {
                Scale = ConstantInt::get(Scale->getType(),
                                         Scale->getZExtValue() / ArrayEltSize);
                if (Scale->getZExtValue() != 1) {
                  Constant *C = ConstantExpr::getIntegerCast(Scale, NewIdx->getType(),
                                                             false /*ZExt*/);
                  NewIdx = BinaryOperator::Create(BinaryOperator::Mul, NewIdx, C, "idxscale");
                }

                // Insert the new GEP instruction.
                Value *Idx[2];
                Idx[0] = Constant::getNullValue(Type::getInt32Ty(GEP->getContext()));
                Idx[1] = NewIdx;
                Value *NewGEP = GetElementPtrInst::Create(nullptr, StrippedPtr, Idx,
                                                          GEP->getName(), GEP);
                GEP->replaceAllUsesWith(new BitCastInst(NewGEP, GEP->getType(), GEP->getName(), GEP));
                continue;
              }
            }
          }
        }
      }
    }
  }

  return true;
}
Esempio n. 6
0
bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {

  const User *U = nullptr;
  unsigned Opcode = Instruction::UserOp1;
  if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
    // Don't walk into other basic blocks unless the object is an alloca from
    // another block, otherwise it may not have a virtual register assigned.
    if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
        FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
      Opcode = I->getOpcode();
      U = I;
    }
  } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
    Opcode = C->getOpcode();
    U = C;
  }

  if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
    if (Ty->getAddressSpace() > 255)
      // Fast instruction selection doesn't support the special
      // address spaces.
      return false;

  if (const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) {
    if (Addr.getGlobalValue())
      return false;
    Addr.setGlobalValue(GV);
    return true;
  }

  switch (Opcode) {
  default:
    break;
  case Instruction::BitCast: {
    // Look through bitcasts.
    return computeAddress(U->getOperand(0), Addr);
  }
  case Instruction::IntToPtr: {
    // Look past no-op inttoptrs.
    if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
        TLI.getPointerTy(DL))
      return computeAddress(U->getOperand(0), Addr);
    break;
  }
  case Instruction::PtrToInt: {
    // Look past no-op ptrtoints.
    if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
      return computeAddress(U->getOperand(0), Addr);
    break;
  }
  case Instruction::GetElementPtr: {
    Address SavedAddr = Addr;
    uint64_t TmpOffset = Addr.getOffset();
    // Iterate through the GEP folding the constants into offsets where
    // we can.
    for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
         GTI != E; ++GTI) {
      const Value *Op = GTI.getOperand();
      if (StructType *STy = dyn_cast<StructType>(*GTI)) {
        const StructLayout *SL = DL.getStructLayout(STy);
        unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
        TmpOffset += SL->getElementOffset(Idx);
      } else {
        uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
        for (;;) {
          if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
            // Constant-offset addressing.
            TmpOffset += CI->getSExtValue() * S;
            break;
          }
          if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
            // An unscaled add of a register. Set it as the new base.
            Addr.setReg(getRegForValue(Op));
            break;
          }
          if (canFoldAddIntoGEP(U, Op)) {
            // A compatible add with a constant operand. Fold the constant.
            ConstantInt *CI =
                cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
            TmpOffset += CI->getSExtValue() * S;
            // Iterate on the other operand.
            Op = cast<AddOperator>(Op)->getOperand(0);
            continue;
          }
          // Unsupported
          goto unsupported_gep;
        }
      }
    }
    // Try to grab the base operand now.
    Addr.setOffset(TmpOffset);
    if (computeAddress(U->getOperand(0), Addr))
      return true;
    // We failed, restore everything and try the other options.
    Addr = SavedAddr;
  unsupported_gep:
    break;
  }
  case Instruction::Alloca: {
    const AllocaInst *AI = cast<AllocaInst>(Obj);
    DenseMap<const AllocaInst *, int>::iterator SI =
        FuncInfo.StaticAllocaMap.find(AI);
    if (SI != FuncInfo.StaticAllocaMap.end()) {
      Addr.setKind(Address::FrameIndexBase);
      Addr.setFI(SI->second);
      return true;
    }
    break;
  }
  case Instruction::Add: {
    // Adds of constants are common and easy enough.
    const Value *LHS = U->getOperand(0);
    const Value *RHS = U->getOperand(1);

    if (isa<ConstantInt>(LHS))
      std::swap(LHS, RHS);

    if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
      Addr.setOffset(Addr.getOffset() + CI->getSExtValue());
      return computeAddress(LHS, Addr);
    }

    Address Backup = Addr;
    if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
      return true;
    Addr = Backup;

    break;
  }
  case Instruction::Sub: {
    // Subs of constants are common and easy enough.
    const Value *LHS = U->getOperand(0);
    const Value *RHS = U->getOperand(1);

    if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
      Addr.setOffset(Addr.getOffset() - CI->getSExtValue());
      return computeAddress(LHS, Addr);
    }
    break;
  }
  }
  Addr.setReg(getRegForValue(Obj));
  return Addr.getReg() != 0;
}
Esempio n. 7
0
Value* LoopTripCount::insertTripCount(Loop* L, Instruction* InsertPos)
{
	// inspired from Loop::getCanonicalInductionVariable
	BasicBlock *H = L->getHeader();
	BasicBlock* LoopPred = L->getLoopPredecessor();
	BasicBlock* startBB = NULL;//which basicblock stores start value
	int OneStep = 0;// the extra add or plus step for calc

   Assert(LoopPred, "Require Loop has a Pred");
	DEBUG(errs()<<"loop  depth:"<<L->getLoopDepth()<<"\n");
	/** whats difference on use of predecessor and preheader??*/
	//RET_ON_FAIL(self->getLoopLatch()&&self->getLoopPreheader());
	//assert(self->getLoopLatch() && self->getLoopPreheader() && "need loop simplify form" );
	ret_null_fail(L->getLoopLatch(), "need loop simplify form");

	BasicBlock* TE = NULL;//True Exit
	SmallVector<BasicBlock*,4> Exits;
	L->getExitingBlocks(Exits);

	if(Exits.size()==1) TE = Exits.front();
	else{
		if(std::find(Exits.begin(),Exits.end(),L->getLoopLatch())!=Exits.end()) TE = L->getLoopLatch();
		else{
			SmallVector<llvm::Loop::Edge,4> ExitEdges;
			L->getExitEdges(ExitEdges);
			//stl 用法,先把所有满足条件的元素(出口的结束符是不可到达)移动到数组的末尾,再统一删除
			ExitEdges.erase(std::remove_if(ExitEdges.begin(), ExitEdges.end(), 
						[](llvm::Loop::Edge& I){
						return isa<UnreachableInst>(I.second->getTerminator());
						}), ExitEdges.end());
			if(ExitEdges.size()==1) TE = const_cast<BasicBlock*>(ExitEdges.front().first);
		}
	}

	//process true exit
	ret_null_fail(TE, "need have a true exit");

	Instruction* IndOrNext = NULL;
	Value* END = NULL;
   //终止块的终止指令:分情况讨论branchinst,switchinst;
   //跳转指令br bool a1,a2;condition<-->bool
	if(isa<BranchInst>(TE->getTerminator())){
		const BranchInst* EBR = cast<BranchInst>(TE->getTerminator());
		Assert(EBR->isConditional(), "end branch is not conditional");
		ICmpInst* EC = dyn_cast<ICmpInst>(EBR->getCondition());
		if(EC->getPredicate() == EC->ICMP_SGT){
         Assert(!L->contains(EBR->getSuccessor(0)), *EBR<<":abnormal exit with great than");//终止块的终止指令---->跳出执行循环外的指令
         OneStep += 1;
      } else if(EC->getPredicate() == EC->ICMP_EQ)
         Assert(!L->contains(EBR->getSuccessor(0)), *EBR<<":abnormal exit with great than");
      else if(EC->getPredicate() == EC->ICMP_SLT) {
         ret_null_fail(!L->contains(EBR->getSuccessor(1)), *EBR<<":abnormal exit with less than");
      } else {
         ret_null_fail(0, *EC<<" unknow combination of end condition");
      }
		IndOrNext = dyn_cast<Instruction>(castoff(EC->getOperand(0)));//去掉类型转化
		END = EC->getOperand(1);
		DEBUG(errs()<<"end   value:"<<*EC<<"\n");
	}else if(isa<SwitchInst>(TE->getTerminator())){
		SwitchInst* ESW = const_cast<SwitchInst*>(cast<SwitchInst>(TE->getTerminator()));
		IndOrNext = dyn_cast<Instruction>(castoff(ESW->getCondition()));
		for(auto I = ESW->case_begin(),E = ESW->case_end();I!=E;++I){
			if(!L->contains(I.getCaseSuccessor())){
				ret_null_fail(!END,"");
				assert(!END && "shouldn't have two ends");
				END = I.getCaseValue();
			}
		}
		DEBUG(errs()<<"end   value:"<<*ESW<<"\n");
	}else{
		assert(0 && "unknow terminator type");
	}

	ret_null_fail(L->isLoopInvariant(END), "end value should be loop invariant");//至此得END值

	Value* start = NULL;
	Value* ind = NULL;
	Instruction* next = NULL;
	bool addfirst = false;//add before icmp ed

	DISABLE(errs()<<*IndOrNext<<"\n");
	if(isa<LoadInst>(IndOrNext)){
		//memory depend analysis
		Value* PSi = IndOrNext->getOperand(0);//point type Step.i

		int SICount[2] = {0};//store in predecessor count,store in loop body count
		for( auto I = PSi->use_begin(),E = PSi->use_end();I!=E;++I){
			DISABLE(errs()<<**I<<"\n");
			StoreInst* SI = dyn_cast<StoreInst>(*I);
			if(!SI || SI->getOperand(1) != PSi) continue;
			if(!start&&L->isLoopInvariant(SI->getOperand(0))) {
				if(SI->getParent() != LoopPred)
					if(std::find(pred_begin(LoopPred),pred_end(LoopPred),SI->getParent()) == pred_end(LoopPred)) continue;
				start = SI->getOperand(0);
				startBB = SI->getParent();
				++SICount[0];
			}
			Instruction* SI0 = dyn_cast<Instruction>(SI->getOperand(0));
			if(L->contains(SI) && SI0 && SI0->getOpcode() == Instruction::Add){
				next = SI0;
				++SICount[1];
			}

		}
		Assert(SICount[0]==1 && SICount[1]==1, "");
		ind = IndOrNext;
	}else{
		if(isa<PHINode>(IndOrNext)){
			PHINode* PHI = cast<PHINode>(IndOrNext);
			ind = IndOrNext;
			if(castoff(PHI->getIncomingValue(0)) == castoff(PHI->getIncomingValue(1)) && PHI->getParent() != H)
				ind = castoff(PHI->getIncomingValue(0));
			addfirst = false;
		}else if(IndOrNext->getOpcode() == Instruction::Add){
			next = IndOrNext;
			addfirst = true;
		}else{
			Assert(0 ,"unknow how to analysis");
		}

		for(auto I = H->begin();isa<PHINode>(I);++I){
			PHINode* P = cast<PHINode>(I);
			if(ind && P == ind){
				//start = P->getIncomingValueForBlock(L->getLoopPredecessor());
				start = tryFindStart(P, L, startBB);
				next = dyn_cast<Instruction>(P->getIncomingValueForBlock(L->getLoopLatch()));
			}else if(next && P->getIncomingValueForBlock(L->getLoopLatch()) == next){
				//start = P->getIncomingValueForBlock(L->getLoopPredecessor());
				start = tryFindStart(P, L, startBB);
				ind = P;
			}
		}
	}


	Assert(start ,"couldn't find a start value");
	//process complex loops later
	//DEBUG(if(L->getLoopDepth()>1 || !L->getSubLoops().empty()) return NULL);
	DEBUG(errs()<<"start value:"<<*start<<"\n");
	DEBUG(errs()<<"ind   value:"<<*ind<<"\n");
	DEBUG(errs()<<"next  value:"<<*next<<"\n");


	//process non add later
	unsigned next_phi_idx = 0;
	ConstantInt* Step = NULL,*PrevStep = NULL;/*only used if next is phi node*/
   ret_null_fail(next, "");
	PHINode* next_phi = dyn_cast<PHINode>(next);
	do{
		if(next_phi) {
			next = dyn_cast<Instruction>(next_phi->getIncomingValue(next_phi_idx));
			ret_null_fail(next, "");
			DEBUG(errs()<<"next phi "<<next_phi_idx<<":"<<*next<<"\n");
			if(Step&&PrevStep){
				Assert(Step->getSExtValue() == PrevStep->getSExtValue(),"");
			}
			PrevStep = Step;
		}
		Assert(next->getOpcode() == Instruction::Add , "why induction increment is not Add");
		Assert(next->getOperand(0) == ind ,"why induction increment is not add it self");
		Step = dyn_cast<ConstantInt>(next->getOperand(1));
		Assert(Step,"");
	}while(next_phi && ++next_phi_idx<next_phi->getNumIncomingValues());
	//RET_ON_FAIL(Step->equalsInt(1));
	//assert(VERBOSE(Step->equalsInt(1),Step) && "why induction increment number is not 1");


	Value* RES = NULL;
	//if there are no predecessor, we can insert code into start value basicblock
	IRBuilder<> Builder(InsertPos);
	Assert(start->getType()->isIntegerTy() && END->getType()->isIntegerTy() , " why increment is not integer type");
	if(start->getType() != END->getType()){
		start = Builder.CreateCast(CastInst::getCastOpcode(start, false,
					END->getType(), false),start,END->getType());
	}
   if(Step->getType() != END->getType()){
      //Because Step is a Constant, so it casted is constant
		Step = dyn_cast<ConstantInt>(Builder.CreateCast(CastInst::getCastOpcode(Step, false,
					END->getType(), false),Step,END->getType()));
      AssertRuntime(Step);
   }
	if(Step->isMinusOne())
		RES = Builder.CreateSub(start,END);
	else//Step Couldn't be zero
		RES = Builder.CreateSub(END, start);
	if(addfirst) OneStep -= 1;
	if(Step->isMinusOne()) OneStep*=-1;
	assert(OneStep<=1 && OneStep>=-1);
	RES = (OneStep==1)?Builder.CreateAdd(RES,Step):(OneStep==-1)?Builder.CreateSub(RES, Step):RES;
	if(!Step->isMinusOne()&&!Step->isOne())
		RES = Builder.CreateSDiv(RES, Step);
	RES->setName(H->getName()+".tc");

	return RES;
}
bool HexagonOptimizeSZextends::runOnFunction(Function &F) {
  unsigned Idx = 1;
  // Try to optimize sign extends in formal parameters. It's relying on
  // callee already sign extending the values. I'm not sure if our ABI
  // requires callee to sign extend though.
  for (auto &Arg : F.args()) {
    if (F.getAttributes().hasAttribute(Idx, Attribute::SExt)) {
      if (!isa<PointerType>(Arg.getType())) {
        for (auto UI = Arg.use_begin(); UI != Arg.use_end();) {
          if (isa<SExtInst>(*UI)) {
            Instruction* Use = cast<Instruction>(*UI);
            SExtInst* SI = new SExtInst(&Arg, Use->getType());
            assert (EVT::getEVT(SI->getType()) ==
                    (EVT::getEVT(Use->getType())));
            ++UI;
            Use->replaceAllUsesWith(SI);
            Instruction* First = &F.getEntryBlock().front();
            SI->insertBefore(First);
            Use->eraseFromParent();
          } else {
            ++UI;
          }
        }
      }
    }
    ++Idx;
  }

  // Try to remove redundant sext operations on Hexagon. The hardware
  // already sign extends many 16 bit intrinsic operations to 32 bits.
  // For example:
  // %34 = tail call i32 @llvm.hexagon.A2.addh.l16.sat.ll(i32 %x, i32 %y)
  // %sext233 = shl i32 %34, 16
  // %conv52 = ashr exact i32 %sext233, 16
  for (auto &B : F) {
    for (auto &I : B) {
      // Look for arithmetic shift right by 16.
      BinaryOperator *Ashr = dyn_cast<BinaryOperator>(&I);
      if (!(Ashr && Ashr->getOpcode() == Instruction::AShr))
        continue;
      Value *AshrOp1 = Ashr->getOperand(1);
      ConstantInt *C = dyn_cast<ConstantInt>(AshrOp1);
      // Right shifted by 16.
      if (!(C && C->getSExtValue() == 16))
        continue;

      // The first operand of Ashr comes from logical shift left.
      Instruction *Shl = dyn_cast<Instruction>(Ashr->getOperand(0));
      if (!(Shl && Shl->getOpcode() == Instruction::Shl))
        continue;
      Value *Intr = Shl->getOperand(0);
      Value *ShlOp1 = Shl->getOperand(1);
      C = dyn_cast<ConstantInt>(ShlOp1);
      // Left shifted by 16.
      if (!(C && C->getSExtValue() == 16))
        continue;

      // The first operand of Shl comes from an intrinsic.
      if (IntrinsicInst *I = dyn_cast<IntrinsicInst>(Intr)) {
        if (!intrinsicAlreadySextended(I->getIntrinsicID()))
          continue;
        // All is well. Replace all uses of AShr with I.
        for (auto UI = Ashr->user_begin(), UE = Ashr->user_end();
             UI != UE; ++UI) {
          const Use &TheUse = UI.getUse();
          if (Instruction *J = dyn_cast<Instruction>(TheUse.getUser())) {
            J->replaceUsesOfWith(Ashr, I);
          }
        }
      }
    }
  }

  return true;
}
	void CGGraph::constructGraph() {

		std::vector<CGConstraint*>::iterator it;
		std::string nodeName;
		CGConstraint* curConstraint;
		CGNode* firstNode;
		CGNode* secondNode;
		std::vector<int>::iterator lengthIt;
		int curValue;
		ConstantInt* cInt;

		for (it = constraints.begin(); it != constraints.end(); ++it) {

			curConstraint = *it;
			Instruction* PP = curConstraint->programPoint;

			switch(curConstraint->type) {
				case CGConstraint::C1:
				{

					firstNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(0), PP));
					secondNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(1), PP));

					firstNode->connectTo(secondNode, 0);
					
					break;
				}
				case CGConstraint::C2:
				{
					if (isa<StoreInst>(PP)) {
						/*
						operand(0) = constant int or variable of int type
						operand(1)  = var being stored into
						*/
						firstNode = getNode(getNameFromValue(PP->getOperand(0), PP));
						secondNode = getNode(getNameFromValue(PP->getOperand(1), PP));
						firstNode->connectTo(secondNode, 0);
					}
					else if (isa<LoadInst>(PP)) {
						/*
						operand(0) = pointer being loaded from
						(Value*)PP  = var being loaded into
						*/
						firstNode = getNode(getNameFromValue(PP->getOperand(0), PP));
						secondNode = getNode(getNameFromValue(PP, PP));
						firstNode->connectTo(secondNode, 0);
					}
					else if (isa<CastInst>(PP)) {
						/*
						operand(0) = var being casted 
						(Value*)PP  = var getting the result of the cast
						*/
						firstNode = getNode(getNameFromValue(PP->getOperand(0), PP));
						secondNode = getNode(getNameFromValue(PP, PP));
						firstNode->connectTo(secondNode, 0);
					}

					break;
				}
				case CGConstraint::C3:
				{
				
					secondNode = getNode(getNameFromValue(PP, PP));
					if ((cInt = dyn_cast<ConstantInt>(curConstraint->programPoint->getOperand(0)))) {
						firstNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(1), PP));
					} else if ((cInt = dyn_cast<ConstantInt>(curConstraint->programPoint->getOperand(1)))) {
						firstNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(0), PP));
					} else {
						return;
					}
					curValue = cInt->getSExtValue();
					firstNode->connectTo(secondNode, curValue);
					break;
				}
				case CGConstraint::C4:
				{

					CmpInst* cmpInst;
					BranchInst* branchInst;
					
					if( !(branchInst = dyn_cast<BranchInst>(curConstraint->programPoint)) ) {
						errs() << "ERROR: BranchInst cast unsuccessful for C4 in CGGraph::constructGraph() \n";
						return;
					}
					if( !(cmpInst = dyn_cast<CmpInst>(owner->branchToCompare[branchInst])) ) {
						errs() << "ERROR: CmpInst not found for C4 in CGGraph::constructGraph() \n";
						return;
					}

					int size1, size2;
					size1 = curConstraint->piAssignments.size();
					size2 = curConstraint->piAssignments2.size();
					/*
					There are two possibilities here: (a) size1 = size2 = 2, or (b) size1 = size2 = 1;
					If (b), there will be one operand in the compare inst that is a literal value.
					That literal value still generates a constraint although it does not generate a pi assignment.
					We need to account for that.
					*/

					if (size1 != size2) {
						errs() << "ERROR: piAssignments not of equal length for C4 in CGGraph::constructGraph()\n"; 
						return;
					}
					if ( (size1 < 1) || (size1 > 2) ) {
						errs() << "ERROR: piAssignments.size() != 1 or 2 for C4 in CGGraph::constructGraph()\n"; 
						return;
					}
						
					//this takes care of the first two constraints for both cases (size = 1 or size = 2)
					//first branch
					for (int i = 0; i < size1; ++i) {
						firstNode = getNode(curConstraint->piAssignments[i]->getOperandName()); //vi - wr
						secondNode = getNode(curConstraint->piAssignments[i]->getAssignedName()); //vj - ws 
						firstNode->connectTo(secondNode, 0); //vi -> vj 0  -  wr -> ws 0
					}
					//second branch
					for (int i = 0; i < size2; ++i) {
						firstNode = getNode(curConstraint->piAssignments2[i]->getOperandName()); //vi - wr
						secondNode = getNode(curConstraint->piAssignments2[i]->getAssignedName()); //vk - wt 
						firstNode->connectTo(secondNode, 0); //vi -> vk 0  -  wr -> wt 0
					}
		
					/*
					- first and second op names for the third constraint for branches 1 and 2
					- each case is stored in the order of the pi assignments, which is also the 
					order of the cmp instruction operands
					*/
					std::string firstOpNameBr1, secondOpNameBr1, firstOpNameBr2, secondOpNameBr2;
					
					if (size1 == 1) {
						/*
						the 2nd constraint in the table will not exist in this case, but there will be a 3rd constraint
						that was missed by the above, e.g.
						if (x1 <= 10)
						1. x2 <= x1
						2. nothing
						3. x2 <= 10  <---- we need to add this here
						*/ 
						
						//prune the int from the CmpInst
						if (cmpInst->getNumOperands() != 2) {
							errs() << "ERROR: cmpInst->getNumOperands() != 2 in CGGraph::constructGraph()\n";
							return;
						}
						if ((cInt = dyn_cast<ConstantInt>(cmpInst->getOperand(0)))) {
							//int is first op
							firstOpNameBr1 = getNameFromValue(cInt, PP);
							secondOpNameBr1 = curConstraint->piAssignments[0]->getAssignedName();
							firstOpNameBr2 = firstOpNameBr1;
							secondOpNameBr2 = curConstraint->piAssignments2[0]->getAssignedName();
						} else if ((cInt = dyn_cast<ConstantInt>(cmpInst->getOperand(1)))) {
							//int is second op 
							firstOpNameBr1 = curConstraint->piAssignments[0]->getAssignedName();
							secondOpNameBr1 = getNameFromValue(cInt, PP);
							firstOpNameBr2 = curConstraint->piAssignments2[0]->getAssignedName();
							secondOpNameBr2 = secondOpNameBr1;
						} else {
							errs() << "ERROR: int not found in cmpInstr in CGGraph::constructGraph()\n";
							return;
						}
					}
					else if (size1 == 2) {
						//store in order of pi assignments
						firstOpNameBr1 = curConstraint->piAssignments[0]->getAssignedName();
						secondOpNameBr1 = curConstraint->piAssignments[1]->getAssignedName();
						firstOpNameBr2 = curConstraint->piAssignments2[0]->getAssignedName();
						secondOpNameBr2 = curConstraint->piAssignments2[1]->getAssignedName();
					}
	
					CGNode* firstNodeBr1 = getNode(firstOpNameBr1);
					CGNode* secondNodeBr1 = getNode(secondOpNameBr1);
					CGNode* firstNodeBr2 = getNode(firstOpNameBr2);
					CGNode* secondNodeBr2 = getNode(secondOpNameBr2);
					
					switch(cmpInst->getPredicate()) {
						case CmpInst::ICMP_SGT: // >
							firstNodeBr1->connectTo(secondNodeBr1, -1); //vj -> ws -1
							secondNodeBr2->connectTo(firstNodeBr2, 0); //wt -> vk 0
							break;
						case CmpInst::ICMP_SLT: // <
							secondNodeBr1->connectTo(firstNodeBr1, -1); //ws -> vj -1
							firstNodeBr2->connectTo(secondNodeBr2, 0); //vk -> wt 0
							break;
						case CmpInst::ICMP_SGE: // >=
							firstNodeBr1->connectTo(secondNodeBr1, 0); //vj -> ws 0
							secondNodeBr2->connectTo(firstNodeBr2, -1); //wt -> vk -1
							break;
						case CmpInst::ICMP_SLE: // <=
							secondNodeBr1->connectTo(firstNodeBr1, 0); //ws -> vj 0
							firstNodeBr2->connectTo(secondNodeBr2, -1); //vk -> wt -1						
							break;
						default:
							break;
					}

					break;
				}
				case CGConstraint::C5:
				{
					//operand 1 = array length
					firstNode = getNode(getNameFromValue(PP->getOperand(1), PP));
					secondNode = getNode(curConstraint->piAssignments[0]->getAssignedName());
					firstNode->connectTo(secondNode, -1);
					break;
				}
				case CGConstraint::CONTROL_FLOW:
				{
					//Done and ready to test

					firstNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(0), PP));
					secondNode = getNode(getNameFromValue(curConstraint->programPoint, PP));
					firstNode->connectTo(secondNode, 0);
					firstNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(1), PP));
					firstNode->connectTo(secondNode, 0);
					break;
				}
			} //end switch
		} //end for	
	} //end constructGraph()
Esempio n. 10
0
/// MatchOperationAddr - Given an instruction or constant expr, see if we can
/// fold the operation into the addressing mode.  If so, update the addressing
/// mode and return true, otherwise return false without modifying AddrMode.
bool AddressingModeMatcher::MatchOperationAddr(User *AddrInst, unsigned Opcode,
                                               unsigned Depth) {
  // Avoid exponential behavior on extremely deep expression trees.
  if (Depth >= 5) return false;
  
  switch (Opcode) {
  case Instruction::PtrToInt:
    // PtrToInt is always a noop, as we know that the int type is pointer sized.
    return MatchAddr(AddrInst->getOperand(0), Depth);
  case Instruction::IntToPtr:
    // This inttoptr is a no-op if the integer type is pointer sized.
    if (TLI.getValueType(AddrInst->getOperand(0)->getType()) ==
        TLI.getPointerTy())
      return MatchAddr(AddrInst->getOperand(0), Depth);
    return false;
  case Instruction::BitCast:
    // BitCast is always a noop, and we can handle it as long as it is
    // int->int or pointer->pointer (we don't want int<->fp or something).
    if ((AddrInst->getOperand(0)->getType()->isPointerTy() ||
         AddrInst->getOperand(0)->getType()->isIntegerTy()) &&
        // Don't touch identity bitcasts.  These were probably put here by LSR,
        // and we don't want to mess around with them.  Assume it knows what it
        // is doing.
        AddrInst->getOperand(0)->getType() != AddrInst->getType())
      return MatchAddr(AddrInst->getOperand(0), Depth);
    return false;
  case Instruction::Add: {
    // Check to see if we can merge in the RHS then the LHS.  If so, we win.
    ExtAddrMode BackupAddrMode = AddrMode;
    unsigned OldSize = AddrModeInsts.size();
    if (MatchAddr(AddrInst->getOperand(1), Depth+1) &&
        MatchAddr(AddrInst->getOperand(0), Depth+1))
      return true;
    
    // Restore the old addr mode info.
    AddrMode = BackupAddrMode;
    AddrModeInsts.resize(OldSize);
    
    // Otherwise this was over-aggressive.  Try merging in the LHS then the RHS.
    if (MatchAddr(AddrInst->getOperand(0), Depth+1) &&
        MatchAddr(AddrInst->getOperand(1), Depth+1))
      return true;
    
    // Otherwise we definitely can't merge the ADD in.
    AddrMode = BackupAddrMode;
    AddrModeInsts.resize(OldSize);
    break;
  }
  //case Instruction::Or:
  // TODO: We can handle "Or Val, Imm" iff this OR is equivalent to an ADD.
  //break;
  case Instruction::Mul:
  case Instruction::Shl: {
    // Can only handle X*C and X << C.
    ConstantInt *RHS = dyn_cast<ConstantInt>(AddrInst->getOperand(1));
    if (!RHS) return false;
    int64_t Scale = RHS->getSExtValue();
    if (Opcode == Instruction::Shl)
      Scale = 1LL << Scale;
    
    return MatchScaledValue(AddrInst->getOperand(0), Scale, Depth);
  }
  case Instruction::GetElementPtr: {
    // Scan the GEP.  We check it if it contains constant offsets and at most
    // one variable offset.
    int VariableOperand = -1;
    unsigned VariableScale = 0;
    
    int64_t ConstantOffset = 0;
    const TargetData *TD = TLI.getTargetData();
    gep_type_iterator GTI = gep_type_begin(AddrInst);
    for (unsigned i = 1, e = AddrInst->getNumOperands(); i != e; ++i, ++GTI) {
      if (const StructType *STy = dyn_cast<StructType>(*GTI)) {
        const StructLayout *SL = TD->getStructLayout(STy);
        unsigned Idx =
          cast<ConstantInt>(AddrInst->getOperand(i))->getZExtValue();
        ConstantOffset += SL->getElementOffset(Idx);
      } else {
        uint64_t TypeSize = TD->getTypeAllocSize(GTI.getIndexedType());
        if (ConstantInt *CI = dyn_cast<ConstantInt>(AddrInst->getOperand(i))) {
          ConstantOffset += CI->getSExtValue()*TypeSize;
        } else if (TypeSize) {  // Scales of zero don't do anything.
          // We only allow one variable index at the moment.
          if (VariableOperand != -1)
            return false;
          
          // Remember the variable index.
          VariableOperand = i;
          VariableScale = TypeSize;
        }
      }
    }
    
    // A common case is for the GEP to only do a constant offset.  In this case,
    // just add it to the disp field and check validity.
    if (VariableOperand == -1) {
      AddrMode.BaseOffs += ConstantOffset;
      if (ConstantOffset == 0 || TLI.isLegalAddressingMode(AddrMode, AccessTy)){
        // Check to see if we can fold the base pointer in too.
        if (MatchAddr(AddrInst->getOperand(0), Depth+1))
          return true;
      }
      AddrMode.BaseOffs -= ConstantOffset;
      return false;
    }

    // Save the valid addressing mode in case we can't match.
    ExtAddrMode BackupAddrMode = AddrMode;
    unsigned OldSize = AddrModeInsts.size();

    // See if the scale and offset amount is valid for this target.
    AddrMode.BaseOffs += ConstantOffset;

    // Match the base operand of the GEP.
    if (!MatchAddr(AddrInst->getOperand(0), Depth+1)) {
      // If it couldn't be matched, just stuff the value in a register.
      if (AddrMode.HasBaseReg) {
        AddrMode = BackupAddrMode;
        AddrModeInsts.resize(OldSize);
        return false;
      }
      AddrMode.HasBaseReg = true;
      AddrMode.BaseReg = AddrInst->getOperand(0);
    }

    // Match the remaining variable portion of the GEP.
    if (!MatchScaledValue(AddrInst->getOperand(VariableOperand), VariableScale,
                          Depth)) {
      // If it couldn't be matched, try stuffing the base into a register
      // instead of matching it, and retrying the match of the scale.
      AddrMode = BackupAddrMode;
      AddrModeInsts.resize(OldSize);
      if (AddrMode.HasBaseReg)
        return false;
      AddrMode.HasBaseReg = true;
      AddrMode.BaseReg = AddrInst->getOperand(0);
      AddrMode.BaseOffs += ConstantOffset;
      if (!MatchScaledValue(AddrInst->getOperand(VariableOperand),
                            VariableScale, Depth)) {
        // If even that didn't work, bail.
        AddrMode = BackupAddrMode;
        AddrModeInsts.resize(OldSize);
        return false;
      }
    }

    return true;
  }
  }
  return false;
}
Esempio n. 11
0
void DebugDatabase::addVariableSourceDbgValue(DebugValue *dbgVal,
                                              TraceScheduler *traceScheduler) {
    DbgValueInst *dbgValInst = dbgVal->getDbgValInsn();
    assert(dbgValInst);

    int id = addVariableSource(dbgVal->getVariable(), dbgValInst, true);

    std::string query;
    if (dbgVal->isConstantInt()) {
        // Get the integer value
        ConstantInt *ci = cast<ConstantInt>(dbgValInst->getValue());

        query = "INSERT INTO VariableSourceConstantInt ";
        query += "(VariableSourceId, constantInt) ";
        query += "VALUES (" + std::to_string(id);
        query += "," + std::to_string(ci->getSExtValue());
        query += ");";
        runQuery(query);

    } else if (dbgVal->isConstantNull()) {
        query = "INSERT INTO VariableSourceConstantInt ";
        query += "(VariableSourceId, constantInt) ";
        query += "VALUES (" + std::to_string(id);
        query += ",NULL";
        query += ");";
        runQuery(query);

    } else if (dbgVal->isConstantPointer()) {
        ConstantExpr *CE = dyn_cast<ConstantExpr>(dbgValInst->getValue());
        assert(CE);

        Value *base;
        int offset;
        getGEPBaseAndOffset(CE, &base, &offset);

        int ramId = ramToIds[dbgInfo->getAlloc()->getRAM(base)];
        assert(ramId);

        query = "INSERT INTO VariableSourcePointer ";
        query += "(VariableSourceId, ramId, offset) ";
        query += "VALUES (" + std::to_string(id);
        query += "," + std::to_string(ramId);
        query += "," + std::to_string(offset);
        query += ");";
        runQuery(query);

    } else if (dbgVal->isAlloca()) {
        RAM *ram =
            dbgInfo->getAlloc()->getRAM(dbgVal->getDbgValInsn()->getValue());
        assert(ram);

        int offset = dbgVal->getDbgValInsn()->getOffset();

        int ramId = ramToIds[ram];
        assert(ramId);

        query = "INSERT INTO VariableSourcePointer ";
        query += "(VariableSourceId, ramId, offset) ";
        query += "VALUES (" + std::to_string(id);
        query += "," + std::to_string(ramId);
        query += "," + std::to_string(offset);
        query += ");";
        runQuery(query);

        //        dbgs() << *(dbgVal->getDbgValInsn()) << " is an alloca\n";
    } else if (dbgVal->isArgument() || dbgVal->isFunctionCall() ||
               dbgVal->isRegister()) {
        GenerateRTL *hw = dbgVal->getVariable()->getGenRtl();

        string signalName = dbgVal->getSignalName();
        RTLSignal *signal;

        signal = hw->getRTL()->findExists(signalName);

        if (!signal) {
            dbgs() << *(dbgVal->getDbgValInsn()) << "\n";
            dbgs() << "Can't find signal " << dbgVal->getSignalName() << "\n";
        }

        //        RTLSignal *signal =
        //        hw->getRTL()->find(dbgVal->getSignalName());

        query = "INSERT INTO VariableSourceSignal ";
        query += "(VariableSourceId, rtlSignalId) ";
        query += "VALUES (" + std::to_string(id);
        query += "," + std::to_string(rtlSignalToIds[signal]);
        query += ");";
        runQuery(query);

    } else if (dbgVal->isUndefined()) {
        query = "INSERT INTO VariableSourceUndefined ";
        query += "(VariableSourceId) ";
        query += "VALUES (" + std::to_string(id);
        query += ");";
        runQuery(query);
    } else {
        dbgs() << *(dbgValInst) << "\n";
        dbgs() << *(dbgValInst->getValue()) << "\n";
        assert(false);
    }
}