Getting ScalarEvolution info inside a custom pass

previous research:

I am trying to analyze every loop in a function and get the bounds of each loop via getBounds. I require an object of type ScalarEvolution to get that info.
I found that getAnalysis could be used in passes to get this info from some snippets online, but I get errors saying that getAnalysis is not defined, or that it is not a member of a static class. I assume there is some inaccuracy in how I am going about this.

This is the expansion of the line I use to compile my pass:

/home/share/llvm_build/bin/clang -shared -o hw1.so hw1.cpp -I/home/share/llvm-project-17.0.2.src/llvm/include -I/home/share/llvm_build/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -fPIC -fno-rtti -L/home/share/llvm_build/lib

This is the code of the pass so far. I want to get the correct info in variable SE on line 16:

#include "llvm/IR/PassManager.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"

using namespace llvm;

namespace {

struct DependencyAnalysisPass : public PassInfoMixin<DependencyAnalysisPass> {
  PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
};

PreservedAnalyses DependencyAnalysisPass::run(Function &F, FunctionAnalysisManager &FAM) {

  auto &LI = FAM.getResult<LoopAnalysis>(F);
  auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
  for (const auto &L : LI) {
    if (auto LB = L->getBounds(*SE)) {

    } 
  }
  for (BasicBlock &BB : F) {
    for (Instruction &I : BB) {
        if (auto *LI = dyn_cast<LoadInst>(&I)) {
          outs() << "Load:  " << I << "\n" ;
        } else if (auto *SI = dyn_cast<StoreInst>(&I)) {
          outs() << "Store: " << I << "\n" ;
        } else {
          outs() << "Other: " << I << "\n" ;
        }
    }
  }
  return PreservedAnalyses::all();
}

} // end anonymous namespace

extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo() {
  return {LLVM_PLUGIN_API_VERSION, "DependencyAnalysisPass", LLVM_VERSION_STRING,
          [](PassBuilder &PB) {
            PB.registerPipelineParsingCallback(
                [](StringRef Name, FunctionPassManager &FPM,
                   ArrayRef<PassBuilder::PipelineElement>) {
                  if (Name == "depanalyze") {
                    FPM.addPass(DependencyAnalysisPass());
                    return true;
                  }
                  return false;
                });
          }};
}

Have you tried FAM.getResult instead of getAnalysis?

thanks for the pointer. Using:

  auto &LI = FAM.getResult<LoopAnalysis>(F);
  auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F);
  for (const auto &L : LI) {
    if (auto LB = L->getBounds(SE)) {
      outs() << "Valid loop found" << "\n";
      outs() << LB->getInitialIVValue() << " "
             << LB->getStepInst() << "\n"; 
    } 
  }

compiles without any errors. However, it doesn’t seem to print any data related to loops in my test input. Is my usage of FAM.getResult correct?

The return value from getBounds is std::optional, and it can return nothing in a number of situations. You can look at the source to see what it does.

In terms of usage your code looks ok.

Another option is to use getBackedgeTakenCount from SE: https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/Analysis/ScalarEvolution.h#L889

I would recommend using that interface, as getBounds has a number of constraints which can cause it to fail. If you want to identify inductions, you check check if phis are AddRecurrences.

Thanks for the help. I’ve found that the loop isn’t particularly suitable for these analysis methods. I’ve tried using getBackedgeTakenCount with the result from FAM.getResult, which expectedly doesn’t work. I will look at how to get that working and ask in a separate thread if i have any other questions.