bool Scalarizer::visitGetElementPtrInst(GetElementPtrInst &GEPI) { VectorType *VT = dyn_cast<VectorType>(GEPI.getType()); if (!VT) return false; IRBuilder<> Builder(&GEPI); unsigned NumElems = VT->getNumElements(); unsigned NumIndices = GEPI.getNumIndices(); Scatterer Base = scatter(&GEPI, GEPI.getOperand(0)); SmallVector<Scatterer, 8> Ops; Ops.resize(NumIndices); for (unsigned I = 0; I < NumIndices; ++I) Ops[I] = scatter(&GEPI, GEPI.getOperand(I + 1)); ValueVector Res; Res.resize(NumElems); for (unsigned I = 0; I < NumElems; ++I) { SmallVector<Value *, 8> Indices; Indices.resize(NumIndices); for (unsigned J = 0; J < NumIndices; ++J) Indices[J] = Ops[J][I]; Res[I] = Builder.CreateGEP(GEPI.getSourceElementType(), Base[I], Indices, GEPI.getName() + ".i" + Twine(I)); if (GEPI.isInBounds()) if (GetElementPtrInst *NewGEPI = dyn_cast<GetElementPtrInst>(Res[I])) NewGEPI->setIsInBounds(); } gather(&GEPI, Res); return true; }
bool EfficiencySanitizer::instrumentGetElementPtr(Instruction *I, Module &M) { GetElementPtrInst *GepInst = dyn_cast<GetElementPtrInst>(I); bool Res = false; if (GepInst == nullptr || GepInst->getNumIndices() == 1) { ++NumIgnoredGEPs; return false; } Type *SourceTy = GepInst->getSourceElementType(); StructType *StructTy = nullptr; ConstantInt *Idx; // Check if GEP calculates address from a struct array. if (isa<StructType>(SourceTy)) { StructTy = cast<StructType>(SourceTy); Idx = dyn_cast<ConstantInt>(GepInst->getOperand(1)); if ((Idx == nullptr || Idx->getSExtValue() != 0) && !shouldIgnoreStructType(StructTy) && StructTyMap.count(StructTy) != 0) Res |= insertCounterUpdate(I, StructTy, getArrayCounterIdx(StructTy)); } // Iterate all (except the first and the last) idx within each GEP instruction // for possible nested struct field address calculation. for (unsigned i = 1; i < GepInst->getNumIndices(); ++i) { SmallVector<Value *, 8> IdxVec(GepInst->idx_begin(), GepInst->idx_begin() + i); Type *Ty = GetElementPtrInst::getIndexedType(SourceTy, IdxVec); unsigned CounterIdx = 0; if (isa<ArrayType>(Ty)) { ArrayType *ArrayTy = cast<ArrayType>(Ty); StructTy = dyn_cast<StructType>(ArrayTy->getElementType()); if (shouldIgnoreStructType(StructTy) || StructTyMap.count(StructTy) == 0) continue; // The last counter for struct array access. CounterIdx = getArrayCounterIdx(StructTy); } else if (isa<StructType>(Ty)) { StructTy = cast<StructType>(Ty); if (shouldIgnoreStructType(StructTy) || StructTyMap.count(StructTy) == 0) continue; // Get the StructTy's subfield index. Idx = cast<ConstantInt>(GepInst->getOperand(i+1)); assert(Idx->getSExtValue() >= 0 && Idx->getSExtValue() < StructTy->getNumElements()); CounterIdx = getFieldCounterIdx(StructTy) + Idx->getSExtValue(); } Res |= insertCounterUpdate(I, StructTy, CounterIdx); } if (Res) ++NumInstrumentedGEPs; else ++NumIgnoredGEPs; return Res; }
/// If the argument is a GEP, then returns the operand identified by /// getGEPInductionOperand. However, if there is some other non-loop-invariant /// operand, it returns that instead. Value *llvm::stripGetElementPtr(Value *Ptr, ScalarEvolution *SE, Loop *Lp) { GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr); if (!GEP) return Ptr; unsigned InductionOperand = getGEPInductionOperand(GEP); // Check that all of the gep indices are uniform except for our induction // operand. for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) if (i != InductionOperand && !SE->isLoopInvariant(SE->getSCEV(GEP->getOperand(i)), Lp)) return Ptr; return GEP->getOperand(InductionOperand); }
void Executor::executeGep(Instruction *i) { if (DisabledSymbolicExeCurRun) { return; } assert(i && "Expecting an instruction!"); GetElementPtrInst *gep = (GetElementPtrInst*) i; assert(gep->getNumIndices()<=2 && "Unsupported gep instruction"); if(AllocaInst *a = dyn_cast<AllocaInst>(gep->getPointerOperand())) { Type *ty = a->getAllocatedType(); if (ty->isIntegerTy()) { // Incompleteness: pointer dereferencement on symbolic value AllLocDefinite = false; return; } } unsigned idx = 0; Type *subTy = NULL; Type *ptrOpTy = gep->getPointerOperandType(); if (ptrOpTy && ptrOpTy->getNumContainedTypes()==1) { subTy = ptrOpTy->getContainedType(0); } if (subTy && subTy->getNumContainedTypes()>0) { idx = 1; } else { assert("Unsupported gep instruction!"); } Value *ptr = (Value*) i; if(gep->hasIndices()) { Value *index = gep->getOperand(idx+1); if (SMAP->contains(index)) { // P[v->sv] // sv is a new symbolic value // Value *a = gep->getPointerOperand(); // ptr = (a index) //SymbolPtr Sindex = SMAP->get(index); //PMAP->createGepOp(ptr, a, Sindex); // Incompleteness: pointer dereferencement on symbolic value AllLocDefinite = false; } else { // P = P - ptr PMAP->remove(ptr); } } // Global allocation /*else if(isa<GlobalVariable>(ptr)) { // ptr in domain(P) if (PMAP->contains(ptr)) { SymbolPtr Pptr = PMAP->get(ptr); // P' = P[ptr->S(val)] PMAP->update(ptr, Pptr); } else { // P = P - ptr PMAP->remove(ptr); } }*/ }
/* * Very sloppy implementation for quick prototyping * // TODO Assumption is that the first field contains the number of iterations -- if not, then modify source for now */ Value *HeteroOMPTransform::find_loop_upper_bound(Value *context) { // TODO Assumption is that the first field contains the number of iterations -- if not, then modify source for now for (Value::use_iterator i = context->use_begin(), e = context->use_end(); i != e; ++i) { Instruction *insn = dyn_cast<Instruction>(*i); GetElementPtrInst *GEP; StoreInst *SI; if ((GEP = dyn_cast<GetElementPtrInst>(insn)) && isa<ConstantInt>(GEP->getOperand(2)) && ((cast<ConstantInt>(GEP->getOperand(2)))->equalsInt(0))) { /// README:NOTE THE ASSUMPTION THAT THE FIRST ELEMENT IN THE CONTEXT IS MAX ITERATION OF PARALLEL LOOP for (Value::use_iterator I = insn->use_begin(), E = insn->use_end(); I != E; ++I) { if ((SI = dyn_cast<StoreInst>(*I))) { Value *op_0 = SI->getOperand(0); return op_0; } } } } return NULL; }
void ModuloScheduler::findLoopCarriedMemoryAccesses( RAM *globalRAM, std::map<Instruction *, MEM_ACCESS> &memAccessMap, std::map<RAM *, std::vector<MEM_ACCESS>> &memoryAccesses) { assert(alloc); // add additional memory constraints for local memory read/writes for (BasicBlock::iterator I = BB->begin(), ie = BB->end(); I != ie; I++) { Value *addr = NULL; std::string memtype; if (LoadInst *L = dyn_cast<LoadInst>(I)) { addr = L->getPointerOperand(); memtype = "load"; } else if (StoreInst *S = dyn_cast<StoreInst>(I)) { addr = S->getPointerOperand(); memtype = "store"; } else { continue; } RAM *ram; if (LEGUP_CONFIG->getParameterInt("LOCAL_RAMS")) { ram = alloc->getLocalRamFromValue(addr); } else { ram = globalRAM; } if (!ram) continue; GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(addr); if (!GEP) continue; Value *offset = GEP->getOperand(2); MEM_ACCESS access; access.I = I; access.ram = ram; int indexOffset = 0; if (findInductionOffset(offset, ram, loop->getCanonicalInductionVariable(), memtype, &indexOffset)) { // found an offset to the induction variable access.type = MEM_ACCESS::InductionOffset; access.offset = indexOffset; } else { access.type = MEM_ACCESS::Address; access.ptr = GEP; } memoryAccesses[ram].push_back(access); memAccessMap[I] = access; } }
// // Method: preprocess() // // Description: // %p = bitcast %p1 to T1 // gep(%p) ... // -> // gep (bitcast %p1 to T1), ... // // Inputs: // M - A reference to the LLVM module to process // // Outputs: // M - The transformed LLVM module. // static void preprocess(Module& 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); if(BitCastInst *BI = dyn_cast<BitCastInst>(GEP->getOperand(0))) { if(Constant *C = dyn_cast<Constant>(BI->getOperand(0))) { GEP->setOperand(0, ConstantExpr::getBitCast(C, BI->getType())); } } } } } }
/// Determines whether a phi corresponds to an inbounds recurrence where the /// base is not a known nonnull-or-poison value. Returns the base value, or /// null if the phi doesn't correspond to such a recurrence. Value *NullCheckElimination::isNontrivialInBoundsRecurrence(PHINode *PN) { if (PN->getNumOperands() != 2) return nullptr; Value *BaseV; GetElementPtrInst *SuccessorI; if (auto *GEP = castToInBoundsGEP(PN->getOperand(0))) { BaseV = PN->getOperand(1); SuccessorI = GEP; } else if (auto *GEP = castToInBoundsGEP(PN->getOperand(1))) { BaseV = PN->getOperand(0); SuccessorI = GEP; } else { return nullptr; } if (NonNullOrPoisonValues.count(BaseV) || SuccessorI->getOperand(0) != PN) return nullptr; return BaseV; }
// FIXME: Merge with llvm::isConsecutiveAccess bool Vectorizer::isConsecutiveAccess(Value *A, Value *B) { Value *PtrA = getPointerOperand(A); Value *PtrB = getPointerOperand(B); unsigned ASA = getPointerAddressSpace(A); unsigned ASB = getPointerAddressSpace(B); // Check that the address spaces match and that the pointers are valid. if (!PtrA || !PtrB || (ASA != ASB)) return false; // Make sure that A and B are different pointers of the same size type. unsigned PtrBitWidth = DL.getPointerSizeInBits(ASA); Type *PtrATy = PtrA->getType()->getPointerElementType(); Type *PtrBTy = PtrB->getType()->getPointerElementType(); if (PtrA == PtrB || DL.getTypeStoreSize(PtrATy) != DL.getTypeStoreSize(PtrBTy) || DL.getTypeStoreSize(PtrATy->getScalarType()) != DL.getTypeStoreSize(PtrBTy->getScalarType())) return false; APInt Size(PtrBitWidth, DL.getTypeStoreSize(PtrATy)); unsigned IdxWidth = DL.getIndexSizeInBits(ASA); APInt OffsetA(IdxWidth, 0), OffsetB(IdxWidth, 0); PtrA = PtrA->stripAndAccumulateInBoundsConstantOffsets(DL, OffsetA); PtrB = PtrB->stripAndAccumulateInBoundsConstantOffsets(DL, OffsetB); APInt OffsetDelta = OffsetB - OffsetA; // Check if they are based on the same pointer. That makes the offsets // sufficient. if (PtrA == PtrB) return OffsetDelta == Size; // Compute the necessary base pointer delta to have the necessary final delta // equal to the size. APInt BaseDelta = Size - OffsetDelta; // Compute the distance with SCEV between the base pointers. const SCEV *PtrSCEVA = SE.getSCEV(PtrA); const SCEV *PtrSCEVB = SE.getSCEV(PtrB); const SCEV *C = SE.getConstant(BaseDelta); const SCEV *X = SE.getAddExpr(PtrSCEVA, C); if (X == PtrSCEVB) return true; // Sometimes even this doesn't work, because SCEV can't always see through // patterns that look like (gep (ext (add (shl X, C1), C2))). Try checking // things the hard way. // Look through GEPs after checking they're the same except for the last // index. GetElementPtrInst *GEPA = getSourceGEP(A); GetElementPtrInst *GEPB = getSourceGEP(B); if (!GEPA || !GEPB || GEPA->getNumOperands() != GEPB->getNumOperands()) return false; unsigned FinalIndex = GEPA->getNumOperands() - 1; for (unsigned i = 0; i < FinalIndex; i++) if (GEPA->getOperand(i) != GEPB->getOperand(i)) return false; Instruction *OpA = dyn_cast<Instruction>(GEPA->getOperand(FinalIndex)); Instruction *OpB = dyn_cast<Instruction>(GEPB->getOperand(FinalIndex)); if (!OpA || !OpB || OpA->getOpcode() != OpB->getOpcode() || OpA->getType() != OpB->getType()) return false; // Only look through a ZExt/SExt. if (!isa<SExtInst>(OpA) && !isa<ZExtInst>(OpA)) return false; bool Signed = isa<SExtInst>(OpA); OpA = dyn_cast<Instruction>(OpA->getOperand(0)); OpB = dyn_cast<Instruction>(OpB->getOperand(0)); if (!OpA || !OpB || OpA->getType() != OpB->getType()) return false; // Now we need to prove that adding 1 to OpA won't overflow. bool Safe = false; // First attempt: if OpB is an add with NSW/NUW, and OpB is 1 added to OpA, // we're okay. if (OpB->getOpcode() == Instruction::Add && isa<ConstantInt>(OpB->getOperand(1)) && cast<ConstantInt>(OpB->getOperand(1))->getSExtValue() > 0) { if (Signed) Safe = cast<BinaryOperator>(OpB)->hasNoSignedWrap(); else Safe = cast<BinaryOperator>(OpB)->hasNoUnsignedWrap(); } unsigned BitWidth = OpA->getType()->getScalarSizeInBits(); // Second attempt: // If any bits are known to be zero other than the sign bit in OpA, we can // add 1 to it while guaranteeing no overflow of any sort. if (!Safe) { KnownBits Known(BitWidth); computeKnownBits(OpA, Known, DL, 0, nullptr, OpA, &DT); if (Known.countMaxTrailingOnes() < (BitWidth - 1)) Safe = true; } if (!Safe) return false; const SCEV *OffsetSCEVA = SE.getSCEV(OpA); const SCEV *OffsetSCEVB = SE.getSCEV(OpB); const SCEV *One = SE.getConstant(APInt(BitWidth, 1)); const SCEV *X2 = SE.getAddExpr(OffsetSCEVA, One); return X2 == OffsetSCEVB; }
// // 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 = &getAnalysis<TargetData>(); 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(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(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(StrippedPtr, Idx, GEP->getName(), GEP); GEP->replaceAllUsesWith(new BitCastInst(NewGEP, GEP->getType(), GEP->getName(), GEP)); continue; } } } } } } } return true; }
string esp::parseName(Value *value){ // has existed if(names.find(value) != names.end()) return names[value]; string name = ""; Value *current = value; /* bool continueFlag = true; do{ if(isa<Instruction > (current)){ Instruction* inst = dyn_cast<Instruction>(current); unsigned op = inst->getOpcode(); switch(op){ case Instruction::Ret :{ break; } case Instruction::Br :{ break; } case Instruction::Switch :{ break; } case Instruction::Call :{ CallInst *callinst = (CallInst*) current; if (((CallInst*) current)->getCalledFunction() != NULL) { name += string("@")+((CallInst*) current)->getCalledFunction()->getNameStr() + "("; } else { name += string("@[funcPTR]("); name += ((CallInst*) current)->getCalledValue()->getNameStr(); } for (unsigned i = 1; i < callinst->getNumOperands(); i++) { name += esp::parseName(callinst->getOperand(i)); } name += string(")"); continueFlag = false; break; } case Instruction::PHI :{ name += string("PHI["); name += current->getNameStr(); PHINode *phi = (PHINode*) current; for (unsigned i = 0; i < phi->getNumIncomingValues(); i++) { Value *incoming = phi->getIncomingValue(i); if (i != 0) name += ","; if (!hasLoop(incoming)) { if (!incoming->hasName()) { name += esp::parseName(incoming); } else { name += incoming->getNameStr(); } } } name += std::string("]"); continueFlag = false; break; } case Instruction::Select :{ break; } case Instruction::Add :{ name += "+"; name += parseBinaryOpName(inst); break; } case Instruction::Sub :{ name += "-"; name += parseBinaryOpName(inst); break; } case Instruction::Mul :{ name += "*"; name += parseBinaryOpName(inst); break; } case Instruction::UDiv :{ name += "/"; name += parseBinaryOpName(inst); break; } case Instruction::SDiv :{ name += "//"; name += parseBinaryOpName(inst); break; } case Instruction::And :{ name += "&"; name += parseBinaryOpName(inst); break; } case Instruction::Or :{ name += "|"; name += parseBinaryOpName(inst); break; } case Instruction::Xor :{ name += "^"; name += parseBinaryOpName(inst); break; } case Instruction::Shl :{ name += "<<"; name += parseBinaryOpName(inst); break; } case Instruction::LShr :{ name += ">>"; name += parseBinaryOpName(inst); break; } case Instruction::AShr :{ name += ">>>"; name += parseBinaryOpName(inst); break; } case Instruction::ICmp :{ ICmpInst * icmp = dyn_cast<ICmpInst>(current); if (isa<Constant>(icmp->getOperand(0))) { name += esp::parseName(icmp->getOperand(1)); continueFlag = false; } else { name += esp::parseName(icmp->getOperand(0)); continueFlag = false; } break; } case Instruction::Alloca :{ name += current->getNameStr(); break; } case Instruction::Load :{ if (((LoadInst*) inst)->isVolatile()) name += std::string("@VolatileLoad"); name += "*"; name += esp::parseName(inst->getOperand(0)); continueFlag = false; break; } case Instruction::Store :{ // need to handle continueFlag = false; break; } case Instruction::GetElementPtr :{ GetElementPtrInst * gep = dyn_cast<GetElementPtrInst>(current); unsigned ops = gep->getNumOperands(); name += "["; for (unsigned i = 1; i < ops; i++) { Value *v = gep->getOperand(i); if (ConstantInt * ci = dyn_cast<ConstantInt>(v)) { if (i == 1 && ci->equalsInt(0)) continue; name += "."; name += ci->getValue().toString(10, false); } else { name += "."; name += esp::parseName(v); } } name += "]"; name += esp::parseName(gep->getOperand(0)); continueFlag = false; break; } case Instruction::BitCast:{ name += esp::parseName(inst->getOperand(0)); continueFlag = false; break; } default :{ // Illegal or unsupported instruction name += current->getNameStr(); break; } } }else if(isa<Argument>(current)){ if (arguments.find(current) != arguments.end()) name += std::string("$") + current->getNameStr(); }else if(isa<GlobalValue>(current)){ name += std::string("@") + current->getNameStr(); }else if(isa<ConstantInt>(current)){ ConstantInt * cint = dyn_cast<ConstantInt > (current); name += cint->getValue().toString(10, true); }else if (isa<Constant > (current)) { Constant *c = dyn_cast<Constant > (current); if (c->isNullValue()) { name += "null"; } }else{ // Illegal format } if(!continueFlag) break; current = parents[current]; }while(current); */ //Refactor do { if (isa<LoadInst > (current)) { name += "*"; if (parents[current] == NULL) name += (((LoadInst*) current)->getOperand(0))->getNameStr(); if (((LoadInst*) current)->isVolatile()) name += std::string("@VolatileLoad"); } else if (dyn_cast<GetElementPtrInst > (current)) { GetElementPtrInst * gep = dyn_cast<GetElementPtrInst > (current); unsigned ops = gep->getNumOperands(); name += "["; for (unsigned i = 1; i < ops; i++) { Value *v = gep->getOperand(i); if (dyn_cast<ConstantInt > (current)) { ConstantInt * ci = dyn_cast<ConstantInt > (current); if (i == 1 && ci->equalsInt(0)) continue; name += "."; name += ci->getValue().toString(10, false); } else { name += "."; name += parseName(v); } } name += "]"; name += parseName(gep->getOperand(0)); break; } else if (isa<AllocaInst > (current)) { name += current->getNameStr(); } else if (isa<Argument > (current)) { if (arguments.find(current) != arguments.end()) name += std::string("$") + current->getNameStr(); } else if (isa<GlobalValue > (current)) { name += std::string("@") + current->getNameStr(); } else if (isa<CallInst > (current)) { CallInst *callinst = (CallInst*) current; if (((CallInst*) current)->getCalledFunction() != NULL) { name += std::string("@")+((CallInst*) current)->getCalledFunction()->getNameStr() + "("; } else { name += std::string("@[funcPTR]("); name += ((CallInst*) current)->getCalledValue()->getNameStr(); } for (unsigned i = 1; i < callinst->getNumOperands(); i++) { name += parseName(callinst->getOperand(i)); } name += std::string(")"); break; } else if (isa<CastInst > (current)) { } else if (isa<PHINode > (current)) { /* name += std::string("PHI["); s += parent->getNameStr(); PHINode *phi = (PHINode*) parent; for (unsigned i = 0; i < phi->getNumIncomingValues(); i++) { //s+=phi->getIncomingBlock(i)->getNameStr(); Value *incoming = phi->getIncomingValue(i); if (i != 0) s += ","; if (!hasLoop(incoming)) { DEBUG(errs() << "incoming#" << i << " no loop(i rather doubt it)\n"); if (!incoming->hasName()) { s += parseName(incoming); } else { s += incoming->getNameStr(); } } } // PHI nodes...ugh s += std::string("]"); break; */ } else if (isa<BinaryOperator > (current)) { BinaryOperator *bo = dyn_cast<BinaryOperator > (current); Instruction::BinaryOps opcode = bo->getOpcode(); if (opcode == Instruction::Add) { name.append("+"); } else if (opcode == Instruction::Sub) { name.append("-"); } else if (opcode == Instruction::Or) { name.append("||"); } else if (opcode == Instruction::Mul) { name.append("*"); } else if (opcode == Instruction::Xor) { name.append("^"); } else if (opcode == Instruction::And) { name.append("&&"); } else if (opcode == Instruction::Shl) { name.append("<<"); } else if (opcode == Instruction::AShr) { name.append(">>"); } else if (opcode == Instruction::LShr) { name.append(">>>"); } Value *v0 = bo->getOperand(0); Value *v1 = bo->getOperand(1); if (isa<ConstantInt > (v0)) { name += ((ConstantInt*) v0)->getValue().toString(10, false); } else if (isa<ConstantInt > (v1)) { name += ((ConstantInt*) v1)->getValue().toString(10, false); } else { printDebugMsg("Binary Operation between non-constants\n"); } } else if (dyn_cast<GEPOperator > (current)) { GEPOperator * gep = dyn_cast<GEPOperator > (current); unsigned ops = gep->getNumOperands(); name += "["; for (unsigned i = 1; i < ops; i++) { Value *v = gep->getOperand(i); if (dyn_cast<ConstantInt > (v)) { ConstantInt * ci = dyn_cast<ConstantInt > (v); if (i == 1 && ci->equalsInt(0)) continue; name += "."; name += ci->getValue().toString(10, false); } } name += "]"; name += parseName(gep->getOperand(0)); break; } else if (dyn_cast<ICmpInst > (current)) { ICmpInst * icmp = dyn_cast<ICmpInst > (current); if (isa<Constant > (icmp->getOperand(0))) { name += parseName(icmp->getOperand(1)); break; } else { name += parseName(icmp->getOperand(0)); break; } } else if (dyn_cast<ConstantInt > (current)) { ConstantInt * cint = dyn_cast<ConstantInt > (current); name += cint->getValue().toString(10, true); } else { name += current->getNameStr(); // might not work } } while ((current = parents[current])); names[value] = name; return name; }
/// updateCallSites - Update all sites that call F to use NF. CallGraphNode *SRETPromotion::updateCallSites(Function *F, Function *NF) { CallGraph &CG = getAnalysis<CallGraph>(); SmallVector<Value*, 16> Args; // Attributes - Keep track of the parameter attributes for the arguments. SmallVector<AttributeWithIndex, 8> ArgAttrsVec; // Get a new callgraph node for NF. CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF); while (!F->use_empty()) { CallSite CS(*F->use_begin()); Instruction *Call = CS.getInstruction(); const AttrListPtr &PAL = F->getAttributes(); // Add any return attributes. if (Attributes attrs = PAL.getRetAttributes()) ArgAttrsVec.push_back(AttributeWithIndex::get(0, attrs)); // Copy arguments, however skip first one. CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); Value *FirstCArg = *AI; ++AI; // 0th parameter attribute is reserved for return type. // 1th parameter attribute is for first 1st sret argument. unsigned ParamIndex = 2; while (AI != AE) { Args.push_back(*AI); if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) ArgAttrsVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); ++ParamIndex; ++AI; } // Add any function attributes. if (Attributes attrs = PAL.getFnAttributes()) ArgAttrsVec.push_back(AttributeWithIndex::get(~0, attrs)); AttrListPtr NewPAL = AttrListPtr::get(ArgAttrsVec.begin(), ArgAttrsVec.end()); // Build new call instruction. Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args.begin(), Args.end(), "", Call); cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv()); cast<InvokeInst>(New)->setAttributes(NewPAL); } else { New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call); cast<CallInst>(New)->setCallingConv(CS.getCallingConv()); cast<CallInst>(New)->setAttributes(NewPAL); if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } Args.clear(); ArgAttrsVec.clear(); New->takeName(Call); // Update the callgraph to know that the callsite has been transformed. CallGraphNode *CalleeNode = CG[Call->getParent()->getParent()]; CalleeNode->removeCallEdgeFor(Call); CalleeNode->addCalledFunction(New, NF_CGN); // Update all users of sret parameter to extract value using extractvalue. for (Value::use_iterator UI = FirstCArg->use_begin(), UE = FirstCArg->use_end(); UI != UE; ) { User *U2 = *UI++; CallInst *C2 = dyn_cast<CallInst>(U2); if (C2 && (C2 == Call)) continue; GetElementPtrInst *UGEP = cast<GetElementPtrInst>(U2); ConstantInt *Idx = cast<ConstantInt>(UGEP->getOperand(2)); Value *GR = ExtractValueInst::Create(New, Idx->getZExtValue(), "evi", UGEP); while(!UGEP->use_empty()) { // isSafeToUpdateAllCallers has checked that all GEP uses are // LoadInsts LoadInst *L = cast<LoadInst>(*UGEP->use_begin()); L->replaceAllUsesWith(GR); L->eraseFromParent(); } UGEP->eraseFromParent(); continue; } Call->eraseFromParent(); } return NF_CGN; }
void ArrayObfs::ArrObfuscate ( Function *F ) { // Iterate the whole Function Function *f = F; for ( Function::iterator bb = f->begin(); bb != f->end(); ++bb ) { for ( BasicBlock::iterator inst = bb->begin(); inst != bb->end(); ) { if ( inst->getOpcode() == 29 ) // getelementptr { //errs() << "INST : " << *inst << "\n"; GetElementPtrInst *Ary = dyn_cast<GetElementPtrInst>(&*inst); Value *ptrVal = Ary->getOperand(0); Type *type = ptrVal->getType(); unsigned numOfOprand = Ary->getNumOperands(); unsigned lastOprand = numOfOprand - 1; // Check Type Array if ( PointerType *ptrType = dyn_cast<PointerType>( type ) ) { Type *elementType = ptrType->getElementType(); if ( elementType->isArrayTy() ) { // Skip if Index is a Variable if ( dyn_cast<ConstantInt>( Ary->getOperand( lastOprand ) ) ) { ////////////////////////////////////////////////////////////////////////////// // Do Real Stuff Value *oprand = Ary->getOperand( lastOprand ); Value *basePtr = Ary->getOperand( 0 ); APInt offset = dyn_cast<ConstantInt>(oprand)->getValue(); Value *prevPtr = basePtr; // Enter a Loop to Perform Random Obfuscation unsigned cnt = 100; // Prelog : Clone the Original Inst unsigned ObfsIdx = cryptoutils->get_uint64_t() & 0xffff; Value *newOprand = ConstantInt::get( oprand->getType(), ObfsIdx ); Instruction *gep = inst->clone(); gep->setOperand( lastOprand, newOprand ); gep->setOperand( 0, prevPtr ); gep->insertBefore( inst ); prevPtr = gep; offset = offset - ObfsIdx; // Create a Global Variable to Avoid Optimization Module *M = f->getParent(); Constant *initGV = ConstantInt::get( prevPtr->getType(), 0 ); GlobalVariable *gv = new GlobalVariable( *M, prevPtr->getType(), false, GlobalValue::CommonLinkage, initGV ); while ( cnt-- ) { // Iteratively Generate Obfuscated Code switch( cryptoutils->get_uint64_t() & 7 ) { // Random Indexing Obfuscation case 0 : case 1 : case 2 : { //errs() << "=> Random Index \n"; // Create New Instruction // Create Obfuscated New Oprand in ConstantInt Type unsigned ObfsIdx = cryptoutils->get_uint64_t() & 0xffff; Value *newOprand = ConstantInt::get( oprand->getType(), ObfsIdx ); // Create GetElementPtrInst Instruction GetElementPtrInst *gep = GetElementPtrInst::Create( prevPtr, newOprand, "", inst ); //Set prevPtr prevPtr = gep; //errs() << "Created : " << *prevPtr << "\n"; offset = offset - ObfsIdx; break; } // Ptr Dereference case 3 : case 4 : { //errs() << "=> Ptr Dereference \n"; Module *M = f->getParent(); Value *ONE = ConstantInt::get( Type::getInt32Ty( M->getContext() ), 1 ); Value *tmp = new AllocaInst( prevPtr->getType(), ONE, "", inst ); new StoreInst( prevPtr, tmp, inst ); prevPtr = new LoadInst( tmp, "", inst ); break; } // Ptr Value Transform case 5 : case 6 : case 7 : { //errs() << "=> Ptr Value Trans \n"; unsigned RandNum = cryptoutils->get_uint64_t(); Value *ObfsVal = ConstantInt::get( prevPtr->getType(), RandNum ); BinaryOperator *op = BinaryOperator::Create( Instruction::FAdd, prevPtr, ObfsVal, "", inst ); new StoreInst( prevPtr, gv, inst ); BinaryOperator::Create( Instruction::FSub, gv, ObfsVal, "", inst ); prevPtr = new LoadInst( gv, "", inst ); break; } } } // Postlog : Fix the Original Indexing { Value *fixOprand = ConstantInt::get( oprand->getType(), offset ); // Refine the Last Instruction GetElementPtrInst *gep = GetElementPtrInst::Create( prevPtr, fixOprand, "", inst ); // Fix the Relationship inst->replaceAllUsesWith( gep ); // Finally : Unlink This Instruction From Parent Instruction *DI = inst++; //errs() << "user_back : " << *(DI->user_back()) << "\n"; DI->removeFromParent(); } ////////////////////////////////////////////////////////////////////////////// // End : Variable Index } else { inst++; } // End : Check Array Type } else { inst++; } // End : Check Pointer Type } else { inst++; } // End : Check Opcode GetElementPtr } else { inst++; } } } ++ArrayMod; }
int qdp_jit_vec::vectorize_loads( std::vector<std::vector<Instruction*> >& load_instructions ) { DEBUG(dbgs() << "Vectorize loads, total of " << load_instructions.size() << "\n"); //std::vector<std::pair<Value*,Value*> > scalar_vector_loads; scalar_vector_pairs.clear(); if (load_instructions.empty()) return 0; int load_vec_elem = 0; for( std::vector<Instruction*>& VI : load_instructions ) { DEBUG(dbgs() << "Processing vector of loads number " << load_vec_elem++ << "\n"); assert( VI.size() == vec_len && "length of vector of loads does not match vec_len" ); int loads_consec = true; uint64_t lo,hi; bool first = true; for( Instruction* I : VI ) { GetElementPtrInst* GEP; if ((GEP = dyn_cast<GetElementPtrInst>(I->getOperand(0)))) { if (first) { ConstantInt * CI; if ((CI = dyn_cast<ConstantInt>(GEP->getOperand(1)))) { lo = CI->getZExtValue(); hi = lo+1; first=false; } else { DEBUG(dbgs() << "First load in the chain: Operand of GEP not a ConstantInt" << *GEP->getOperand(1) << "\n"); assert( 0 && "First load in the chain: Operand of GEP not a ConstantInt\n"); exit(0); } } else { ConstantInt * CI; if ((CI = dyn_cast<ConstantInt>(GEP->getOperand(1)))) { if (hi != CI->getZExtValue()) { DEBUG(dbgs() << "Loads not consecutive lo=" << lo << " hi=" << hi << " this=" << CI->getZExtValue() << "\n"); loads_consec = false; } else { hi++; } } } } else { DEBUG(dbgs() << "Operand of load not a GEP " << *I->getOperand(0) << "\n"); assert( 0 && "Operand of load not a GEP" ); exit(0); loads_consec = false; } } if (loads_consec) { DEBUG(dbgs() << "Loads consecuetive\n"); LoadInst* LI = cast<LoadInst>(VI.at(0)); GetElementPtrInst* GEP = cast<GetElementPtrInst>(LI->getOperand(0)); Instruction* GEPcl = clone_with_operands(GEP); unsigned AS = LI->getPointerAddressSpace(); VectorType *VecTy = VectorType::get( LI->getType() , vec_len ); unsigned bitwidth = LI->getType()->getPrimitiveSizeInBits(); unsigned bytewidth = bitwidth == 1 ? 1 : bitwidth/8; DEBUG(dbgs() << "bit/byte width of load instr trype: " << bitwidth << "/" << bytewidth << "\n"); //Builder->SetInsertPoint( GEP ); Value *VecPtr = Builder->CreateBitCast(GEPcl,VecTy->getPointerTo(AS)); //Value *VecLoad = Builder->CreateLoad( VecPtr ); unsigned align = lo % vec_len == 0 ? bytewidth * vec_len : bytewidth; Value *VecLoad = Builder->CreateAlignedLoad( VecPtr , align ); //DEBUG(dbgs() << "created vector load: " << *VecLoad << "\n"); //function->dump(); // unsigned AS = LI->getPointerAddressSpace(); // VectorType *VecTy = VectorType::get( LI->getType() , vec_len ); // Builder->SetInsertPoint( LI ); // Value *VecPtr = Builder->CreateBitCast(LI->getPointerOperand(),VecTy->getPointerTo(AS)); // Value *VecLoad = Builder->CreateLoad( VecPtr ); scalar_vector_pairs.push_back( std::make_pair( VI.at(0) , VecLoad ) ); } else { DEBUG(dbgs() << "Loads not consecutive:\n"); for (Value* V: VI) { DEBUG(dbgs() << *V << "\n"); } //Instruction* I = dyn_cast<Instruction>(VI.back()->getNextNode()); //DEBUG(dbgs() << *I << "\n"); //Builder->SetInsertPoint( VI.at(0) ); std::vector<Instruction*> VIcl; for( Instruction* I : VI ) { VIcl.push_back( clone_with_operands(I) ); } VectorType *VecTy = VectorType::get( VI.at(0)->getType() , vec_len ); Value *Vec = UndefValue::get(VecTy); int i=0; for( Instruction* I : VIcl ) { Vec = Builder->CreateInsertElement(Vec, I, Builder->getInt32(i++)); } scalar_vector_pairs.push_back( std::make_pair( VI.at(0) , Vec ) ); } } //vectorize_all_uses( scalar_vector_loads ); DEBUG(dbgs() << "Searching for the stores:\n"); //function->dump(); // // Vectorize all StoreInst reachable by the first load of each vector of loads // { SetVector<Instruction*> to_visit; SetVector<Instruction*> stores_processed; for( std::vector<Instruction*>& VI : load_instructions ) { to_visit.insert(VI.at(0)); } while (!to_visit.empty()) { Instruction* I = to_visit.back(); to_visit.pop_back(); DEBUG(dbgs() << "visiting " << *I << "\n"); if (StoreInst* SI = dyn_cast<StoreInst>(I)) { if (!stores_processed.count(SI)) { get_vector_version( SI ); stores_processed.insert( SI ); } } else { for (Use &U : I->uses()) { Value* V = U.getUser(); to_visit.insert(cast<Instruction>(V)); } } } } // DEBUG(dbgs() << "After vectorizing the stores\n"); // function->dump(); // // Mark all stores as being processed // SetVector<Instruction*> to_visit; for( std::vector<Instruction*>& VI : load_instructions ) { for( Instruction* I : VI ) { to_visit.insert(I); if (GetElementPtrInst* GEP = dyn_cast<GetElementPtrInst>(I->getOperand(0))) { for_erasure.insert(GEP); } } } while (!to_visit.empty()) { Instruction* I = to_visit.back(); to_visit.pop_back(); for_erasure.insert(I); if (StoreInst* SI = dyn_cast<StoreInst>(I)) { stores_processed.insert(SI); if (GetElementPtrInst* GEP = dyn_cast<GetElementPtrInst>(SI->getOperand(1))) { for_erasure.insert(GEP); } } else { for (Use &U : I->uses()) { Value* V = U.getUser(); to_visit.insert(cast<Instruction>(V)); } } } DEBUG(dbgs() << "----------------------------------------\n"); DEBUG(dbgs() << "After vectorize_loads\n"); //function->dump(); return 0; }