diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index ce646a172b4..c1c8e0387cf 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -1423,6 +1423,31 @@ Value *SROA::ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType, V = Builder.CreateBitCast(V, ToType, "tmp"); return V; } + + // If ToType is a first class aggregate, extract out each of the pieces and + // use insertvalue's to form the FCA. + if (const StructType *ST = dyn_cast(ToType)) { + const StructLayout &Layout = *TD->getStructLayout(ST); + Value *Res = UndefValue::get(ST); + for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { + Value *Elt = ConvertScalar_ExtractValue(FromVal, ST->getElementType(i), + Offset+Layout.getElementOffset(i), + Builder); + Res = Builder.CreateInsertValue(Res, Elt, i, "tmp"); + } + return Res; + } + + if (const ArrayType *AT = dyn_cast(ToType)) { + uint64_t EltSize = TD->getTypePaddedSizeInBits(AT->getElementType()); + Value *Res = UndefValue::get(AT); + for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) { + Value *Elt = ConvertScalar_ExtractValue(FromVal, AT->getElementType(), + Offset+i*EltSize, Builder); + Res = Builder.CreateInsertValue(Res, Elt, i, "tmp"); + } + return Res; + } // Otherwise, this must be a union that was converted to an integer value. const IntegerType *NTy = cast(FromVal->getType()); @@ -1444,9 +1469,11 @@ Value *SROA::ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType, // 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()) - FromVal = Builder.CreateLShr(FromVal, ConstantInt::get(FromVal->getType(), ShAmt), "tmp"); + FromVal = Builder.CreateLShr(FromVal, ConstantInt::get(FromVal->getType(), + ShAmt), "tmp"); else if (ShAmt < 0 && (unsigned)-ShAmt < NTy->getBitWidth()) - FromVal = Builder.CreateShl(FromVal, ConstantInt::get(FromVal->getType(), -ShAmt), "tmp"); + FromVal = Builder.CreateShl(FromVal, ConstantInt::get(FromVal->getType(), + -ShAmt), "tmp"); // Finally, unconditionally truncate the integer to the right width. unsigned LIBitWidth = TD->getTypeSizeInBits(ToType); diff --git a/test/Transforms/ScalarRepl/sroa-fca.ll b/test/Transforms/ScalarRepl/sroa-fca.ll index a7ec3a11d73..1bfdaccc0d8 100644 --- a/test/Transforms/ScalarRepl/sroa-fca.ll +++ b/test/Transforms/ScalarRepl/sroa-fca.ll @@ -10,3 +10,12 @@ define i64 @test({i32, i32} %A) { ret i64 %Q } +define {i32,i32} @test2(i64 %A) { + %X = alloca i64 + %Y = bitcast i64* %X to {i32,i32}* + store i64 %A, i64* %X + + %Q = load {i32,i32}* %Y + ret {i32,i32} %Q +} +