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:
parent
c9d7ed4029
commit
9385ab1c9d
@ -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;
|
||||
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user