Why should I know this?

Memcpyopt crashes with simple IR 본문

LLVM-STUDY/PATCH

Memcpyopt crashes with simple IR

die4taoam 2023. 11. 6. 15:37

 

이번에 살펴볼 패치는 매우 짧아서 좋은 패치 입니다.

 

패치의 링크

https://github.com/llvm/llvm-project/issues/71183

 

Memcpyopt crashes with simple IR · Issue #71183 · llvm/llvm-project

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:10:11:12:13" target triple = "x86_64-unknown-linux-gnu" define void @"julia_#36#f_439"() { top: call v...

github.com

 

 

최초에 문제가 발생하는 IR 은 다음과 같습니다.

define void @"julia_#36#f_439"() {
top:
  call void @llvm.memcpy.p0.p11.i64(ptr null, ptr addrspace(11) null, i64 0, i1 false), !tbaa !0
  ret void
}

 

하지만 이슈에서 공유된 단순화 된 문제 유발 IR은 다음과 같이 약간 다릅니다.

https://llvm.godbolt.org/z/azPcMoM7q

 

Compiler Explorer - LLVM IR (opt 17.0.1)

define void @test(ptr %p, ptr %p2, i64 %size) { call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %p2, i64 %size, i1 false) memory(none) ret void } declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)

llvm.godbolt.org

 

단순화 된 IR

define void @test(ptr %p, ptr %p2, i64 %size) {
  call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %p2, i64 %size, i1 false) memory(none)
  ret void
}

declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)

 

 

 

문제가 생기는 코드는 다음과 같습니다.

  BatchAAResults BAA(*AA);
  MemoryUseOrDef *MA = MSSA->getMemoryAccess(M);
  // FIXME: Not using getClobberingMemoryAccess() here due to PR54682.
  MemoryAccess *AnyClobber = MA->getDefiningAccess();
  MemoryLocation DestLoc = MemoryLocation::getForDest(M);
#10 0x000055555657236f in llvm::MemoryUseOrDef::getDefiningAccess (this=0x0) at /home/m/llvm-project/llvm/include/llvm/Analysis/MemorySSA.h:262
#11 0x0000555558f742f5 in llvm::MemCpyOptPass::processMemCpy (this=0x55555ceb25d8, M=0x55555ceb4060, BBI=...) at /home/m/llvm-project/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp:1692
#12 0x0000555558f75b60 in llvm::MemCpyOptPass::iterateOnFunction (this=0x55555ceb25d8, F=...) at /home/m/llvm-project/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp:1991
#13 0x0000555558f75fe9 in llvm::MemCpyOptPass::runImpl (this=0x55555ceb25d8, F=..., TLI_=0x55555ceb5708, AA_=0x55555ceb4378, AC_=0x55555ceb14f8, DT_=0x55555ceb7e08, PDT_=0x55555ceb3e98, MSSA_=0x55555ce56230)
    at /home/m/llvm-project/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp:2048

 

위 코드에서 MSSA->getMemoryAccess(M) 은 null을 반환해 문제가 발생하게 됩니다.
할당된 메모리 공간이 없기 때문입니다.

 

패치도 다음처럼 앞부분에서 메모리 접근 검사를 하는 것으로 마무리 됐습니다.

bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {
  // We can only optimize non-volatile memcpy's.
  if (M->isVolatile()) return false;

  // If the source and destination of the memcpy are the same, then zap it.
  if (M->getSource() == M->getDest()) {
    ++BBI;
    eraseInstruction(M);
    return true;
  }

  // If the size is zero, remove the memcpy. This also prevents infinite loops
  // in processMemSetMemCpyDependence, which is a no-op for zero-length memcpys.
  if (isZeroSize(M->getLength())) {
    ++BBI;
    eraseInstruction(M);
    return true;
  }

  MemoryUseOrDef *MA = MSSA->getMemoryAccess(M);
  if (!MA)
    // Degenerate case: memcpy marked as not accessing memory.
    return false;

 

문제가 생기는 경우는 memcpy의 인자가 메모리에 할당된 내역을 찾을 수 없기 때문에 발생하는 것으로, null이 인자로 넘어오는 것을 포괄합니다.

 

- 끗 -

 

MemorySSA (TBD)

https://die4taoam.tistory.com/140

 

[TODO] MemorySSA = MSSA

https://llvm.org/docs/MemorySSA.html MemorySSA — LLVM 18.0.0git documentation MemorySSA is an analysis that can be built for any arbitrary function. When it’s built, it does a pass over the function’s IR in order to build up its mapping of MemoryAcce

die4taoam.tistory.com

 

Comments