NonDefUseDependency及例子

在研究ReassociatePass的优化时,我发现了其中有一个函数bool llvm::mayHaveNonDefUseDependency(const Instruction &I) {,这个函数会判断一个指令是否是不可优化的,也即是否是可能会造成NonDefUseDependency的。
潜在的非定义使用依赖关系指的是在程序中,某个指令使用了另一个指令产生的值,但两者之间的关系不是经过明确定义的。这可能导致程序在并行执行或重排序时出现问题,因为执行顺序的改变可能会影响到数据的正确性。
这种所谓的没有经过明确定义的,也即没有通过限制指令标记两个指令之间是不可移动或不可并行的,但两个指令之间有明显的先后关系,如果并行可能会出现某种失败的情况。

一个例子

#include 
#include 

int main() {
    int x = 0;
    #pragma omp parallel
    {
        #pragma omp for
        for(int i = 0; i < 100; ++i)
            x = x + 1;
    }
    std::cout << x << std::endl;
}

omp.h头文件主要是将#pragma omp编译为openmp代码。运行指令如下:

clang -fopenmp source -o target

mayHaveNonDefUseDependency

bool llvm::mayHaveNonDefUseDependency(const Instruction &I) {
  if (I.mayReadOrWriteMemory())
    // Memory dependency possible
    return true;
  if (!isSafeToSpeculativelyExecute(&I))
    // Can't move above a maythrow call or infinite loop.  Or if an
    // inalloca alloca, above a stacksave call.
    return true;
  if (!isGuaranteedToTransferExecutionToSuccessor(&I))
    // 1) Can't reorder two inf-loop calls, even if readonly
    // 2) Also can't reorder an inf-loop call below a instruction which isn't
    //    safe to speculative execute.  (Inverse of above)
    return true;
  return false;
}
  1. 首先判断是否读写内存,常见的例如Load Store指令,Call, Invoke指令。
  2. 判断是否是safeToSpeculativelyExecute,此处指的是不能安全的推断执行的指令。能够推测执行的指令,例如如果除数为0,则会返回false,也即mayHaveNonDefUseDependency会返回true.
  3. 判断GuaranteedtoTransferExecutionToSuccessor,该函数用于判断一个指令是否可以将控制流转移到指令后。如果是Return指令或不可达指令,显然会返回false。如果是CatchPad指令,需要判断。最后判断指令是否mayThrow或者willReturn,如果不满足mayThro且willReturn,就会返回true.
bool llvm::isGuaranteedToTransferExecutionToSuccessor(const Instruction *I) {
  // Note: An atomic operation isn't guaranteed to return in a reasonable amount
  // of time because it's possible for another thread to interfere with it for an
  // arbitrary length of time, but programs aren't allowed to rely on that.

  // If there is no successor, then execution can't transfer to it.
  if (isa<ReturnInst>(I))
    return false;
  if (isa<UnreachableInst>(I))
    return false;

  // Note: Do not add new checks here; instead, change Instruction::mayThrow or
  // Instruction::willReturn.
  //
  // FIXME: Move this check into Instruction::willReturn.
  if (isa<CatchPadInst>(I)) { 
    switch (classifyEHPersonality(I->getFunction()->getPersonalityFn())) {
    default:
      // A catchpad may invoke exception object constructors and such, which
      // in some languages can be arbitrary code, so be conservative by default.
      return false;
    case EHPersonality::CoreCLR:
      // For CoreCLR, it just involves a type test.
      return true;
    }
  }

  // An instruction that returns without throwing must transfer control flow
  // to a successor.
  return !I->mayThrow() && I->willReturn();
}

我编译的clang暂时不支持openmp,故此处不测试。

你可能感兴趣的:(编程语言,LLVM,编译,程序分析)