diff options
| -rwxr-xr-x | polly/include/polly/ScopDetection.h | 9 | ||||
| -rw-r--r-- | polly/lib/Analysis/ScopDetection.cpp | 55 | ||||
| -rw-r--r-- | polly/test/ScopDetect/base_pointer.ll | 71 | 
3 files changed, 130 insertions, 5 deletions
diff --git a/polly/include/polly/ScopDetection.h b/polly/include/polly/ScopDetection.h index 63c5c1bbe72..0450311e256 100755 --- a/polly/include/polly/ScopDetection.h +++ b/polly/include/polly/ScopDetection.h @@ -152,6 +152,15 @@ class ScopDetection : public FunctionPass {    /// @return The failure message why the alias is invalid.    std::string formatInvalidAlias(AliasSet &AS) const; +  /// @brief Check if a value is invariant in the region Reg. +  /// +  /// @param Val Value to check for invariance. +  /// @param Reg The region to consider for the invariance of Val. +  /// +  /// @return True if the value represented by Val is invariant in the region +  ///         identified by Reg. +  bool isInvariant(const Value &Val, const Region &Reg) const; +    /// @brief Check if a memory access can be part of a Scop.    ///    /// @param Inst The instruction accessing the memory. diff --git a/polly/lib/Analysis/ScopDetection.cpp b/polly/lib/Analysis/ScopDetection.cpp index 9456ab3afa5..87314b88200 100644 --- a/polly/lib/Analysis/ScopDetection.cpp +++ b/polly/lib/Analysis/ScopDetection.cpp @@ -348,6 +348,53 @@ std::string ScopDetection::formatInvalidAlias(AliasSet &AS) const {    return OS.str();  } +bool ScopDetection::isInvariant(const Value &Val, const Region &Reg) const { +  // A reference to function argument or constant value is invariant. +  if (isa<Argument>(Val) || isa<Constant>(Val)) +    return true; + +  const Instruction *I = dyn_cast<Instruction>(&Val); +  if (!I) +    return false; + +  if (!Reg.contains(I)) +    return true; + +  if (I->mayHaveSideEffects()) +    return false; + +  // When Val is a Phi node, it is likely not invariant. We do not check whether +  // Phi nodes are actually invariant, we assume that Phi nodes are usually not +  // invariant. Recursively checking the operators of Phi nodes would lead to +  // infinite recursion. +  if (isa<PHINode>(*I)) +    return false; + +  // Check that all operands of the instruction are +  // themselves invariant. +  const Instruction::const_op_iterator OE = I->op_end(); +  for (Instruction::const_op_iterator OI = I->op_begin(); OI != OE; ++OI) { +    if (!isInvariant(**OI, Reg)) +      return false; +  } + +  // When the instruction is a load instruction, check that no write to memory +  // in the region aliases with the load. +  if (const LoadInst *LI = dyn_cast<LoadInst>(I)) { +    AliasAnalysis::Location Loc = AA->getLocation(LI); +    const Region::const_block_iterator BE = Reg.block_end(); +    // Check if any basic block in the region can modify the location pointed to +    // by 'Loc'.  If so, 'Val' is (likely) not invariant in the region. +    for (Region::const_block_iterator BI = Reg.block_begin(); BI != BE; ++BI) { +      const BasicBlock &BB = **BI; +      if (AA->canBasicBlockModify(BB, Loc)) +        return false; +    } +  } + +  return true; +} +  bool ScopDetection::isValidMemoryAccess(Instruction &Inst,                                          DetectionContext &Context) const {    Value *Ptr = getPointerOperand(Inst); @@ -370,6 +417,14 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst,      return false;    } +  // Check that the base address of the access is invariant in the current +  // region. +  if (!isInvariant(*BaseValue, Context.CurRegion)) { +    INVALID(AffFunc, +            "Base address not invariant in current region:" << *BaseValue); +    return false; +  } +    AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);    if (!AllowNonAffine && diff --git a/polly/test/ScopDetect/base_pointer.ll b/polly/test/ScopDetect/base_pointer.ll index 45bd6b78bbc..ee05d13a3b1 100644 --- a/polly/test/ScopDetect/base_pointer.ll +++ b/polly/test/ScopDetect/base_pointer.ll @@ -151,9 +151,9 @@ entry:  for.i:    %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]    %ptr = phi float* [ %ptr.next, %for.i.inc ], [ %A, %entry ] -; To get a PHI node inside a SCoP, that can not be analyzed but -; for which the surrounding scop is normally still valid we use a function -; without any sideeffects. +; To get a PHI node inside a SCoP that can not be analyzed but +; for which the surrounding SCoP is normally still valid we use a function +; without any side effects.    %ptr.next = call float* @getNextBasePtr(float* %ptr)    br label %S1 @@ -182,8 +182,8 @@ entry:  for.i:    %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ]  ; To get an instruction inside a region, we use a function without side -; effects on which SCEV blocks, but for which still is clear that the return -; value remains invariant throughout the whole loop. +; effects on which SCEV blocks, but for which it is still clear that the +; return value remains invariant throughout the whole loop.    %ptr = call float* @getNextBasePtr(float* %A)    br label %S1 @@ -234,3 +234,64 @@ exit:  ; CHECK-LABEL: base_pointer_is_inst_inside_invariant_2  ; CHECK: Valid Region for Scop: for.i => exit + +declare float* @getNextBasePtr3(float*, i64) readnone nounwind + +define void @base_pointer_is_inst_inside_variant(i64 %n, float* %A) { +entry: +  br label %for.i + +for.i: +  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ] +  %ptr = call float* @getNextBasePtr3(float* %A, i64 %indvar.i) +  %ptr2 = call float* @getNextBasePtr(float* %ptr) +  br label %S1 + +S1: +  %conv = sitofp i64 %indvar.i to float +  %arrayidx5 = getelementptr float* %ptr2, i64 %indvar.i +  store float %conv, float* %arrayidx5, align 4 +  br label %for.i.inc + +for.i.inc: +  %indvar.i.next = add i64 %indvar.i, 1 +  %exitcond.i = icmp ne i64 %indvar.i.next, %n +  br i1 %exitcond.i, label %for.i, label %exit + +exit: +  ret void +} + +; CHECK: base_pointer_is_inst_inside_variant +; CHECK-NOT: Valid Region for Scop + +define void @base_pointer_is_ptr2ptr(float** noalias %A, i64 %n) { +entry: +  br label %for.i + +for.i: +  %indvar.i = phi i64 [ %indvar.i.next, %for.i.inc ], [ 0, %entry ] +  %arrayidx = getelementptr float** %A, i64 %indvar.i +  br label %for.j + +for.j: +  %indvar.j = phi i64 [ 0, %for.i ], [ %indvar.j.next, %for.j ] +  %conv = sitofp i64 %indvar.i to float +  %basepointer = load float** %arrayidx, align 8 +  %arrayidx5 = getelementptr float* %basepointer, i64 %indvar.j +  store float %conv, float* %arrayidx5, align 4 +  %indvar.j.next = add i64 %indvar.j, 1 +  %exitcond.j = icmp ne i64 %indvar.j.next, %n +  br i1 %exitcond.j, label %for.j, label %for.i.inc + +for.i.inc: +  %indvar.i.next = add i64 %indvar.i, 1 +  %exitcond.i = icmp ne i64 %indvar.i.next, %n +  br i1 %exitcond.i, label %for.i, label %exit + +exit: +  ret void +} + +; CHECK: base_pointer_is_ptr2ptr +; CHECK-NOT: Valid Region for Scop  | 

