+ I != E; ++I) {
+ isSafeUseOfAllocation(cast<Instruction>(*I), AI, Info);
+ if (Info.isUnsafe) {
+ DOUT << "Cannot transform: " << *AI << " due to user: " << **I;
+ return 0;
+ }
+ }
+
+ // Okay, we know all the users are promotable. If the aggregate is a memcpy
+ // source and destination, we have to be careful. In particular, the memcpy
+ // could be moving around elements that live in structure padding of the LLVM
+ // types, but may actually be used. In these cases, we refuse to promote the
+ // struct.
+ if (Info.isMemCpySrc && Info.isMemCpyDst &&
+ HasPadding(AI->getType()->getElementType(), getAnalysis<TargetData>()))
+ return 0;
+
+ // If we require cleanup, return 1, otherwise return 3.
+ return Info.needsCanon ? 1 : 3;
+}
+
+/// CanonicalizeAllocaUsers - If SROA reported that it can promote the specified
+/// allocation, but only if cleaned up, perform the cleanups required.
+void SROA::CanonicalizeAllocaUsers(AllocationInst *AI) {
+ // At this point, we know that the end result will be SROA'd and promoted, so
+ // we can insert ugly code if required so long as sroa+mem2reg will clean it
+ // up.
+ for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();
+ UI != E; ) {
+ GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(*UI++);
+ if (!GEPI) continue;
+ gep_type_iterator I = gep_type_begin(GEPI);
+ ++I;
+
+ if (const ArrayType *AT = dyn_cast<ArrayType>(*I)) {
+ uint64_t NumElements = AT->getNumElements();
+
+ if (!isa<ConstantInt>(I.getOperand())) {
+ if (NumElements == 1) {
+ GEPI->setOperand(2, Constant::getNullValue(Type::Int32Ty));
+ } else {
+ assert(NumElements == 2 && "Unhandled case!");
+ // All users of the GEP must be loads. At each use of the GEP, insert
+ // two loads of the appropriate indexed GEP and select between them.
+ Value *IsOne = new ICmpInst(ICmpInst::ICMP_NE, I.getOperand(),
+ Constant::getNullValue(I.getOperand()->getType()),
+ "isone", GEPI);
+ // Insert the new GEP instructions, which are properly indexed.
+ SmallVector<Value*, 8> Indices(GEPI->op_begin()+1, GEPI->op_end());
+ Indices[1] = Constant::getNullValue(Type::Int32Ty);
+ Value *ZeroIdx = GetElementPtrInst::Create(GEPI->getOperand(0),
+ Indices.begin(),
+ Indices.end(),
+ GEPI->getName()+".0", GEPI);
+ Indices[1] = ConstantInt::get(Type::Int32Ty, 1);
+ Value *OneIdx = GetElementPtrInst::Create(GEPI->getOperand(0),
+ Indices.begin(),
+ Indices.end(),
+ GEPI->getName()+".1", GEPI);
+ // Replace all loads of the variable index GEP with loads from both
+ // indexes and a select.
+ while (!GEPI->use_empty()) {
+ LoadInst *LI = cast<LoadInst>(GEPI->use_back());
+ Value *Zero = new LoadInst(ZeroIdx, LI->getName()+".0", LI);
+ Value *One = new LoadInst(OneIdx , LI->getName()+".1", LI);
+ Value *R = SelectInst::Create(IsOne, One, Zero, LI->getName(), LI);
+ LI->replaceAllUsesWith(R);
+ LI->eraseFromParent();
+ }
+ GEPI->eraseFromParent();
+ }
+ }
+ }
+ }
+}
+
+/// MergeInType - Add the 'In' type to the accumulated type so far. If the
+/// types are incompatible, return true, otherwise update Accum and return
+/// false.
+///
+/// There are three cases we handle here:
+/// 1) An effectively-integer union, where the pieces are stored into as
+/// smaller integers (common with byte swap and other idioms).
+/// 2) A union of vector types of the same size and potentially its elements.
+/// Here we turn element accesses into insert/extract element operations.
+/// 3) A union of scalar types, such as int/float or int/pointer. Here we
+/// merge together into integers, allowing the xform to work with #1 as
+/// well.
+static bool MergeInType(const Type *In, const Type *&Accum,
+ const TargetData &TD) {
+ // If this is our first type, just use it.
+ const VectorType *PTy;
+ if (Accum == Type::VoidTy || In == Accum) {
+ Accum = In;
+ } else if (In == Type::VoidTy) {
+ // Noop.
+ } else if (In->isInteger() && Accum->isInteger()) { // integer union.
+ // Otherwise pick whichever type is larger.
+ if (cast<IntegerType>(In)->getBitWidth() >
+ cast<IntegerType>(Accum)->getBitWidth())
+ Accum = In;
+ } else if (isa<PointerType>(In) && isa<PointerType>(Accum)) {
+ // Pointer unions just stay as one of the pointers.
+ } else if (isa<VectorType>(In) || isa<VectorType>(Accum)) {
+ if ((PTy = dyn_cast<VectorType>(Accum)) &&
+ PTy->getElementType() == In) {
+ // Accum is a vector, and we are accessing an element: ok.
+ } else if ((PTy = dyn_cast<VectorType>(In)) &&
+ PTy->getElementType() == Accum) {
+ // In is a vector, and accum is an element: ok, remember In.
+ Accum = In;
+ } else if ((PTy = dyn_cast<VectorType>(In)) && isa<VectorType>(Accum) &&
+ PTy->getBitWidth() == cast<VectorType>(Accum)->getBitWidth()) {
+ // Two vectors of the same size: keep Accum.
+ } else {
+ // Cannot insert an short into a <4 x int> or handle
+ // <2 x int> -> <4 x int>
+ return true;
+ }
+ } else {
+ // Pointer/FP/Integer unions merge together as integers.
+ switch (Accum->getTypeID()) {
+ case Type::PointerTyID: Accum = TD.getIntPtrType(); break;
+ case Type::FloatTyID: Accum = Type::Int32Ty; break;
+ case Type::DoubleTyID: Accum = Type::Int64Ty; break;
+ case Type::X86_FP80TyID: return true;
+ case Type::FP128TyID: return true;
+ case Type::PPC_FP128TyID: return true;
+ default:
+ assert(Accum->isInteger() && "Unknown FP type!");
+ break;
+ }
+
+ switch (In->getTypeID()) {
+ case Type::PointerTyID: In = TD.getIntPtrType(); break;
+ case Type::FloatTyID: In = Type::Int32Ty; break;
+ case Type::DoubleTyID: In = Type::Int64Ty; break;
+ case Type::X86_FP80TyID: return true;
+ case Type::FP128TyID: return true;
+ case Type::PPC_FP128TyID: return true;
+ default:
+ assert(In->isInteger() && "Unknown FP type!");
+ break;
+ }
+ return MergeInType(In, Accum, TD);
+ }
+ return false;
+}
+
+/// getUIntAtLeastAsBigAs - Return an unsigned integer type that is at least
+/// as big as the specified type. If there is no suitable type, this returns
+/// null.
+const Type *getUIntAtLeastAsBigAs(unsigned NumBits) {
+ if (NumBits > 64) return 0;
+ if (NumBits > 32) return Type::Int64Ty;
+ if (NumBits > 16) return Type::Int32Ty;
+ if (NumBits > 8) return Type::Int16Ty;
+ return Type::Int8Ty;
+}
+
+/// CanConvertToScalar - V is a pointer. If we can convert the pointee to a
+/// single scalar integer type, return that type. Further, if the use is not
+/// a completely trivial use that mem2reg could promote, set IsNotTrivial. If
+/// there are no uses of this pointer, return Type::VoidTy to differentiate from
+/// failure.
+///
+const Type *SROA::CanConvertToScalar(Value *V, bool &IsNotTrivial) {
+ const Type *UsedType = Type::VoidTy; // No uses, no forced type.
+ const TargetData &TD = getAnalysis<TargetData>();
+ const PointerType *PTy = cast<PointerType>(V->getType());
+
+ for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI!=E; ++UI) {
+ Instruction *User = cast<Instruction>(*UI);
+
+ if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
+ // FIXME: Loads of a first class aggregrate value could be converted to a
+ // series of loads and insertvalues
+ if (!LI->getType()->isSingleValueType())
+ return 0;
+
+ if (MergeInType(LI->getType(), UsedType, TD))
+ return 0;
+
+ } else if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
+ // Storing the pointer, not into the value?
+ if (SI->getOperand(0) == V) return 0;
+
+ // FIXME: Stores of a first class aggregrate value could be converted to a
+ // series of extractvalues and stores
+ if (!SI->getOperand(0)->getType()->isSingleValueType())
+ return 0;
+
+ // NOTE: We could handle storing of FP imms into integers here!
+
+ if (MergeInType(SI->getOperand(0)->getType(), UsedType, TD))
+ return 0;
+ } else if (BitCastInst *CI = dyn_cast<BitCastInst>(User)) {
+ IsNotTrivial = true;
+ const Type *SubTy = CanConvertToScalar(CI, IsNotTrivial);
+ if (!SubTy || MergeInType(SubTy, UsedType, TD)) return 0;
+ } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) {
+ // Check to see if this is stepping over an element: GEP Ptr, int C
+ if (GEP->getNumOperands() == 2 && isa<ConstantInt>(GEP->getOperand(1))) {
+ unsigned Idx = cast<ConstantInt>(GEP->getOperand(1))->getZExtValue();
+ unsigned ElSize = TD.getABITypeSize(PTy->getElementType());
+ unsigned BitOffset = Idx*ElSize*8;
+ if (BitOffset > 64 || !isPowerOf2_32(ElSize)) return 0;
+
+ IsNotTrivial = true;
+ const Type *SubElt = CanConvertToScalar(GEP, IsNotTrivial);
+ if (SubElt == 0) return 0;
+ if (SubElt != Type::VoidTy && SubElt->isInteger()) {
+ const Type *NewTy =
+ getUIntAtLeastAsBigAs(TD.getABITypeSizeInBits(SubElt)+BitOffset);
+ if (NewTy == 0 || MergeInType(NewTy, UsedType, TD)) return 0;
+ continue;
+ }
+ } else if (GEP->getNumOperands() == 3 &&
+ isa<ConstantInt>(GEP->getOperand(1)) &&
+ isa<ConstantInt>(GEP->getOperand(2)) &&
+ cast<ConstantInt>(GEP->getOperand(1))->isZero()) {
+ // We are stepping into an element, e.g. a structure or an array:
+ // GEP Ptr, int 0, uint C
+ const Type *AggTy = PTy->getElementType();
+ unsigned Idx = cast<ConstantInt>(GEP->getOperand(2))->getZExtValue();
+
+ if (const ArrayType *ATy = dyn_cast<ArrayType>(AggTy)) {
+ if (Idx >= ATy->getNumElements()) return 0; // Out of range.
+ } else if (const VectorType *VectorTy = dyn_cast<VectorType>(AggTy)) {
+ // Getting an element of the vector.
+ if (Idx >= VectorTy->getNumElements()) return 0; // Out of range.
+
+ // Merge in the vector type.
+ if (MergeInType(VectorTy, UsedType, TD)) return 0;
+
+ const Type *SubTy = CanConvertToScalar(GEP, IsNotTrivial);
+ if (SubTy == 0) return 0;
+
+ if (SubTy != Type::VoidTy && MergeInType(SubTy, UsedType, TD))
+ return 0;
+
+ // We'll need to change this to an insert/extract element operation.
+ IsNotTrivial = true;
+ continue; // Everything looks ok
+
+ } else if (isa<StructType>(AggTy)) {
+ // Structs are always ok.
+ } else {
+ return 0;
+ }
+ const Type *NTy = getUIntAtLeastAsBigAs(TD.getABITypeSizeInBits(AggTy));
+ if (NTy == 0 || MergeInType(NTy, UsedType, TD)) return 0;
+ const Type *SubTy = CanConvertToScalar(GEP, IsNotTrivial);
+ if (SubTy == 0) return 0;
+ if (SubTy != Type::VoidTy && MergeInType(SubTy, UsedType, TD))
+ return 0;
+ continue; // Everything looks ok
+ }
+ return 0;
+ } else {
+ // Cannot handle this!
+ return 0;
+ }
+ }
+
+ return UsedType;
+}
+
+/// ConvertToScalar - The specified alloca passes the CanConvertToScalar
+/// predicate and is non-trivial. Convert it to something that can be trivially
+/// promoted into a register by mem2reg.
+void SROA::ConvertToScalar(AllocationInst *AI, const Type *ActualTy) {
+ DOUT << "CONVERT TO SCALAR: " << *AI << " TYPE = "
+ << *ActualTy << "\n";
+ ++NumConverted;
+
+ BasicBlock *EntryBlock = AI->getParent();
+ assert(EntryBlock == &EntryBlock->getParent()->getEntryBlock() &&
+ "Not in the entry block!");
+ EntryBlock->getInstList().remove(AI); // Take the alloca out of the program.
+
+ // Create and insert the alloca.
+ AllocaInst *NewAI = new AllocaInst(ActualTy, 0, AI->getName(),
+ EntryBlock->begin());
+ ConvertUsesToScalar(AI, NewAI, 0);
+ delete AI;
+}
+
+
+/// ConvertUsesToScalar - Convert all of the users of Ptr to use the new alloca
+/// directly. This happens when we are converting an "integer union" to a
+/// single integer scalar, or when we are converting a "vector union" to a
+/// vector with insert/extractelement instructions.
+///
+/// Offset is an offset from the original alloca, in bits that need to be
+/// shifted to the right. By the end of this, there should be no uses of Ptr.
+void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, unsigned Offset) {
+ while (!Ptr->use_empty()) {
+ Instruction *User = cast<Instruction>(Ptr->use_back());
+
+ if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
+ Value *NV = ConvertUsesOfLoadToScalar(LI, NewAI, Offset);
+ LI->replaceAllUsesWith(NV);
+ LI->eraseFromParent();
+ } else if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
+ assert(SI->getOperand(0) != Ptr && "Consistency error!");
+
+ Value *SV = ConvertUsesOfStoreToScalar(SI, NewAI, Offset);
+ new StoreInst(SV, NewAI, SI);
+ SI->eraseFromParent();
+
+ } else if (BitCastInst *CI = dyn_cast<BitCastInst>(User)) {
+ ConvertUsesToScalar(CI, NewAI, Offset);
+ CI->eraseFromParent();
+ } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) {
+ const PointerType *AggPtrTy =
+ cast<PointerType>(GEP->getOperand(0)->getType());
+ const TargetData &TD = getAnalysis<TargetData>();
+ unsigned AggSizeInBits =
+ TD.getABITypeSizeInBits(AggPtrTy->getElementType());
+
+ // Check to see if this is stepping over an element: GEP Ptr, int C
+ unsigned NewOffset = Offset;
+ if (GEP->getNumOperands() == 2) {
+ unsigned Idx = cast<ConstantInt>(GEP->getOperand(1))->getZExtValue();
+ unsigned BitOffset = Idx*AggSizeInBits;
+
+ NewOffset += BitOffset;
+ } else if (GEP->getNumOperands() == 3) {
+ // We know that operand #2 is zero.
+ unsigned Idx = cast<ConstantInt>(GEP->getOperand(2))->getZExtValue();
+ const Type *AggTy = AggPtrTy->getElementType();
+ if (const SequentialType *SeqTy = dyn_cast<SequentialType>(AggTy)) {
+ unsigned ElSizeBits =
+ TD.getABITypeSizeInBits(SeqTy->getElementType());
+
+ NewOffset += ElSizeBits*Idx;
+ } else if (const StructType *STy = dyn_cast<StructType>(AggTy)) {
+ unsigned EltBitOffset =
+ TD.getStructLayout(STy)->getElementOffsetInBits(Idx);
+
+ NewOffset += EltBitOffset;
+ } else {
+ assert(0 && "Unsupported operation!");
+ abort();
+ }
+ } else {
+ assert(0 && "Unsupported operation!");
+ abort();
+ }
+ ConvertUsesToScalar(GEP, NewAI, NewOffset);
+ GEP->eraseFromParent();
+ } else {
+ assert(0 && "Unsupported operation!");
+ abort();
+ }
+ }
+}
+
+/// ConvertUsesOfLoadToScalar - Convert all of the users the specified load to
+/// use the new alloca directly, returning the value that should replace the
+/// load. This happens when we are converting an "integer union" to a
+/// single integer scalar, or when we are converting a "vector union" to a
+/// vector with insert/extractelement instructions.
+///
+/// Offset is an offset from the original alloca, in bits that need to be
+/// shifted to the right. By the end of this, there should be no uses of Ptr.
+Value *SROA::ConvertUsesOfLoadToScalar(LoadInst *LI, AllocaInst *NewAI,
+ unsigned Offset) {
+ // The load is a bit extract from NewAI shifted right by Offset bits.
+ Value *NV = new LoadInst(NewAI, LI->getName(), LI);
+
+ if (NV->getType() == LI->getType() && Offset == 0) {
+ // We win, no conversion needed.
+ return NV;
+ }
+
+ // If the result type of the 'union' is a pointer, then this must be ptr->ptr
+ // cast. Anything else would result in NV being an integer.
+ if (isa<PointerType>(NV->getType())) {
+ assert(isa<PointerType>(LI->getType()));
+ return new BitCastInst(NV, LI->getType(), LI->getName(), LI);
+ }
+
+ if (const VectorType *VTy = dyn_cast<VectorType>(NV->getType())) {
+ // If the result alloca is a vector type, this is either an element
+ // access or a bitcast to another vector type.
+ if (isa<VectorType>(LI->getType()))
+ return new BitCastInst(NV, LI->getType(), LI->getName(), LI);
+
+ // Otherwise it must be an element access.
+ const TargetData &TD = getAnalysis<TargetData>();
+ unsigned Elt = 0;
+ if (Offset) {
+ unsigned EltSize = TD.getABITypeSizeInBits(VTy->getElementType());
+ Elt = Offset/EltSize;
+ Offset -= EltSize*Elt;
+ }
+ NV = new ExtractElementInst(NV, ConstantInt::get(Type::Int32Ty, Elt),
+ "tmp", LI);
+
+ // If we're done, return this element.
+ if (NV->getType() == LI->getType() && Offset == 0)
+ return NV;
+ }
+
+ const IntegerType *NTy = cast<IntegerType>(NV->getType());
+
+ // If this is a big-endian system and the load is narrower than the
+ // full alloca type, we need to do a shift to get the right bits.
+ int ShAmt = 0;
+ const TargetData &TD = getAnalysis<TargetData>();
+ if (TD.isBigEndian()) {
+ // On big-endian machines, the lowest bit is stored at the bit offset
+ // from the pointer given by getTypeStoreSizeInBits. This matters for
+ // integers with a bitwidth that is not a multiple of 8.
+ ShAmt = TD.getTypeStoreSizeInBits(NTy) -
+ TD.getTypeStoreSizeInBits(LI->getType()) - Offset;
+ } else {
+ ShAmt = Offset;
+ }
+
+ // Note: we support negative bitwidths (with shl) which are not defined.
+ // We do this to support (f.e.) loads off the end of a structure where
+ // only some bits are used.
+ if (ShAmt > 0 && (unsigned)ShAmt < NTy->getBitWidth())
+ NV = BinaryOperator::CreateLShr(NV,
+ ConstantInt::get(NV->getType(),ShAmt),
+ LI->getName(), LI);
+ else if (ShAmt < 0 && (unsigned)-ShAmt < NTy->getBitWidth())
+ NV = BinaryOperator::CreateShl(NV,
+ ConstantInt::get(NV->getType(),-ShAmt),
+ LI->getName(), LI);
+
+ // Finally, unconditionally truncate the integer to the right width.
+ unsigned LIBitWidth = TD.getTypeSizeInBits(LI->getType());
+ if (LIBitWidth < NTy->getBitWidth())
+ NV = new TruncInst(NV, IntegerType::get(LIBitWidth),
+ LI->getName(), LI);
+
+ // If the result is an integer, this is a trunc or bitcast.
+ if (isa<IntegerType>(LI->getType())) {
+ // Should be done.
+ } else if (LI->getType()->isFloatingPoint()) {
+ // Just do a bitcast, we know the sizes match up.
+ NV = new BitCastInst(NV, LI->getType(), LI->getName(), LI);
+ } else {
+ // Otherwise must be a pointer.
+ NV = new IntToPtrInst(NV, LI->getType(), LI->getName(), LI);
+ }
+ assert(NV->getType() == LI->getType() && "Didn't convert right?");
+ return NV;
+}
+
+
+/// ConvertUsesOfStoreToScalar - Convert the specified store to a load+store
+/// pair of the new alloca directly, returning the value that should be stored
+/// to the alloca. This happens when we are converting an "integer union" to a
+/// single integer scalar, or when we are converting a "vector union" to a
+/// vector with insert/extractelement instructions.
+///
+/// Offset is an offset from the original alloca, in bits that need to be
+/// shifted to the right. By the end of this, there should be no uses of Ptr.
+Value *SROA::ConvertUsesOfStoreToScalar(StoreInst *SI, AllocaInst *NewAI,
+ unsigned Offset) {
+
+ // Convert the stored type to the actual type, shift it left to insert
+ // then 'or' into place.
+ Value *SV = SI->getOperand(0);
+ const Type *AllocaType = NewAI->getType()->getElementType();
+ if (SV->getType() == AllocaType && Offset == 0) {
+ // All is well.
+ } else if (const VectorType *PTy = dyn_cast<VectorType>(AllocaType)) {
+ Value *Old = new LoadInst(NewAI, NewAI->getName()+".in", SI);
+
+ // If the result alloca is a vector type, this is either an element
+ // access or a bitcast to another vector type.
+ if (isa<VectorType>(SV->getType())) {
+ SV = new BitCastInst(SV, AllocaType, SV->getName(), SI);
+ } else {
+ // Must be an element insertion.
+ const TargetData &TD = getAnalysis<TargetData>();
+ unsigned Elt = Offset/TD.getABITypeSizeInBits(PTy->getElementType());
+ SV = InsertElementInst::Create(Old, SV,
+ ConstantInt::get(Type::Int32Ty, Elt),
+ "tmp", SI);
+ }
+ } else if (isa<PointerType>(AllocaType)) {
+ // If the alloca type is a pointer, then all the elements must be
+ // pointers.
+ if (SV->getType() != AllocaType)
+ SV = new BitCastInst(SV, AllocaType, SV->getName(), SI);
+ } else {
+ Value *Old = new LoadInst(NewAI, NewAI->getName()+".in", SI);
+
+ // If SV is a float, convert it to the appropriate integer type.
+ // If it is a pointer, do the same, and also handle ptr->ptr casts
+ // here.
+ const TargetData &TD = getAnalysis<TargetData>();
+ unsigned SrcWidth = TD.getTypeSizeInBits(SV->getType());
+ unsigned DestWidth = TD.getTypeSizeInBits(AllocaType);
+ unsigned SrcStoreWidth = TD.getTypeStoreSizeInBits(SV->getType());
+ unsigned DestStoreWidth = TD.getTypeStoreSizeInBits(AllocaType);
+ if (SV->getType()->isFloatingPoint())
+ SV = new BitCastInst(SV, IntegerType::get(SrcWidth),
+ SV->getName(), SI);
+ else if (isa<PointerType>(SV->getType()))
+ SV = new PtrToIntInst(SV, TD.getIntPtrType(), SV->getName(), SI);
+
+ // Always zero extend the value if needed.
+ if (SV->getType() != AllocaType)
+ SV = new ZExtInst(SV, AllocaType, SV->getName(), SI);
+
+ // If this is a big-endian system and the store is narrower than the
+ // full alloca type, we need to do a shift to get the right bits.
+ int ShAmt = 0;
+ if (TD.isBigEndian()) {
+ // On big-endian machines, the lowest bit is stored at the bit offset
+ // from the pointer given by getTypeStoreSizeInBits. This matters for
+ // integers with a bitwidth that is not a multiple of 8.
+ ShAmt = DestStoreWidth - SrcStoreWidth - Offset;
+ } else {
+ ShAmt = Offset;
+ }
+
+ // Note: we support negative bitwidths (with shr) which are not defined.
+ // We do this to support (f.e.) stores off the end of a structure where
+ // only some bits in the structure are set.
+ APInt Mask(APInt::getLowBitsSet(DestWidth, SrcWidth));
+ if (ShAmt > 0 && (unsigned)ShAmt < DestWidth) {
+ SV = BinaryOperator::CreateShl(SV,
+ ConstantInt::get(SV->getType(), ShAmt),
+ SV->getName(), SI);
+ Mask <<= ShAmt;
+ } else if (ShAmt < 0 && (unsigned)-ShAmt < DestWidth) {
+ SV = BinaryOperator::CreateLShr(SV,
+ ConstantInt::get(SV->getType(),-ShAmt),
+ SV->getName(), SI);
+ Mask = Mask.lshr(ShAmt);
+ }
+
+ // Mask out the bits we are about to insert from the old value, and or
+ // in the new bits.
+ if (SrcWidth != DestWidth) {
+ assert(DestWidth > SrcWidth);
+ Old = BinaryOperator::CreateAnd(Old, ConstantInt::get(~Mask),
+ Old->getName()+".mask", SI);
+ SV = BinaryOperator::CreateOr(Old, SV, SV->getName()+".ins", SI);
+ }
+ }
+ return SV;
+}
+
+
+
+/// PointsToConstantGlobal - Return true if V (possibly indirectly) points to
+/// some part of a constant global variable. This intentionally only accepts
+/// constant expressions because we don't can't rewrite arbitrary instructions.
+static bool PointsToConstantGlobal(Value *V) {
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
+ return GV->isConstant();
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+ if (CE->getOpcode() == Instruction::BitCast ||
+ CE->getOpcode() == Instruction::GetElementPtr)
+ return PointsToConstantGlobal(CE->getOperand(0));
+ return false;
+}
+
+/// isOnlyCopiedFromConstantGlobal - Recursively walk the uses of a (derived)
+/// pointer to an alloca. Ignore any reads of the pointer, return false if we
+/// see any stores or other unknown uses. If we see pointer arithmetic, keep
+/// track of whether it moves the pointer (with isOffset) but otherwise traverse
+/// the uses. If we see a memcpy/memmove that targets an unoffseted pointer to
+/// the alloca, and if the source pointer is a pointer to a constant global, we
+/// can optimize this.
+static bool isOnlyCopiedFromConstantGlobal(Value *V, Instruction *&TheCopy,
+ bool isOffset) {
+ for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI!=E; ++UI) {
+ if (isa<LoadInst>(*UI)) {
+ // Ignore loads, they are always ok.
+ continue;
+ }
+ if (BitCastInst *BCI = dyn_cast<BitCastInst>(*UI)) {
+ // If uses of the bitcast are ok, we are ok.
+ if (!isOnlyCopiedFromConstantGlobal(BCI, TheCopy, isOffset))
+ return false;
+ continue;