Why should I know this?

LoopLatch 본문

LLVM-STUDY

LoopLatch

die4taoam 2023. 2. 26. 19:18

Loop에서 Latch란 다음과 같이 정의되어 있다.

https://llvm.org/docs/LoopTerminology.html

 

LLVM Loop Terminology (and Canonical Forms) — LLVM 17.0.0git documentation

The Loop Simplify Form is a canonical form that makes several analyses and transformations simpler and more effective. It is ensured by the LoopSimplify (-loop-simplify) pass and is automatically added by the pass managers when scheduling a LoopPass. This

llvm.org

A latch is a loop node that has an edge to the header.

 

 

 

예를 들어 다음과 같은 IR이 존재한다고 하면, (loop-flatten.ll 중 test1 )

define i32 @test1(i32 %val, i16* nocapture %A) {
entry:
  br label %for.body
for.body:                                         ; preds = %entry, %for.inc6
  %i.018 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
  %mul = mul nuw nsw i32 %i.018, 20
  br label %for.body3
for.body3:                                        ; preds = %for.body, %for.body3
  %j.017 = phi i32 [ 0, %for.body ], [ %inc, %for.body3 ]
  %add = add nuw nsw i32 %j.017, %mul
  %arrayidx = getelementptr inbounds i16, i16* %A, i32 %add
  %0 = load i16, i16* %arrayidx, align 2
  %conv16 = zext i16 %0 to i32
  %add4 = add i32 %conv16, %val
  %conv5 = trunc i32 %add4 to i16
  store i16 %conv5, i16* %arrayidx, align 2
  %inc = add nuw nsw i32 %j.017, 1
  %exitcond = icmp ne i32 %inc, 20
  br i1 %exitcond, label %for.body3, label %for.inc6
for.inc6:                                         ; preds = %for.body3
  %inc7 = add nuw nsw i32 %i.018, 1
  %exitcond19 = icmp ne i32 %inc7, 10
  br i1 %exitcond19, label %for.body, label %for.end8
for.end8:                                         ; preds = %for.inc6
  ret i32 10
}

 

다음과 같이 시각화를 할 수 있다.

bin/opt test1.ll -S -loop-flatten -verify-loop-info -verify-dom-info -verify-scev -verify --dot-cfg

 

여기서 Latch는 for.inc6 이고exiting/latch block 이다.

Latch를 찾는 getLoopLatch 함수는 다음처럼 구현되어 있다.

 

// LoopLatch - LoopInfoImpl.h:212

/// getLoopLatch - If there is a single latch block for this loop, return it.
/// A latch block is a block that contains a branch back to the header.
template <class BlockT, class LoopT>
BlockT *LoopBase<BlockT, LoopT>::getLoopLatch() const {
  assert(!isInvalid() && "Loop not in a valid state!");
  BlockT *Header = getHeader();
  BlockT *Latch = nullptr;
  for (const auto Pred : children<Inverse<BlockT *>>(Header)) {
    if (contains(Pred)) {
      if (Latch)
        return nullptr;
      Latch = Pred;
    }
  }
  return Latch;
}

 

getHeader로 반환되는 Header는 for.body이다. 

LoopHeader :                                                                 
for.body:                                         ; preds = %for.inc6, %entry
  %i.018 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]                       
  %mul = mul nuw nsw i32 %i.018, 20                                          
  br label %for.body3                                                        

 

주석과 같이 LoopLatch를 찾는 코드는 위의 Loop Header 인 for.body의 pred들을 역방향으로 탐색하여

Pred가 Loop문 내에 포함되어 있는 경우 해당 Pred basicblock을 반환한다.
하지만 만약 Latch가 둘 이상 존재하는 경우에는 nullptr을 반환한다.

 

 

Comments