Why should I know this?

[TODO] llvm 공부 계획 업데이트 본문

LLVM-STUDY/TODO

[TODO] llvm 공부 계획 업데이트

die4taoam 2023. 10. 18. 13:27

https://die4taoam.tistory.com/101

 

LLVM 공부/기록/공유 고민

LLVM Optimizing 과정을 공부하면서 효율을 높히고 기록을 남기기 위해서 고민을 좀 해봤습니다. 예로 들려는 최적화는 LoopFlatten 입니다. llvm/lib/Transforms/Scalar/LoopFlatten.cpp 에 구현되어 있습니다. 첫

die4taoam.tistory.com

위처럼 세웠던 계획의 개선안.

 

TEST(LoopInfoTest, HowToFindTripCount) {
  const char *ModuleStr =
      "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"
      "define void @foo(i32 %n, i1 %cond) {\n"
      "entry:\n"
      "  br label %for.cond\n"
      "for.cond:\n"
      "  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]\n"
      "  %cmp = icmp slt i32 %i.0, %n\n"
      "  br i1 %cond, label %for.inc, label %for.end1\n"
      "for.inc:\n"
      "  %inc = add nsw i32 %i.0, 1\n"
      "  br i1 %cmp, label %for.cond, label %for.end2, !llvm.loop !0\n"
      "for.end1:\n"
      "  br label %for.end\n"
      "for.end2:\n"
      "  br label %for.end\n"
      "for.end:\n"
      "  ret void\n"
      "}\n"
      "!0 = distinct !{!0, !1}\n"
      "!1 = !{!\"llvhttp://m.loop.distribute.enable\", i1 true}\n";

  // Parse the module.
  LLVMContext Context;
  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
  auto *F = M->getFunction("foo");
  TargetLibraryInfoImpl TLII;
  TargetLibraryInfo TLI(TLII);
  AssumptionCache AC(*F);
  DominatorTree DT(*F);
  LoopInfo LI(DT);
  ScalarEvolution SE(*F, TLI, AC, DT, LI);
  AAResults AA(TLI);
  DataLayout DL(F->getParent());
  TargetTransformInfo TTI(DL);
  MemorySSA MSSA(*F, &AA, &DT);
  MemorySSAUpdater MSSAU(&MSSA);

  Function::iterator FI = F->begin();
  // First basic block is entry - skip it.
  BasicBlock *Header = &*(++FI);
  assert(Header->getName() == "for.cond");
  Loop *L = LI.getLoopFor(Header);

  // Find the induction PHI. If there is no induction PHI, we can't do the
  // transformation. TODO: could other variables trigger this? Do we have to
  // search for the best one?
  PHINode *InductionPHI = L->getInductionVariable(SE);
  if (!InductionPHI) {
    dbgs() << "Could not find induction PHI\n";
  }
  dbgs() << "\n"
         << "Found induction PHI: ";
  InductionPHI->dump();

  BasicBlock *Latch = L->getLoopLatch();
  bool ContinueOnTrue = L->contains(Latch->getTerminator()->getSuccessor(0));
  auto IsValidPredicate = [&](ICmpInst::Predicate Pred) {
    if (ContinueOnTrue)
      return Pred == CmpInst::ICMP_NE || Pred == CmpInst::ICMP_ULT;
    else
      return Pred == CmpInst::ICMP_EQ;
  };

  ICmpInst *Compare = L->getLatchCmpInst();
  if (!Compare || !IsValidPredicate(Compare->getUnsignedPredicate()) ||
      Compare->hasNUsesOrMore(2)) {
    LLVM_DEBUG(dbgs() << "Could not find valid comparison\n");
    FAIL();
  }

  // Find increment and trip count.
  // There are exactly 2 incoming values to the induction phi; one from the
  // pre-header and one from the latch. The incoming latch value is the
  // increment variable.
  BinaryOperator *Increment =
      cast<BinaryOperator>(InductionPHI->getIncomingValueForBlock(Latch));
  if (Increment->hasNUsesOrMore(3)) {
    LLVM_DEBUG(dbgs() << "Could not find valid increment\n");
    FAIL();
  }

  // The trip count is the RHS of the compare. If this doesn't match the trip
  // count computed by SCEV then this is because the trip count variable
  // has been widened so the types don't match, or because it is a constant and
  // another transformation has changed the compare (e.g. icmp ult %inc,
  // tripcount -> icmp ult %j, tripcount-1), or both.
  Value *RHS = Compare->getOperand(1);

  dbgs() << "ComPare : ";
  Compare->dump();
  dbgs() << "TripCount : ";
  RHS->dump();
  dbgs() << "FIN";
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
 
기존 방식 개선 방식

기존 방식은 최적화 패스를 분석하고 그 과정에서 도출된 핵심 로직을 예제와 함께 하나의 예제코드로 묶는 방식.

개선 방식은 분석 및 로직 도출까진 동일하지만 예제코드가 아닌 입력 값을 받아 원하는 값을 뿌려주는 방식.

 

예)

./loop-study  -trip-count  <IR>

=> Now Searching for TripCount...

1. searching loop...

[Loop 출력]

-> searching Latch...

-> searching Increment...

-> FOUND TripCount!

 

'LLVM-STUDY > TODO' 카테고리의 다른 글

[TODO] 목록  (0) 2023.11.02
[TODO] DominatorTree  (0) 2023.10.20
A Validated Semantics for LLVM IR  (0) 2023.06.23
[TODO] undef  (0) 2023.06.16
symbolic execution 이란 무엇인가?  (0) 2023.05.03
Comments