1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[MemCpyOpt] Extract common function for unwinding check

These two cases should be using the same logic. Not NFC, as this
resolves the TODO regarding use of the underlying object.
This commit is contained in:
Nikita Popov 2020-10-17 15:29:19 +02:00
parent c9d7ed4029
commit 9385ab1c9d
2 changed files with 23 additions and 22 deletions

View File

@ -311,6 +311,22 @@ INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
INITIALIZE_PASS_END(MemCpyOptLegacyPass, "memcpyopt", "MemCpy Optimization",
false, false)
// Check that V is either not accessible by the caller, or unwinding cannot
// occur between Start and End.
static bool mayBeVisibleThroughUnwinding(Value *V, Instruction *Start,
Instruction *End) {
assert(Start->getParent() == End->getParent() && "Must be in same block");
if (!Start->getFunction()->doesNotThrow() &&
!isa<AllocaInst>(getUnderlyingObject(V))) {
for (const Instruction &I :
make_range(Start->getIterator(), End->getIterator())) {
if (I.mayThrow())
return true;
}
}
return false;
}
void MemCpyOptPass::eraseInstruction(Instruction *I) {
if (MSSAU)
MSSAU->removeMemoryAccess(I);
@ -848,16 +864,8 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpyLoad,
// guaranteed to be executed if C is. As it is a non-atomic access, it
// renders accesses from other threads undefined.
// TODO: This is currently not checked.
// TODO: Check underlying object, so we can look through GEPs.
if (!isa<AllocaInst>(cpyDest)) {
assert(C->getParent() == cpyStore->getParent() &&
"call and copy must be in the same block");
for (const Instruction &I : make_range(C->getIterator(),
cpyStore->getIterator())) {
if (I.mayThrow())
return false;
}
}
if (mayBeVisibleThroughUnwinding(cpyDest, C, cpyStore))
return false;
// Check that dest points to memory that is at least as aligned as src.
Align srcAlign = srcAlloca->getAlign();
@ -1094,16 +1102,8 @@ bool MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
Value *DestSize = MemSet->getLength();
Value *SrcSize = MemCpy->getLength();
// If the destination might be accessible by the caller, make sure we cannot
// unwind between the memset and the memcpy.
if (!MemCpy->getFunction()->doesNotThrow() &&
!isa<AllocaInst>(getUnderlyingObject(Dest))) {
for (const Instruction &I :
make_range(MemSet->getIterator(), MemCpy->getIterator())) {
if (I.mayThrow())
return false;
}
}
if (mayBeVisibleThroughUnwinding(Dest, MemSet, MemCpy))
return false;
// By default, create an unaligned memset.
unsigned Align = 1;

View File

@ -131,8 +131,9 @@ define void @dest_is_gep_may_throw_call() {
; CHECK-NEXT: [[SRC:%.*]] = alloca [8 x i8], align 1
; CHECK-NEXT: [[SRC_I8:%.*]] = bitcast [8 x i8]* [[SRC]] to i8*
; CHECK-NEXT: [[DEST_I8:%.*]] = getelementptr [16 x i8], [16 x i8]* [[DEST]], i64 0, i64 8
; CHECK-NEXT: call void @accept_ptr(i8* [[SRC_I8]])
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST_I8]], i8* [[SRC_I8]], i64 8, i1 false)
; CHECK-NEXT: [[DEST_I81:%.*]] = bitcast i8* [[DEST_I8]] to [8 x i8]*
; CHECK-NEXT: [[DEST_I812:%.*]] = bitcast [8 x i8]* [[DEST_I81]] to i8*
; CHECK-NEXT: call void @accept_ptr(i8* [[DEST_I812]])
; CHECK-NEXT: ret void
;
%dest = alloca [16 x i8]