1 //===- ScopDetectionDiagnostic.cpp - Error diagnostics --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Small set of diagnostic helper classes to encapsulate any errors occurred 10 // during the detection of Scops. 11 // 12 // The ScopDetection defines a set of error classes (via Statistic variables) 13 // that groups a number of individual errors into a group, e.g. non-affinity 14 // related errors. 15 // On error we generate an object that carries enough additional information 16 // to diagnose the error and generate a helpful error message. 17 // 18 //===----------------------------------------------------------------------===// 19 20 #include "polly/ScopDetectionDiagnostic.h" 21 #include "llvm/ADT/SmallPtrSet.h" 22 #include "llvm/ADT/SmallVector.h" 23 #include "llvm/ADT/Statistic.h" 24 #include "llvm/ADT/StringRef.h" 25 #include "llvm/ADT/Twine.h" 26 #include "llvm/Analysis/AliasSetTracker.h" 27 #include "llvm/Analysis/LoopInfo.h" 28 #include "llvm/Analysis/OptimizationRemarkEmitter.h" 29 #include "llvm/Analysis/RegionInfo.h" 30 #include "llvm/Analysis/ScalarEvolution.h" 31 #include "llvm/IR/BasicBlock.h" 32 #include "llvm/IR/CFG.h" 33 #include "llvm/IR/DebugLoc.h" 34 #include "llvm/IR/DiagnosticInfo.h" 35 #include "llvm/IR/Instruction.h" 36 #include "llvm/IR/Value.h" 37 #include "llvm/Support/raw_ostream.h" 38 #include <algorithm> 39 #include <cassert> 40 #include <string> 41 #include <utility> 42 43 using namespace llvm; 44 45 #define DEBUG_TYPE "polly-detect" 46 47 #define SCOP_STAT(NAME, DESC) \ 48 { "polly-detect", "NAME", "Number of rejected regions: " DESC } 49 50 static Statistic RejectStatistics[] = { 51 SCOP_STAT(CFG, ""), 52 SCOP_STAT(InvalidTerminator, "Unsupported terminator instruction"), 53 SCOP_STAT(UnreachableInExit, "Unreachable in exit block"), 54 SCOP_STAT(IrreducibleRegion, "Irreducible loops"), 55 SCOP_STAT(LastCFG, ""), 56 SCOP_STAT(AffFunc, ""), 57 SCOP_STAT(UndefCond, "Undefined branch condition"), 58 SCOP_STAT(InvalidCond, "Non-integer branch condition"), 59 SCOP_STAT(UndefOperand, "Undefined operands in comparison"), 60 SCOP_STAT(NonAffBranch, "Non-affine branch condition"), 61 SCOP_STAT(NoBasePtr, "No base pointer"), 62 SCOP_STAT(UndefBasePtr, "Undefined base pointer"), 63 SCOP_STAT(VariantBasePtr, "Variant base pointer"), 64 SCOP_STAT(NonAffineAccess, "Non-affine memory accesses"), 65 SCOP_STAT(DifferentElementSize, "Accesses with differing sizes"), 66 SCOP_STAT(LastAffFunc, ""), 67 SCOP_STAT(LoopBound, "Uncomputable loop bounds"), 68 SCOP_STAT(LoopHasNoExit, "Loop without exit"), 69 SCOP_STAT(LoopHasMultipleExits, "Loop with multiple exits"), 70 SCOP_STAT(LoopOnlySomeLatches, "Not all loop latches in scop"), 71 SCOP_STAT(FuncCall, "Function call with side effects"), 72 SCOP_STAT(NonSimpleMemoryAccess, 73 "Compilated access semantics (volatile or atomic)"), 74 SCOP_STAT(Alias, "Base address aliasing"), 75 SCOP_STAT(Other, ""), 76 SCOP_STAT(IntToPtr, "Integer to pointer conversions"), 77 SCOP_STAT(Alloca, "Stack allocations"), 78 SCOP_STAT(UnknownInst, "Unknown Instructions"), 79 SCOP_STAT(Entry, "Contains entry block"), 80 SCOP_STAT(Unprofitable, "Assumed to be unprofitable"), 81 SCOP_STAT(LastOther, ""), 82 }; 83 84 namespace polly { 85 86 /// Small string conversion via raw_string_stream. 87 template <typename T> std::string operator+(Twine LHS, const T &RHS) { 88 std::string Buf; 89 raw_string_ostream fmt(Buf); 90 fmt << RHS; 91 fmt.flush(); 92 93 return LHS.concat(Buf).str(); 94 } 95 } // namespace polly 96 97 namespace llvm { 98 99 // Lexicographic order on (line, col) of our debug locations. 100 static bool operator<(const DebugLoc &LHS, const DebugLoc &RHS) { 101 return LHS.getLine() < RHS.getLine() || 102 (LHS.getLine() == RHS.getLine() && LHS.getCol() < RHS.getCol()); 103 } 104 } // namespace llvm 105 106 namespace polly { 107 108 BBPair getBBPairForRegion(const Region *R) { 109 return std::make_pair(R->getEntry(), R->getExit()); 110 } 111 112 void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End) { 113 SmallPtrSet<BasicBlock *, 32> Seen; 114 SmallVector<BasicBlock *, 32> Todo; 115 Todo.push_back(P.first); 116 while (!Todo.empty()) { 117 auto *BB = Todo.pop_back_val(); 118 if (BB == P.second) 119 continue; 120 if (!Seen.insert(BB).second) 121 continue; 122 Todo.append(succ_begin(BB), succ_end(BB)); 123 for (const Instruction &Inst : *BB) { 124 DebugLoc DL = Inst.getDebugLoc(); 125 if (!DL) 126 continue; 127 128 Begin = Begin ? std::min(Begin, DL) : DL; 129 End = End ? std::max(End, DL) : DL; 130 } 131 } 132 } 133 134 void emitRejectionRemarks(const BBPair &P, const RejectLog &Log, 135 OptimizationRemarkEmitter &ORE) { 136 DebugLoc Begin, End; 137 getDebugLocations(P, Begin, End); 138 139 ORE.emit( 140 OptimizationRemarkMissed(DEBUG_TYPE, "RejectionErrors", Begin, P.first) 141 << "The following errors keep this region from being a Scop."); 142 143 for (RejectReasonPtr RR : Log) { 144 145 if (const DebugLoc &Loc = RR->getDebugLoc()) 146 ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Loc, 147 RR->getRemarkBB()) 148 << RR->getEndUserMessage()); 149 else 150 ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Begin, 151 RR->getRemarkBB()) 152 << RR->getEndUserMessage()); 153 } 154 155 /* Check to see if Region is a top level region, getExit = NULL*/ 156 if (P.second) 157 ORE.emit( 158 OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.second) 159 << "Invalid Scop candidate ends here."); 160 else 161 ORE.emit( 162 OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.first) 163 << "Invalid Scop candidate ends here."); 164 } 165 166 //===----------------------------------------------------------------------===// 167 // RejectReason. 168 169 RejectReason::RejectReason(RejectReasonKind K) : Kind(K) { 170 RejectStatistics[static_cast<int>(K)]++; 171 } 172 173 const DebugLoc RejectReason::Unknown = DebugLoc(); 174 175 const DebugLoc &RejectReason::getDebugLoc() const { 176 // Allocate an empty DebugLoc and return it a reference to it. 177 return Unknown; 178 } 179 180 // RejectLog. 181 void RejectLog::print(raw_ostream &OS, int level) const { 182 int j = 0; 183 for (auto Reason : ErrorReports) 184 OS.indent(level) << "[" << j++ << "] " << Reason->getMessage() << "\n"; 185 } 186 187 //===----------------------------------------------------------------------===// 188 // ReportCFG. 189 190 ReportCFG::ReportCFG(const RejectReasonKind K) : RejectReason(K) {} 191 192 bool ReportCFG::classof(const RejectReason *RR) { 193 return RR->getKind() >= RejectReasonKind::CFG && 194 RR->getKind() <= RejectReasonKind::LastCFG; 195 } 196 197 //===----------------------------------------------------------------------===// 198 // ReportInvalidTerminator. 199 200 std::string ReportInvalidTerminator::getRemarkName() const { 201 return "InvalidTerminator"; 202 } 203 204 const Value *ReportInvalidTerminator::getRemarkBB() const { return BB; } 205 206 std::string ReportInvalidTerminator::getMessage() const { 207 return ("Invalid instruction terminates BB: " + BB->getName()).str(); 208 } 209 210 const DebugLoc &ReportInvalidTerminator::getDebugLoc() const { 211 return BB->getTerminator()->getDebugLoc(); 212 } 213 214 bool ReportInvalidTerminator::classof(const RejectReason *RR) { 215 return RR->getKind() == RejectReasonKind::InvalidTerminator; 216 } 217 218 //===----------------------------------------------------------------------===// 219 // UnreachableInExit. 220 221 std::string ReportUnreachableInExit::getRemarkName() const { 222 return "UnreachableInExit"; 223 } 224 225 const Value *ReportUnreachableInExit::getRemarkBB() const { return BB; } 226 227 std::string ReportUnreachableInExit::getMessage() const { 228 std::string BBName = BB->getName().str(); 229 return "Unreachable in exit block" + BBName; 230 } 231 232 const DebugLoc &ReportUnreachableInExit::getDebugLoc() const { return DbgLoc; } 233 234 std::string ReportUnreachableInExit::getEndUserMessage() const { 235 return "Unreachable in exit block."; 236 } 237 238 bool ReportUnreachableInExit::classof(const RejectReason *RR) { 239 return RR->getKind() == RejectReasonKind::UnreachableInExit; 240 } 241 242 //===----------------------------------------------------------------------===// 243 // ReportIrreducibleRegion. 244 245 std::string ReportIrreducibleRegion::getRemarkName() const { 246 return "IrreducibleRegion"; 247 } 248 249 const Value *ReportIrreducibleRegion::getRemarkBB() const { 250 return R->getEntry(); 251 } 252 253 std::string ReportIrreducibleRegion::getMessage() const { 254 return "Irreducible region encountered: " + R->getNameStr(); 255 } 256 257 const DebugLoc &ReportIrreducibleRegion::getDebugLoc() const { return DbgLoc; } 258 259 std::string ReportIrreducibleRegion::getEndUserMessage() const { 260 return "Irreducible region encountered in control flow."; 261 } 262 263 bool ReportIrreducibleRegion::classof(const RejectReason *RR) { 264 return RR->getKind() == RejectReasonKind::IrreducibleRegion; 265 } 266 267 //===----------------------------------------------------------------------===// 268 // ReportAffFunc. 269 270 ReportAffFunc::ReportAffFunc(const RejectReasonKind K, const Instruction *Inst) 271 : RejectReason(K), Inst(Inst) {} 272 273 bool ReportAffFunc::classof(const RejectReason *RR) { 274 return RR->getKind() >= RejectReasonKind::AffFunc && 275 RR->getKind() <= RejectReasonKind::LastAffFunc; 276 } 277 278 //===----------------------------------------------------------------------===// 279 // ReportUndefCond. 280 281 std::string ReportUndefCond::getRemarkName() const { return "UndefCond"; } 282 283 const Value *ReportUndefCond::getRemarkBB() const { return BB; } 284 285 std::string ReportUndefCond::getMessage() const { 286 return ("Condition based on 'undef' value in BB: " + BB->getName()).str(); 287 } 288 289 bool ReportUndefCond::classof(const RejectReason *RR) { 290 return RR->getKind() == RejectReasonKind::UndefCond; 291 } 292 293 //===----------------------------------------------------------------------===// 294 // ReportInvalidCond. 295 296 std::string ReportInvalidCond::getRemarkName() const { return "InvalidCond"; } 297 298 const Value *ReportInvalidCond::getRemarkBB() const { return BB; } 299 300 std::string ReportInvalidCond::getMessage() const { 301 return ("Condition in BB '" + BB->getName()).str() + 302 "' neither constant nor an icmp instruction"; 303 } 304 305 bool ReportInvalidCond::classof(const RejectReason *RR) { 306 return RR->getKind() == RejectReasonKind::InvalidCond; 307 } 308 309 //===----------------------------------------------------------------------===// 310 // ReportUndefOperand. 311 312 std::string ReportUndefOperand::getRemarkName() const { return "UndefOperand"; } 313 314 const Value *ReportUndefOperand::getRemarkBB() const { return BB; } 315 316 std::string ReportUndefOperand::getMessage() const { 317 return ("undef operand in branch at BB: " + BB->getName()).str(); 318 } 319 320 bool ReportUndefOperand::classof(const RejectReason *RR) { 321 return RR->getKind() == RejectReasonKind::UndefOperand; 322 } 323 324 //===----------------------------------------------------------------------===// 325 // ReportNonAffBranch. 326 327 std::string ReportNonAffBranch::getRemarkName() const { return "NonAffBranch"; } 328 329 const Value *ReportNonAffBranch::getRemarkBB() const { return BB; } 330 331 std::string ReportNonAffBranch::getMessage() const { 332 return ("Non affine branch in BB '" + BB->getName()).str() + 333 "' with LHS: " + *LHS + " and RHS: " + *RHS; 334 } 335 336 bool ReportNonAffBranch::classof(const RejectReason *RR) { 337 return RR->getKind() == RejectReasonKind::NonAffBranch; 338 } 339 340 //===----------------------------------------------------------------------===// 341 // ReportNoBasePtr. 342 343 std::string ReportNoBasePtr::getRemarkName() const { return "NoBasePtr"; } 344 345 const Value *ReportNoBasePtr::getRemarkBB() const { return Inst->getParent(); } 346 347 std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; } 348 349 bool ReportNoBasePtr::classof(const RejectReason *RR) { 350 return RR->getKind() == RejectReasonKind::NoBasePtr; 351 } 352 353 //===----------------------------------------------------------------------===// 354 // ReportUndefBasePtr. 355 356 std::string ReportUndefBasePtr::getRemarkName() const { return "UndefBasePtr"; } 357 358 const Value *ReportUndefBasePtr::getRemarkBB() const { 359 return Inst->getParent(); 360 } 361 362 std::string ReportUndefBasePtr::getMessage() const { 363 return "Undefined base pointer"; 364 } 365 366 bool ReportUndefBasePtr::classof(const RejectReason *RR) { 367 return RR->getKind() == RejectReasonKind::UndefBasePtr; 368 } 369 370 //===----------------------------------------------------------------------===// 371 // ReportVariantBasePtr. 372 373 std::string ReportVariantBasePtr::getRemarkName() const { 374 return "VariantBasePtr"; 375 } 376 377 const Value *ReportVariantBasePtr::getRemarkBB() const { 378 return Inst->getParent(); 379 } 380 381 std::string ReportVariantBasePtr::getMessage() const { 382 return "Base address not invariant in current region:" + *BaseValue; 383 } 384 385 std::string ReportVariantBasePtr::getEndUserMessage() const { 386 return "The base address of this array is not invariant inside the loop"; 387 } 388 389 bool ReportVariantBasePtr::classof(const RejectReason *RR) { 390 return RR->getKind() == RejectReasonKind::VariantBasePtr; 391 } 392 393 //===----------------------------------------------------------------------===// 394 // ReportDifferentArrayElementSize 395 396 std::string ReportDifferentArrayElementSize::getRemarkName() const { 397 return "DifferentArrayElementSize"; 398 } 399 400 const Value *ReportDifferentArrayElementSize::getRemarkBB() const { 401 return Inst->getParent(); 402 } 403 404 std::string ReportDifferentArrayElementSize::getMessage() const { 405 return "Access to one array through data types of different size"; 406 } 407 408 bool ReportDifferentArrayElementSize::classof(const RejectReason *RR) { 409 return RR->getKind() == RejectReasonKind::DifferentElementSize; 410 } 411 412 std::string ReportDifferentArrayElementSize::getEndUserMessage() const { 413 StringRef BaseName = BaseValue->getName(); 414 std::string Name = BaseName.empty() ? "UNKNOWN" : BaseName.str(); 415 return "The array \"" + Name + 416 "\" is accessed through elements that differ " 417 "in size"; 418 } 419 420 //===----------------------------------------------------------------------===// 421 // ReportNonAffineAccess. 422 423 std::string ReportNonAffineAccess::getRemarkName() const { 424 return "NonAffineAccess"; 425 } 426 427 const Value *ReportNonAffineAccess::getRemarkBB() const { 428 return Inst->getParent(); 429 } 430 431 std::string ReportNonAffineAccess::getMessage() const { 432 return "Non affine access function: " + *AccessFunction; 433 } 434 435 bool ReportNonAffineAccess::classof(const RejectReason *RR) { 436 return RR->getKind() == RejectReasonKind::NonAffineAccess; 437 } 438 439 std::string ReportNonAffineAccess::getEndUserMessage() const { 440 StringRef BaseName = BaseValue->getName(); 441 std::string Name = BaseName.empty() ? "UNKNOWN" : BaseName.str(); 442 return "The array subscript of \"" + Name + "\" is not affine"; 443 } 444 445 //===----------------------------------------------------------------------===// 446 // ReportLoopBound. 447 448 ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount) 449 : RejectReason(RejectReasonKind::LoopBound), L(L), LoopCount(LoopCount), 450 Loc(L->getStartLoc()) {} 451 452 std::string ReportLoopBound::getRemarkName() const { return "LoopBound"; } 453 454 const Value *ReportLoopBound::getRemarkBB() const { return L->getHeader(); } 455 456 std::string ReportLoopBound::getMessage() const { 457 return "Non affine loop bound '" + *LoopCount + 458 "' in loop: " + L->getHeader()->getName(); 459 } 460 461 const DebugLoc &ReportLoopBound::getDebugLoc() const { return Loc; } 462 463 bool ReportLoopBound::classof(const RejectReason *RR) { 464 return RR->getKind() == RejectReasonKind::LoopBound; 465 } 466 467 std::string ReportLoopBound::getEndUserMessage() const { 468 return "Failed to derive an affine function from the loop bounds."; 469 } 470 471 //===----------------------------------------------------------------------===// 472 // ReportLoopHasNoExit. 473 474 std::string ReportLoopHasNoExit::getRemarkName() const { 475 return "LoopHasNoExit"; 476 } 477 478 const Value *ReportLoopHasNoExit::getRemarkBB() const { return L->getHeader(); } 479 480 std::string ReportLoopHasNoExit::getMessage() const { 481 return "Loop " + L->getHeader()->getName() + " has no exit."; 482 } 483 484 bool ReportLoopHasNoExit::classof(const RejectReason *RR) { 485 return RR->getKind() == RejectReasonKind::LoopHasNoExit; 486 } 487 488 const DebugLoc &ReportLoopHasNoExit::getDebugLoc() const { return Loc; } 489 490 std::string ReportLoopHasNoExit::getEndUserMessage() const { 491 return "Loop cannot be handled because it has no exit."; 492 } 493 494 //===----------------------------------------------------------------------===// 495 // ReportLoopHasMultipleExits. 496 497 std::string ReportLoopHasMultipleExits::getRemarkName() const { 498 return "ReportLoopHasMultipleExits"; 499 } 500 501 const Value *ReportLoopHasMultipleExits::getRemarkBB() const { 502 return L->getHeader(); 503 } 504 505 std::string ReportLoopHasMultipleExits::getMessage() const { 506 return "Loop " + L->getHeader()->getName() + " has multiple exits."; 507 } 508 509 bool ReportLoopHasMultipleExits::classof(const RejectReason *RR) { 510 return RR->getKind() == RejectReasonKind::LoopHasMultipleExits; 511 } 512 513 const DebugLoc &ReportLoopHasMultipleExits::getDebugLoc() const { return Loc; } 514 515 std::string ReportLoopHasMultipleExits::getEndUserMessage() const { 516 return "Loop cannot be handled because it has multiple exits."; 517 } 518 519 //===----------------------------------------------------------------------===// 520 // ReportLoopOnlySomeLatches 521 522 std::string ReportLoopOnlySomeLatches::getRemarkName() const { 523 return "LoopHasNoExit"; 524 } 525 526 const Value *ReportLoopOnlySomeLatches::getRemarkBB() const { 527 return L->getHeader(); 528 } 529 530 std::string ReportLoopOnlySomeLatches::getMessage() const { 531 return "Not all latches of loop " + L->getHeader()->getName() + 532 " part of scop."; 533 } 534 535 bool ReportLoopOnlySomeLatches::classof(const RejectReason *RR) { 536 return RR->getKind() == RejectReasonKind::LoopHasNoExit; 537 } 538 539 const DebugLoc &ReportLoopOnlySomeLatches::getDebugLoc() const { return Loc; } 540 541 std::string ReportLoopOnlySomeLatches::getEndUserMessage() const { 542 return "Loop cannot be handled because not all latches are part of loop " 543 "region."; 544 } 545 546 //===----------------------------------------------------------------------===// 547 // ReportFuncCall. 548 549 ReportFuncCall::ReportFuncCall(Instruction *Inst) 550 : RejectReason(RejectReasonKind::FuncCall), Inst(Inst) {} 551 552 std::string ReportFuncCall::getRemarkName() const { return "FuncCall"; } 553 554 const Value *ReportFuncCall::getRemarkBB() const { return Inst->getParent(); } 555 556 std::string ReportFuncCall::getMessage() const { 557 return "Call instruction: " + *Inst; 558 } 559 560 const DebugLoc &ReportFuncCall::getDebugLoc() const { 561 return Inst->getDebugLoc(); 562 } 563 564 std::string ReportFuncCall::getEndUserMessage() const { 565 return "This function call cannot be handled. " 566 "Try to inline it."; 567 } 568 569 bool ReportFuncCall::classof(const RejectReason *RR) { 570 return RR->getKind() == RejectReasonKind::FuncCall; 571 } 572 573 //===----------------------------------------------------------------------===// 574 // ReportNonSimpleMemoryAccess 575 576 ReportNonSimpleMemoryAccess::ReportNonSimpleMemoryAccess(Instruction *Inst) 577 : ReportOther(RejectReasonKind::NonSimpleMemoryAccess), Inst(Inst) {} 578 579 std::string ReportNonSimpleMemoryAccess::getRemarkName() const { 580 return "NonSimpleMemoryAccess"; 581 } 582 583 const Value *ReportNonSimpleMemoryAccess::getRemarkBB() const { 584 return Inst->getParent(); 585 } 586 587 std::string ReportNonSimpleMemoryAccess::getMessage() const { 588 return "Non-simple memory access: " + *Inst; 589 } 590 591 const DebugLoc &ReportNonSimpleMemoryAccess::getDebugLoc() const { 592 return Inst->getDebugLoc(); 593 } 594 595 std::string ReportNonSimpleMemoryAccess::getEndUserMessage() const { 596 return "Volatile memory accesses or memory accesses for atomic types " 597 "are not supported."; 598 } 599 600 bool ReportNonSimpleMemoryAccess::classof(const RejectReason *RR) { 601 return RR->getKind() == RejectReasonKind::NonSimpleMemoryAccess; 602 } 603 604 //===----------------------------------------------------------------------===// 605 // ReportAlias. 606 607 ReportAlias::ReportAlias(Instruction *Inst, AliasSet &AS) 608 : RejectReason(RejectReasonKind::Alias), Inst(Inst) { 609 for (const auto &I : AS) 610 Pointers.push_back(I.getValue()); 611 } 612 613 std::string ReportAlias::formatInvalidAlias(std::string Prefix, 614 std::string Suffix) const { 615 std::string Message; 616 raw_string_ostream OS(Message); 617 618 OS << Prefix; 619 620 for (PointerSnapshotTy::const_iterator PI = Pointers.begin(), 621 PE = Pointers.end(); 622 ;) { 623 const Value *V = *PI; 624 assert(V && "Diagnostic info does not match found LLVM-IR anymore."); 625 626 if (V->getName().empty()) 627 OS << "\" <unknown> \""; 628 else 629 OS << "\"" << V->getName() << "\""; 630 631 ++PI; 632 633 if (PI != PE) 634 OS << ", "; 635 else 636 break; 637 } 638 639 OS << Suffix; 640 641 return OS.str(); 642 } 643 644 std::string ReportAlias::getRemarkName() const { return "Alias"; } 645 646 const Value *ReportAlias::getRemarkBB() const { return Inst->getParent(); } 647 648 std::string ReportAlias::getMessage() const { 649 return formatInvalidAlias("Possible aliasing: "); 650 } 651 652 std::string ReportAlias::getEndUserMessage() const { 653 return formatInvalidAlias("Accesses to the arrays ", 654 " may access the same memory."); 655 } 656 657 const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); } 658 659 bool ReportAlias::classof(const RejectReason *RR) { 660 return RR->getKind() == RejectReasonKind::Alias; 661 } 662 663 //===----------------------------------------------------------------------===// 664 // ReportOther. 665 666 std::string ReportOther::getRemarkName() const { return "UnknownRejectReason"; } 667 668 std::string ReportOther::getMessage() const { return "Unknown reject reason"; } 669 670 ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {} 671 672 bool ReportOther::classof(const RejectReason *RR) { 673 return RR->getKind() >= RejectReasonKind::Other && 674 RR->getKind() <= RejectReasonKind::LastOther; 675 } 676 677 //===----------------------------------------------------------------------===// 678 // ReportIntToPtr. 679 ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue) 680 : ReportOther(RejectReasonKind::IntToPtr), BaseValue(BaseValue) {} 681 682 std::string ReportIntToPtr::getRemarkName() const { return "IntToPtr"; } 683 684 const Value *ReportIntToPtr::getRemarkBB() const { 685 return BaseValue->getParent(); 686 } 687 688 std::string ReportIntToPtr::getMessage() const { 689 return "Find bad intToptr prt: " + *BaseValue; 690 } 691 692 const DebugLoc &ReportIntToPtr::getDebugLoc() const { 693 return BaseValue->getDebugLoc(); 694 } 695 696 bool ReportIntToPtr::classof(const RejectReason *RR) { 697 return RR->getKind() == RejectReasonKind::IntToPtr; 698 } 699 700 //===----------------------------------------------------------------------===// 701 // ReportAlloca. 702 703 ReportAlloca::ReportAlloca(Instruction *Inst) 704 : ReportOther(RejectReasonKind::Alloca), Inst(Inst) {} 705 706 std::string ReportAlloca::getRemarkName() const { return "Alloca"; } 707 708 const Value *ReportAlloca::getRemarkBB() const { return Inst->getParent(); } 709 710 std::string ReportAlloca::getMessage() const { 711 return "Alloca instruction: " + *Inst; 712 } 713 714 const DebugLoc &ReportAlloca::getDebugLoc() const { 715 return Inst->getDebugLoc(); 716 } 717 718 bool ReportAlloca::classof(const RejectReason *RR) { 719 return RR->getKind() == RejectReasonKind::Alloca; 720 } 721 722 //===----------------------------------------------------------------------===// 723 // ReportUnknownInst. 724 725 ReportUnknownInst::ReportUnknownInst(Instruction *Inst) 726 : ReportOther(RejectReasonKind::UnknownInst), Inst(Inst) {} 727 728 std::string ReportUnknownInst::getRemarkName() const { return "UnknownInst"; } 729 730 const Value *ReportUnknownInst::getRemarkBB() const { 731 return Inst->getParent(); 732 } 733 734 std::string ReportUnknownInst::getMessage() const { 735 return "Unknown instruction: " + *Inst; 736 } 737 738 const DebugLoc &ReportUnknownInst::getDebugLoc() const { 739 return Inst->getDebugLoc(); 740 } 741 742 bool ReportUnknownInst::classof(const RejectReason *RR) { 743 return RR->getKind() == RejectReasonKind::UnknownInst; 744 } 745 746 //===----------------------------------------------------------------------===// 747 // ReportEntry. 748 749 ReportEntry::ReportEntry(BasicBlock *BB) 750 : ReportOther(RejectReasonKind::Entry), BB(BB) {} 751 752 std::string ReportEntry::getRemarkName() const { return "Entry"; } 753 754 const Value *ReportEntry::getRemarkBB() const { return BB; } 755 756 std::string ReportEntry::getMessage() const { 757 return "Region containing entry block of function is invalid!"; 758 } 759 760 std::string ReportEntry::getEndUserMessage() const { 761 return "Scop contains function entry (not yet supported)."; 762 } 763 764 const DebugLoc &ReportEntry::getDebugLoc() const { 765 return BB->getTerminator()->getDebugLoc(); 766 } 767 768 bool ReportEntry::classof(const RejectReason *RR) { 769 return RR->getKind() == RejectReasonKind::Entry; 770 } 771 772 //===----------------------------------------------------------------------===// 773 // ReportUnprofitable. 774 775 ReportUnprofitable::ReportUnprofitable(Region *R) 776 : ReportOther(RejectReasonKind::Unprofitable), R(R) {} 777 778 std::string ReportUnprofitable::getRemarkName() const { return "Unprofitable"; } 779 780 const Value *ReportUnprofitable::getRemarkBB() const { return R->getEntry(); } 781 782 std::string ReportUnprofitable::getMessage() const { 783 return "Region can not profitably be optimized!"; 784 } 785 786 std::string ReportUnprofitable::getEndUserMessage() const { 787 return "No profitable polyhedral optimization found"; 788 } 789 790 const DebugLoc &ReportUnprofitable::getDebugLoc() const { 791 for (const BasicBlock *BB : R->blocks()) 792 for (const Instruction &Inst : *BB) 793 if (const DebugLoc &DL = Inst.getDebugLoc()) 794 return DL; 795 796 return R->getEntry()->getTerminator()->getDebugLoc(); 797 } 798 799 bool ReportUnprofitable::classof(const RejectReason *RR) { 800 return RR->getKind() == RejectReasonKind::Unprofitable; 801 } 802 } // namespace polly 803