// 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"; });
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); } } } }
int InductionDescriptor::getConsecutiveDirection() const { ConstantInt *ConstStep = getConstIntStepValue(); if (ConstStep && (ConstStep->isOne() || ConstStep->isMinusOne())) return ConstStep->getSExtValue(); return 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; }
// // 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; }
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; }
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()
/// 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; }
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); } }