--- /dev/null
+//=== ScopDetectionDiagnostic.h -- Diagnostic for ScopDetection -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// Small set of diagnostic helper classes to encapsulate any errors occurred
+// during the detection of Scops.
+//
+// The ScopDetection defines a set of error classes (via Statistic variables)
+// that groups a number of individual errors into a group, e.g. non-affinity
+// related errors.
+// On error we generate an object that carries enough additional information
+// to diagnose the error and generate a helpful error message.
+//===----------------------------------------------------------------------===//
+#ifndef POLLY_SCOP_DETECTION_DIAGNOSTIC_H
+#define POLLY_SCOP_DETECTION_DIAGNOSTIC_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/AliasSetTracker.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Value.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "polly-detect"
+#include "llvm/Support/Debug.h"
+
+#include <string>
+
+#define BADSCOP_STAT(NAME, DESC) \
+ STATISTIC(Bad##NAME##ForScop, "Number of bad regions for Scop: " DESC)
+
+BADSCOP_STAT(CFG, "CFG too complex");
+BADSCOP_STAT(IndVar, "Non canonical induction variable in loop");
+BADSCOP_STAT(IndEdge, "Found invalid region entering edges");
+BADSCOP_STAT(LoopBound, "Loop bounds can not be computed");
+BADSCOP_STAT(FuncCall, "Function call with side effects appeared");
+BADSCOP_STAT(AffFunc, "Expression not affine");
+BADSCOP_STAT(Alias, "Found base address alias");
+BADSCOP_STAT(SimpleLoop, "Loop not in -loop-simplify form");
+BADSCOP_STAT(Other, "Others");
+
+namespace polly {
+
+/// @brief Small string conversion via raw_string_stream.
+template <typename T> std::string operator+(Twine LHS, const T &RHS) {
+ std::string Buf;
+ raw_string_ostream fmt(Buf);
+ fmt << RHS;
+ fmt.flush();
+
+ return LHS.concat(Buf).str();
+}
+
+//===----------------------------------------------------------------------===//
+/// @brief Base class of all reject reasons found during Scop detection.
+///
+/// Subclasses of RejectReason should provide means to capture enough
+/// diagnostic information to help clients figure out what and where something
+/// went wrong in the Scop detection.
+class RejectReason {
+ //===--------------------------------------------------------------------===//
+public:
+ virtual ~RejectReason() {};
+
+ /// @brief Generate a reasonable diagnostic message describing this error.
+ ///
+ /// @return A debug message representing this error.
+ virtual std::string getMessage() const = 0;
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Base class for CFG related reject reasons.
+///
+/// Scop candidates that violate structural restrictions can be grouped under
+/// this reject reason class.
+class ReportCFG : public RejectReason {
+ //===--------------------------------------------------------------------===//
+public:
+ ReportCFG() { ++BadCFGForScop; }
+};
+
+class ReportNonBranchTerminator : public ReportCFG {
+ BasicBlock *BB;
+
+public:
+ ReportNonBranchTerminator(BasicBlock *BB) : BB(BB) {};
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return ("Non branch instruction terminates BB: " + BB->getName()).str();
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a not well-structured condition within the CFG.
+class ReportCondition : public ReportCFG {
+ //===--------------------------------------------------------------------===//
+
+ // The BasicBlock we found the broken condition in.
+ BasicBlock *BB;
+
+public:
+ ReportCondition(BasicBlock *BB) : BB(BB) {};
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return ("Not well structured condition at BB: " + BB->getName()).str();
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Base class for non-affine reject reasons.
+///
+/// Scop candidates that violate restrictions to affinity are reported under
+/// this class.
+class ReportAffFunc : public RejectReason {
+ //===--------------------------------------------------------------------===//
+public:
+ ReportAffFunc() { ++BadAffFuncForScop; }
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a condition that is based on an 'undef' value.
+class ReportUndefCond : public ReportAffFunc {
+ //===--------------------------------------------------------------------===//
+
+ // The BasicBlock we found the broken condition in.
+ BasicBlock *BB;
+
+public:
+ ReportUndefCond(BasicBlock *BB) : BB(BB) {};
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return ("Condition based on 'undef' value in BB: " + BB->getName()).str();
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures an invalid condition
+///
+/// Conditions have to be either constants or icmp instructions.
+class ReportInvalidCond : public ReportAffFunc {
+ //===--------------------------------------------------------------------===//
+
+ // The BasicBlock we found the broken condition in.
+ BasicBlock *BB;
+
+public:
+ ReportInvalidCond(BasicBlock *BB) : BB(BB) {};
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return ("Condition in BB '" + BB->getName()).str() +
+ "' neither constant nor an icmp instruction";
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures an undefined operand.
+class ReportUndefOperand : public ReportAffFunc {
+ //===--------------------------------------------------------------------===//
+
+ // The BasicBlock we found the undefined operand in.
+ BasicBlock *BB;
+
+public:
+ ReportUndefOperand(BasicBlock *BB) : BB(BB) {};
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return ("undef operand in branch at BB: " + BB->getName()).str();
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a non-affine branch.
+class ReportNonAffBranch : public ReportAffFunc {
+ //===--------------------------------------------------------------------===//
+
+ // The BasicBlock we found the non-affine branch in.
+ BasicBlock *BB;
+
+ /// @brief LHS & RHS of the failed condition.
+ //@{
+ const SCEV *LHS;
+ const SCEV *RHS;
+ //@}
+
+public:
+ ReportNonAffBranch(BasicBlock *BB, const SCEV *LHS, const SCEV *RHS)
+ : BB(BB), LHS(LHS), RHS(RHS) {};
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return ("Non affine branch in BB '" + BB->getName()).str() +
+ "' with LHS: " + *LHS + " and RHS: " + *RHS;
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a missing base pointer.
+class ReportNoBasePtr : public ReportAffFunc {
+ //===--------------------------------------------------------------------===//
+public:
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const { return "No base pointer"; }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures an undefined base pointer.
+class ReportUndefBasePtr : public ReportAffFunc {
+ //===--------------------------------------------------------------------===//
+public:
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const { return "Undefined base pointer"; }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a base pointer that is not invariant in the region.
+class ReportVariantBasePtr : public ReportAffFunc {
+ //===--------------------------------------------------------------------===//
+
+ // The variant base pointer.
+ Value *BaseValue;
+
+public:
+ ReportVariantBasePtr(Value *BaseValue) : BaseValue(BaseValue) {};
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return "Base address not invariant in current region:" + *BaseValue;
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a non-affine access function.
+class ReportNonAffineAccess : public ReportAffFunc {
+ //===--------------------------------------------------------------------===//
+
+ // The non-affine access function.
+ const SCEV *AccessFunction;
+
+public:
+ ReportNonAffineAccess(const SCEV *AccessFunction)
+ : AccessFunction(AccessFunction) {};
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return "Non affine access function: " + *AccessFunction;
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Base class for reject reasons related to induction variables.
+///
+// ReportIndVar reject reasons are generated when the ScopDetection finds
+/// errors in the induction variable(s) of the Scop candidate.
+class ReportIndVar : public RejectReason {
+ //===--------------------------------------------------------------------===//
+public:
+ ReportIndVar() { ++BadIndVarForScop; }
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a phi node that refers to SSA names in the current region.
+class ReportPhiNodeRefInRegion : public ReportIndVar {
+ //===--------------------------------------------------------------------===//
+
+ // The offending instruction.
+ Instruction *Inst;
+
+public:
+ ReportPhiNodeRefInRegion(Instruction *Inst) : Inst(Inst) {};
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return "SCEV of PHI node refers to SSA names in region: " + *Inst;
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a non canonical phi node.
+class ReportNonCanonicalPhiNode : public ReportIndVar {
+ //===--------------------------------------------------------------------===//
+
+ // The offending instruction.
+ Instruction *Inst;
+
+public:
+ ReportNonCanonicalPhiNode(Instruction *Inst) : Inst(Inst) {};
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return "Non canonical PHI node: " + *Inst;
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a non canonical induction variable in the loop header.
+class ReportLoopHeader : public ReportIndVar {
+ //===--------------------------------------------------------------------===//
+
+ // The offending loop.
+ Loop *L;
+
+public:
+ ReportLoopHeader(Loop *L) : L(L) {};
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return ("No canonical IV at loop header: " + L->getHeader()->getName())
+ .str();
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures a region with invalid entering edges.
+class ReportIndEdge : public RejectReason {
+ //===--------------------------------------------------------------------===//
+public:
+ ReportIndEdge() { ++BadIndEdgeForScop; }
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return "Region has invalid entering edges!";
+ }
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with non affine loop bounds.
+class ReportLoopBound : public RejectReason {
+ //===--------------------------------------------------------------------===//
+
+ // The offending loop.
+ Loop *L;
+
+ // The non-affine loop bound.
+ const SCEV *LoopCount;
+
+public:
+ ReportLoopBound(Loop *L, const SCEV *LoopCount) : L(L), LoopCount(LoopCount) {
+ ++BadLoopBoundForScop;
+ };
+
+ /// @name RejectReason interface
+ //@{
+ virtual std::string getMessage() const {
+ return "Non affine loop bound '" + *LoopCount + "' in loop: " +
+ L->getHeader()->getName();
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with non-side-effect-known function calls.
+class ReportFuncCall : public RejectReason {
+ //===--------------------------------------------------------------------===//
+
+ // The offending call instruction.
+ Instruction *Inst;
+
+public:
+ ReportFuncCall(Instruction *Inst) : Inst(Inst) {
+ ++BadFuncCallForScop;
+ };
+
+ /// @name RejectReason interface
+ //@{
+ std::string getMessage() const { return "Call instruction: " + *Inst; }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with aliasing.
+class ReportAlias : public RejectReason {
+ //===--------------------------------------------------------------------===//
+
+ // The offending alias set.
+ AliasSet *AS;
+
+ /// @brief Format an invalid alias set.
+ ///
+ /// @param AS The invalid alias set to format.
+ std::string formatInvalidAlias(AliasSet &AS) const {
+ std::string Message;
+ raw_string_ostream OS(Message);
+
+ OS << "Possible aliasing: ";
+
+ std::vector<Value *> Pointers;
+
+ for (const auto &I : AS)
+ Pointers.push_back(I.getValue());
+
+ std::sort(Pointers.begin(), Pointers.end());
+
+ for (std::vector<Value *>::iterator PI = Pointers.begin(),
+ PE = Pointers.end();
+ ;) {
+ Value *V = *PI;
+
+ if (V->getName().size() == 0)
+ OS << "\"" << *V << "\"";
+ else
+ OS << "\"" << V->getName() << "\"";
+
+ ++PI;
+
+ if (PI != PE)
+ OS << ", ";
+ else
+ break;
+ }
+
+ return OS.str();
+ }
+
+public:
+ ReportAlias(AliasSet *AS) : AS(AS) { ++BadAliasForScop; }
+
+ /// @name RejectReason interface
+ //@{
+ std::string getMessage() const { return formatInvalidAlias(*AS); }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with non simplified loops.
+class ReportSimpleLoop : public RejectReason {
+ //===--------------------------------------------------------------------===//
+public:
+ ReportSimpleLoop() { ++BadSimpleLoopForScop; }
+
+ /// @name RejectReason interface
+ //@{
+ std::string getMessage() const {
+ return "Loop not in simplify form is invalid!";
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Base class for otherwise ungrouped reject reasons.
+class ReportOther : public RejectReason {
+ //===--------------------------------------------------------------------===//
+public:
+ ReportOther() { ++BadOtherForScop; }
+
+ /// @name RejectReason interface
+ //@{
+ std::string getMessage() const { return "Unknown reject reason"; }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with bad IntToPtr instructions.
+class ReportIntToPtr : public ReportOther {
+ //===--------------------------------------------------------------------===//
+
+ // The offending base value.
+ Value *BaseValue;
+
+public:
+ ReportIntToPtr(Value *BaseValue) : BaseValue(BaseValue) {};
+
+ /// @name RejectReason interface
+ //@{
+ std::string getMessage() const {
+ return "Find bad intToptr prt: " + *BaseValue;
+ }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with alloca instructions.
+class ReportAlloca : public ReportOther {
+ //===--------------------------------------------------------------------===//
+ Instruction *Inst;
+
+public:
+ ReportAlloca(Instruction *Inst) : Inst(Inst) {};
+
+ /// @name RejectReason interface
+ //@{
+ std::string getMessage() const { return "Alloca instruction: " + *Inst; }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with unknown instructions.
+class ReportUnknownInst : public ReportOther {
+ //===--------------------------------------------------------------------===//
+ Instruction *Inst;
+
+public:
+ ReportUnknownInst(Instruction *Inst) : Inst(Inst) {};
+
+ /// @name RejectReason interface
+ //@{
+ std::string getMessage() const { return "Unknown instruction: " + *Inst; }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with phi nodes in exit BBs.
+class ReportPHIinExit : public ReportOther {
+ //===--------------------------------------------------------------------===//
+public:
+ /// @name RejectReason interface
+ //@{
+ std::string getMessage() const { return "PHI node in exit BB"; }
+ //@}
+};
+
+//===----------------------------------------------------------------------===//
+/// @brief Captures errors with regions containing the function entry block.
+class ReportEntry : public ReportOther {
+ //===--------------------------------------------------------------------===//
+public:
+ /// @name RejectReason interface
+ //@{
+ std::string getMessage() const {
+ return "Region containing entry block of function is invalid!";
+ }
+ //@}
+};
+
+} // namespace polly
+
+#endif // POLLY_SCOP_DETECTION_DIAGNOSTIC_H
#include "polly/CodeGen/BlockGenerators.h"
#include "polly/LinkAllPasses.h"
#include "polly/Options.h"
+#include "polly/ScopDetectionDiagnostic.h"
#include "polly/ScopDetection.h"
#include "polly/Support/SCEVValidator.h"
#include "polly/Support/ScopHelper.h"
STATISTIC(ValidRegion, "Number of regions that a valid part of Scop");
-#define BADSCOP_STAT(NAME, DESC) \
- STATISTIC(Bad##NAME##ForScop, "Number of bad regions for Scop: " DESC)
-
-#define INVALID(NAME, MESSAGE) \
- do { \
- if (PollyTrackFailures) { \
- std::string Buf; \
- raw_string_ostream fmt(Buf); \
- fmt << MESSAGE; \
- fmt.flush(); \
- LastFailure = Buf; \
- } \
- DEBUG(dbgs() << MESSAGE); \
- DEBUG(dbgs() << "\n"); \
- assert(!Context.Verifying && #NAME); \
- if (!Context.Verifying) \
- ++Bad##NAME##ForScop; \
- } while (0)
-
-#define INVALID_NOVERIFY(NAME, MESSAGE) \
- do { \
- if (PollyTrackFailures) { \
- std::string Buf; \
- raw_string_ostream fmt(Buf); \
- fmt << MESSAGE; \
- fmt.flush(); \
- LastFailure = Buf; \
- } \
- DEBUG(dbgs() << MESSAGE); \
- DEBUG(dbgs() << "\n"); \
- /* DISABLED: assert(!Context.Verifying && #NAME); */ \
- if (!Context.Verifying) \
- ++Bad##NAME##ForScop; \
- } while (0)
-
-BADSCOP_STAT(CFG, "CFG too complex");
-BADSCOP_STAT(IndVar, "Non canonical induction variable in loop");
-BADSCOP_STAT(IndEdge, "Found invalid region entering edges");
-BADSCOP_STAT(LoopBound, "Loop bounds can not be computed");
-BADSCOP_STAT(FuncCall, "Function call with side effects appeared");
-BADSCOP_STAT(AffFunc, "Expression not affine");
-BADSCOP_STAT(Alias, "Found base address alias");
-BADSCOP_STAT(SimpleLoop, "Loop not in -loop-simplify form");
-BADSCOP_STAT(Other, "Others");
-
class DiagnosticScopFound : public DiagnosticInfo {
private:
static int PluginDiagnosticKind;
//===----------------------------------------------------------------------===//
// ScopDetection.
+
+template <class RR, typename... Args>
+inline bool ScopDetection::invalid(DetectionContext &Context, bool Assert,
+ Args &&... Arguments) const {
+
+ if (!Context.Verifying) {
+ RR RejectReason = RR(Arguments...);
+ if (PollyTrackFailures)
+ LastFailure = RejectReason.getMessage();
+
+ DEBUG(dbgs() << RejectReason.getMessage());
+ DEBUG(dbgs() << "\n");
+ } else {
+ assert(!Assert && "Verification of detected scop failed");
+ }
+
+ return false;
+}
+
bool ScopDetection::isMaxRegionInScop(const Region &R, bool Verify) const {
if (!ValidRegions.count(&R))
return false;
BranchInst *Br = dyn_cast<BranchInst>(TI);
- if (!Br) {
- INVALID(CFG, "Non branch instruction terminates BB: " + BB.getName());
- return false;
- }
+ if (!Br)
+ return invalid<ReportNonBranchTerminator>(Context, /*Assert=*/true, &BB);
if (Br->isUnconditional())
return true;
Value *Condition = Br->getCondition();
// UndefValue is not allowed as condition.
- if (isa<UndefValue>(Condition)) {
- INVALID(AffFunc, "Condition based on 'undef' value in BB: " + BB.getName());
- return false;
- }
+ if (isa<UndefValue>(Condition))
+ return invalid<ReportUndefCond>(Context, /*Assert=*/true, &BB);
// Only Constant and ICmpInst are allowed as condition.
- if (!(isa<Constant>(Condition) || isa<ICmpInst>(Condition))) {
- INVALID(AffFunc, "Condition in BB '" + BB.getName() +
- "' neither constant nor an icmp instruction");
- return false;
- }
+ if (!(isa<Constant>(Condition) || isa<ICmpInst>(Condition)))
+ return invalid<ReportInvalidCond>(Context, /*Assert=*/true, &BB);
// Allow perfectly nested conditions.
assert(Br->getNumSuccessors() == 2 && "Unexpected number of successors");
// Are both operands of the ICmp affine?
if (isa<UndefValue>(ICmp->getOperand(0)) ||
- isa<UndefValue>(ICmp->getOperand(1))) {
- INVALID(AffFunc, "undef operand in branch at BB: " + BB.getName());
- return false;
- }
+ isa<UndefValue>(ICmp->getOperand(1)))
+ return invalid<ReportUndefOperand>(Context, /*Assert=*/true, &BB);
Loop *L = LI->getLoopFor(ICmp->getParent());
const SCEV *LHS = SE->getSCEVAtScope(ICmp->getOperand(0), L);
const SCEV *RHS = SE->getSCEVAtScope(ICmp->getOperand(1), L);
if (!isAffineExpr(&Context.CurRegion, LHS, *SE) ||
- !isAffineExpr(&Context.CurRegion, RHS, *SE)) {
- INVALID(AffFunc, "Non affine branch in BB '" << BB.getName()
- << "' with LHS: " << *LHS
- << " and RHS: " << *RHS);
- return false;
- }
+ !isAffineExpr(&Context.CurRegion, RHS, *SE))
+ return invalid<ReportNonAffBranch>(Context, /*Assert=*/true, &BB, LHS,
+ RHS);
}
// Allow loop exit conditions.
// Allow perfectly nested conditions.
Region *R = RI->getRegionFor(&BB);
- if (R->getEntry() != &BB) {
- INVALID(CFG, "Not well structured condition at BB: " + BB.getName());
- return false;
- }
+ if (R->getEntry() != &BB)
+ return invalid<ReportCondition>(Context, /*Assert=*/true, &BB);
return true;
}
return false;
}
-std::string ScopDetection::formatInvalidAlias(AliasSet &AS) const {
- std::string Message;
- raw_string_ostream OS(Message);
-
- OS << "Possible aliasing: ";
-
- std::vector<Value *> Pointers;
-
- for (const auto &I : AS)
- Pointers.push_back(I.getValue());
-
- std::sort(Pointers.begin(), Pointers.end());
-
- for (std::vector<Value *>::iterator PI = Pointers.begin(),
- PE = Pointers.end();
- ;) {
- Value *V = *PI;
-
- if (V->getName().size() == 0)
- OS << "\"" << *V << "\"";
- else
- OS << "\"" << V->getName() << "\"";
-
- ++PI;
-
- if (PI != PE)
- OS << ", ";
- else
- break;
- }
-
- 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))
BasePointer = dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction));
- if (!BasePointer) {
- INVALID(AffFunc, "No base pointer");
- return false;
- }
+ if (!BasePointer)
+ return invalid<ReportNoBasePtr>(Context, /*Assert=*/true);
BaseValue = BasePointer->getValue();
- if (isa<UndefValue>(BaseValue)) {
- INVALID(AffFunc, "Undefined base pointer");
- return false;
- }
+ if (isa<UndefValue>(BaseValue))
+ return invalid<ReportUndefBasePtr>(Context, /*Assert=*/true);
// Check that the base address of the access is invariant in the current
// region.
- if (!isInvariant(*BaseValue, Context.CurRegion)) {
+ if (!isInvariant(*BaseValue, Context.CurRegion))
// Verification of this property is difficult as the independent blocks
// pass may introduce aliasing that we did not have when running the
// scop detection.
- INVALID_NOVERIFY(
- AffFunc, "Base address not invariant in current region:" << *BaseValue);
- return false;
- }
+ return invalid<ReportVariantBasePtr>(Context, /*Assert=*/false, BaseValue);
AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);
if (!AllowNonAffine &&
- !isAffineExpr(&Context.CurRegion, AccessFunction, *SE, BaseValue)) {
- INVALID(AffFunc, "Non affine access function: " << *AccessFunction);
- return false;
- }
+ !isAffineExpr(&Context.CurRegion, AccessFunction, *SE, BaseValue))
+ return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true,
+ AccessFunction);
// FIXME: Alias Analysis thinks IntToPtrInst aliases with alloca instructions
// created by IndependentBlocks Pass.
- if (isa<IntToPtrInst>(BaseValue)) {
- INVALID(Other, "Find bad intToptr prt: " << *BaseValue);
- return false;
- }
+ if (isa<IntToPtrInst>(BaseValue))
+ return invalid<ReportIntToPtr>(Context, /*Assert=*/true, BaseValue);
if (IgnoreAliasing)
return true;
// alias, if -basicaa is not available. They actually do not, but as we can
// not proof this without -basicaa we would fail. We disable this check to
// not cause irrelevant verification failures.
- if (!AS.isMustAlias()) {
- INVALID_NOVERIFY(Alias, formatInvalidAlias(AS));
- return false;
- }
+ if (!AS.isMustAlias())
+ return invalid<ReportAlias>(Context, /*Assert=*/true, &AS);
return true;
}
DetectionContext &Context) const {
if (PHINode *PN = dyn_cast<PHINode>(&Inst))
if (!canSynthesize(PN, LI, SE, &Context.CurRegion)) {
- if (SCEVCodegen) {
- INVALID(IndVar,
- "SCEV of PHI node refers to SSA names in region: " << Inst);
- return false;
-
- } else {
- INVALID(IndVar, "Non canonical PHI node: " << Inst);
- return false;
- }
+ if (SCEVCodegen)
+ return invalid<ReportPhiNodeRefInRegion>(Context, /*Assert=*/true,
+ &Inst);
+ else
+ return invalid<ReportNonCanonicalPhiNode>(Context, /*Assert=*/true,
+ &Inst);
}
// We only check the call instruction but not invoke instruction.
if (isValidCallInst(*CI))
return true;
- INVALID(FuncCall, "Call instruction: " << Inst);
- return false;
+ return invalid<ReportFuncCall>(Context, /*Assert=*/true, &Inst);
}
if (!Inst.mayWriteToMemory() && !Inst.mayReadFromMemory()) {
if (!isa<AllocaInst>(Inst))
return true;
- INVALID(Other, "Alloca instruction: " << Inst);
- return false;
+ return invalid<ReportAlloca>(Context, /*Assert=*/true, &Inst);
}
// Check the access function.
return isValidMemoryAccess(Inst, Context);
// We do not know this instruction, therefore we assume it is invalid.
- INVALID(Other, "Unknown instruction: " << Inst);
- return false;
+ return invalid<ReportUnknownInst>(Context, /*Assert=*/true, &Inst);
}
bool ScopDetection::isValidLoop(Loop *L, DetectionContext &Context) const {
// If code generation is not in scev based mode, we need to ensure that
// each loop has a canonical induction variable.
PHINode *IndVar = L->getCanonicalInductionVariable();
- if (!IndVar) {
- INVALID(IndVar,
- "No canonical IV at loop header: " << L->getHeader()->getName());
- return false;
- }
+ if (!IndVar)
+ return invalid<ReportLoopHeader>(Context, /*Assert=*/true, L);
}
// Is the loop count affine?
const SCEV *LoopCount = SE->getBackedgeTakenCount(L);
- if (!isAffineExpr(&Context.CurRegion, LoopCount, *SE)) {
- INVALID(LoopBound, "Non affine loop bound '" << *LoopCount << "' in loop: "
- << L->getHeader()->getName());
- return false;
- }
+ if (!isAffineExpr(&Context.CurRegion, LoopCount, *SE))
+ return invalid<ReportLoopBound>(Context, /*Assert=*/true, L, LoopCount);
return true;
}
// PHI nodes are not allowed in the exit basic block.
if (BasicBlock *Exit = R.getExit()) {
BasicBlock::iterator I = Exit->begin();
- if (I != Exit->end() && isa<PHINode>(*I)) {
- INVALID(Other, "PHI node in exit BB");
- return false;
- }
+ if (I != Exit->end() && isa<PHINode>(*I))
+ return invalid<ReportPHIinExit>(Context, /*Assert=*/true);
}
return true;
Loop *L = LI->getLoopFor(entry);
if (L) {
- if (!L->isLoopSimplifyForm()) {
- INVALID(SimpleLoop, "Loop not in simplify form is invalid!");
- return false;
- }
+ if (!L->isLoopSimplifyForm())
+ return invalid<ReportSimpleLoop>(Context, /*Assert=*/true);
for (pred_iterator PI = pred_begin(entry), PE = pred_end(entry); PI != PE;
++PI) {
// Region entering edges come from the same loop but outside the region
// are not allowed.
- if (L->contains(*PI) && !R.contains(*PI)) {
- INVALID(IndEdge, "Region has invalid entering edges!");
- return false;
- }
+ if (L->contains(*PI) && !R.contains(*PI))
+ return invalid<ReportIndEdge>(Context, /*Assert=*/true);
}
}
}
// SCoP cannot contain the entry block of the function, because we need
// to insert alloca instruction there when translate scalar to array.
- if (R.getEntry() == &(R.getEntry()->getParent()->getEntryBlock())) {
- INVALID(Other, "Region containing entry block of function is invalid!");
- return false;
- }
+ if (R.getEntry() == &(R.getEntry()->getParent()->getEntryBlock()))
+ return invalid<ReportEntry>(Context, /*Assert=*/true);
if (!isValidExit(Context))
return false;