/// CheckAggExprForMemSetUse - If the initializer is large and has a lot of /// zeros in it, emit a memset and avoid storing the individual zeros. /// static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E, CodeGenFunction &CGF) { // If the slot is already known to be zeroed, nothing to do. Don't mess with // volatile stores. if (Slot.isZeroed() || Slot.isVolatile() || Slot.getAddr() == 0) return; // If the type is 16-bytes or smaller, prefer individual stores over memset. std::pair<uint64_t, unsigned> TypeInfo = CGF.getContext().getTypeInfo(E->getType()); if (TypeInfo.first/8 <= 16) return; // Check to see if over 3/4 of the initializer are known to be zero. If so, // we prefer to emit memset + individual stores for the rest. uint64_t NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF); if (NumNonZeroBytes*4 > TypeInfo.first/8) return; // Okay, it seems like a good idea to use an initial memset, emit the call. llvm::Constant *SizeVal = CGF.Builder.getInt64(TypeInfo.first/8); unsigned Align = TypeInfo.second/8; llvm::Value *Loc = Slot.getAddr(); const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); Loc = CGF.Builder.CreateBitCast(Loc, BP); CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal, Align, false); // Tell the AggExprEmitter that the slot is known zero. Slot.setZeroed(); }
/// CheckAggExprForMemSetUse - If the initializer is large and has a lot of /// zeros in it, emit a memset and avoid storing the individual zeros. /// static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E, CodeGenFunction &CGF) { // If the slot is already known to be zeroed, nothing to do. Don't mess with // volatile stores. if (Slot.isZeroed() || Slot.isVolatile() || Slot.getAddr() == 0) return; // C++ objects with a user-declared constructor don't need zero'ing. if (CGF.getContext().getLangOptions().CPlusPlus) if (const RecordType *RT = CGF.getContext() .getBaseElementType(E->getType())->getAs<RecordType>()) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); if (RD->hasUserDeclaredConstructor()) return; } // If the type is 16-bytes or smaller, prefer individual stores over memset. std::pair<CharUnits, CharUnits> TypeInfo = CGF.getContext().getTypeInfoInChars(E->getType()); if (TypeInfo.first <= CharUnits::fromQuantity(16)) return; // Check to see if over 3/4 of the initializer are known to be zero. If so, // we prefer to emit memset + individual stores for the rest. CharUnits NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF); if (NumNonZeroBytes*4 > TypeInfo.first) return; // Okay, it seems like a good idea to use an initial memset, emit the call. llvm::Constant *SizeVal = CGF.Builder.getInt64(TypeInfo.first.getQuantity()); CharUnits Align = TypeInfo.second; llvm::Value *Loc = Slot.getAddr(); llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); Loc = CGF.Builder.CreateBitCast(Loc, BP); CGF.Builder.CreateMemSet(Loc, CGF.Builder.getInt8(0), SizeVal, Align.getQuantity(), false); // Tell the AggExprEmitter that the slot is known zero. Slot.setZeroed(); }