Skip to content

Commit 6aa6b1f

Browse files
committed
Teach ConvertUsesToScalar to handle memset, allowing it to handle
crazy cases like: struct f { int A, B, C, D, E, F; }; short test4() { struct f A; A.A = 1; memset(&A.B, 2, 12); return A.C; } llvm-svn: 63596
1 parent db39362 commit 6aa6b1f

File tree

2 files changed

+73
-21
lines changed

2 files changed

+73
-21
lines changed

llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ namespace {
130130
void ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset);
131131
Value *ConvertUsesOfLoadToScalar(LoadInst *LI, AllocaInst *NewAI,
132132
uint64_t Offset);
133-
Value *ConvertUsesOfStoreToScalar(StoreInst *SI, AllocaInst *NewAI,
134-
uint64_t Offset);
133+
Value *ConvertUsesOfStoreToScalar(Value *StoredVal, AllocaInst *NewAI,
134+
uint64_t Offset, Instruction *InsertPt);
135135
static Instruction *isOnlyCopiedFromConstantGlobal(AllocationInst *AI);
136136
};
137137
}
@@ -1274,6 +1274,18 @@ bool SROA::CanConvertToScalar(Value *V, bool &IsNotTrivial,
12741274
continue;
12751275
}
12761276

1277+
// If this is a constant sized memset of a constant value (e.g. 0) we can
1278+
// handle it.
1279+
if (isa<MemSetInst>(User) &&
1280+
// Store of constant value.
1281+
isa<ConstantInt>(User->getOperand(2)) &&
1282+
// Store with constant size.
1283+
isa<ConstantInt>(User->getOperand(3))) {
1284+
VecTy = Type::VoidTy;
1285+
IsNotTrivial = true;
1286+
continue;
1287+
}
1288+
12771289
// Otherwise, we cannot handle this!
12781290
return false;
12791291
}
@@ -1301,7 +1313,8 @@ void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset) {
13011313

13021314
if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
13031315
assert(SI->getOperand(0) != Ptr && "Consistency error!");
1304-
new StoreInst(ConvertUsesOfStoreToScalar(SI, NewAI, Offset), NewAI, SI);
1316+
new StoreInst(ConvertUsesOfStoreToScalar(SI->getOperand(0), NewAI,
1317+
Offset, SI), NewAI, SI);
13051318
SI->eraseFromParent();
13061319
continue;
13071320
}
@@ -1321,6 +1334,29 @@ void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset) {
13211334
GEP->eraseFromParent();
13221335
continue;
13231336
}
1337+
1338+
// If this is a constant sized memset of a constant value (e.g. 0) we can
1339+
// transform it into a store of the expanded constant value.
1340+
if (MemSetInst *MSI = dyn_cast<MemSetInst>(User)) {
1341+
assert(MSI->getRawDest() == Ptr && "Consistency error!");
1342+
unsigned NumBytes = cast<ConstantInt>(MSI->getLength())->getZExtValue();
1343+
unsigned Val = cast<ConstantInt>(MSI->getValue())->getZExtValue();
1344+
1345+
// Compute the value replicated the right number of times.
1346+
APInt APVal(NumBytes*8, Val);
1347+
1348+
// Splat the value if non-zero.
1349+
if (Val)
1350+
for (unsigned i = 1; i != NumBytes; ++i)
1351+
APVal |= APVal << 8;
1352+
1353+
new StoreInst(ConvertUsesOfStoreToScalar(ConstantInt::get(APVal), NewAI,
1354+
Offset, MSI), NewAI, MSI);
1355+
MSI->eraseFromParent();
1356+
continue;
1357+
}
1358+
1359+
13241360
assert(0 && "Unsupported operation!");
13251361
abort();
13261362
}
@@ -1422,40 +1458,38 @@ Value *SROA::ConvertUsesOfLoadToScalar(LoadInst *LI, AllocaInst *NewAI,
14221458
///
14231459
/// Offset is an offset from the original alloca, in bits that need to be
14241460
/// shifted to the right. By the end of this, there should be no uses of Ptr.
1425-
Value *SROA::ConvertUsesOfStoreToScalar(StoreInst *SI, AllocaInst *NewAI,
1426-
uint64_t Offset) {
1461+
Value *SROA::ConvertUsesOfStoreToScalar(Value *SV, AllocaInst *NewAI,
1462+
uint64_t Offset, Instruction *IP) {
14271463

14281464
// Convert the stored type to the actual type, shift it left to insert
14291465
// then 'or' into place.
1430-
Value *SV = SI->getOperand(0);
14311466
const Type *AllocaType = NewAI->getType()->getElementType();
1432-
if (SV->getType() == AllocaType && Offset == 0) {
1467+
if (SV->getType() == AllocaType && Offset == 0)
14331468
return SV;
1434-
}
14351469

14361470
if (const VectorType *VTy = dyn_cast<VectorType>(AllocaType)) {
1437-
Value *Old = new LoadInst(NewAI, NewAI->getName()+".in", SI);
1471+
Value *Old = new LoadInst(NewAI, NewAI->getName()+".in", IP);
14381472

14391473
// If the result alloca is a vector type, this is either an element
14401474
// access or a bitcast to another vector type.
14411475
if (isa<VectorType>(SV->getType())) {
1442-
SV = new BitCastInst(SV, AllocaType, SV->getName(), SI);
1476+
SV = new BitCastInst(SV, AllocaType, SV->getName(), IP);
14431477
} else {
14441478
// Must be an element insertion.
14451479
unsigned Elt = Offset/TD->getTypePaddedSizeInBits(VTy->getElementType());
14461480

14471481
if (SV->getType() != VTy->getElementType())
1448-
SV = new BitCastInst(SV, VTy->getElementType(), "tmp", SI);
1482+
SV = new BitCastInst(SV, VTy->getElementType(), "tmp", IP);
14491483

14501484
SV = InsertElementInst::Create(Old, SV,
14511485
ConstantInt::get(Type::Int32Ty, Elt),
1452-
"tmp", SI);
1486+
"tmp", IP);
14531487
}
14541488
return SV;
14551489
}
14561490

14571491

1458-
Value *Old = new LoadInst(NewAI, NewAI->getName()+".in", SI);
1492+
Value *Old = new LoadInst(NewAI, NewAI->getName()+".in", IP);
14591493

14601494
// If SV is a float, convert it to the appropriate integer type.
14611495
// If it is a pointer, do the same, and also handle ptr->ptr casts
@@ -1465,19 +1499,19 @@ Value *SROA::ConvertUsesOfStoreToScalar(StoreInst *SI, AllocaInst *NewAI,
14651499
unsigned SrcStoreWidth = TD->getTypeStoreSizeInBits(SV->getType());
14661500
unsigned DestStoreWidth = TD->getTypeStoreSizeInBits(AllocaType);
14671501
if (SV->getType()->isFloatingPoint() || isa<VectorType>(SV->getType()))
1468-
SV = new BitCastInst(SV, IntegerType::get(SrcWidth), SV->getName(), SI);
1502+
SV = new BitCastInst(SV, IntegerType::get(SrcWidth), SV->getName(), IP);
14691503
else if (isa<PointerType>(SV->getType()))
1470-
SV = new PtrToIntInst(SV, TD->getIntPtrType(), SV->getName(), SI);
1504+
SV = new PtrToIntInst(SV, TD->getIntPtrType(), SV->getName(), IP);
14711505

14721506
// Zero extend or truncate the value if needed.
14731507
if (SV->getType() != AllocaType) {
14741508
if (SV->getType()->getPrimitiveSizeInBits() <
14751509
AllocaType->getPrimitiveSizeInBits())
1476-
SV = new ZExtInst(SV, AllocaType, SV->getName(), SI);
1510+
SV = new ZExtInst(SV, AllocaType, SV->getName(), IP);
14771511
else {
14781512
// Truncation may be needed if storing more than the alloca can hold
14791513
// (undefined behavior).
1480-
SV = new TruncInst(SV, AllocaType, SV->getName(), SI);
1514+
SV = new TruncInst(SV, AllocaType, SV->getName(), IP);
14811515
SrcWidth = DestWidth;
14821516
SrcStoreWidth = DestStoreWidth;
14831517
}
@@ -1502,12 +1536,12 @@ Value *SROA::ConvertUsesOfStoreToScalar(StoreInst *SI, AllocaInst *NewAI,
15021536
if (ShAmt > 0 && (unsigned)ShAmt < DestWidth) {
15031537
SV = BinaryOperator::CreateShl(SV,
15041538
ConstantInt::get(SV->getType(), ShAmt),
1505-
SV->getName(), SI);
1539+
SV->getName(), IP);
15061540
Mask <<= ShAmt;
15071541
} else if (ShAmt < 0 && (unsigned)-ShAmt < DestWidth) {
15081542
SV = BinaryOperator::CreateLShr(SV,
15091543
ConstantInt::get(SV->getType(), -ShAmt),
1510-
SV->getName(), SI);
1544+
SV->getName(), IP);
15111545
Mask = Mask.lshr(-ShAmt);
15121546
}
15131547

@@ -1516,8 +1550,8 @@ Value *SROA::ConvertUsesOfStoreToScalar(StoreInst *SI, AllocaInst *NewAI,
15161550
if (SrcWidth != DestWidth) {
15171551
assert(DestWidth > SrcWidth);
15181552
Old = BinaryOperator::CreateAnd(Old, ConstantInt::get(~Mask),
1519-
Old->getName()+".mask", SI);
1520-
SV = BinaryOperator::CreateOr(Old, SV, SV->getName()+".ins", SI);
1553+
Old->getName()+".mask", IP);
1554+
SV = BinaryOperator::CreateOr(Old, SV, SV->getName()+".ins", IP);
15211555
}
15221556
return SV;
15231557
}

llvm/test/Transforms/ScalarRepl/memset-aggregate.ll

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
; PR1226
22
; RUN: llvm-as < %s | opt -scalarrepl | llvm-dis | grep {ret i32 16843009}
33
; RUN: llvm-as < %s | opt -scalarrepl | llvm-dis | not grep alloca
4+
; RUN: llvm-as < %s | opt -scalarrepl -instcombine | llvm-dis | grep {ret i16 514}
45

56
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
67
target triple = "i686-apple-darwin8"
@@ -46,3 +47,20 @@ entry:
4647
%tmp7 = load i32* %tmp6 ; <i32> [#uses=1]
4748
ret i32 %tmp7
4849
}
50+
51+
52+
%struct.f = type { i32, i32, i32, i32, i32, i32 }
53+
54+
define i16 @test4() nounwind {
55+
entry:
56+
%A = alloca %struct.f, align 8 ; <%struct.f*> [#uses=3]
57+
%0 = getelementptr %struct.f* %A, i32 0, i32 0 ; <i32*> [#uses=1]
58+
store i32 1, i32* %0, align 8
59+
%1 = getelementptr %struct.f* %A, i32 0, i32 1 ; <i32*> [#uses=1]
60+
%2 = bitcast i32* %1 to i8* ; <i8*> [#uses=1]
61+
call void @llvm.memset.i32(i8* %2, i8 2, i32 12, i32 4)
62+
%3 = getelementptr %struct.f* %A, i32 0, i32 2 ; <i32*> [#uses=1]
63+
%4 = load i32* %3, align 8 ; <i32> [#uses=1]
64+
%retval12 = trunc i32 %4 to i16 ; <i16> [#uses=1]
65+
ret i16 %retval12
66+
}

0 commit comments

Comments
 (0)