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(IrreducibleRegion, "Irreducible loops"), 54 SCOP_STAT(UnreachableInExit, "Unreachable in exit block"), 55 SCOP_STAT(IndirectPredecessor, "Branch from indirect terminator"), 56 SCOP_STAT(LastCFG, ""), 57 SCOP_STAT(AffFunc, ""), 58 SCOP_STAT(UndefCond, "Undefined branch condition"), 59 SCOP_STAT(InvalidCond, "Non-integer branch condition"), 60 SCOP_STAT(UndefOperand, "Undefined operands in comparison"), 61 SCOP_STAT(NonAffBranch, "Non-affine branch condition"), 62 SCOP_STAT(NoBasePtr, "No base pointer"), 63 SCOP_STAT(UndefBasePtr, "Undefined base pointer"), 64 SCOP_STAT(VariantBasePtr, "Variant base pointer"), 65 SCOP_STAT(NonAffineAccess, "Non-affine memory accesses"), 66 SCOP_STAT(DifferentElementSize, "Accesses with differing sizes"), 67 SCOP_STAT(LastAffFunc, ""), 68 SCOP_STAT(LoopBound, "Uncomputable loop bounds"), 69 SCOP_STAT(LoopHasNoExit, "Loop without exit"), 70 SCOP_STAT(LoopHasMultipleExits, "Loop with multiple exits"), 71 SCOP_STAT(LoopOnlySomeLatches, "Not all loop latches in scop"), 72 SCOP_STAT(FuncCall, "Function call with side effects"), 73 SCOP_STAT(NonSimpleMemoryAccess, 74 "Complicated access semantics (volatile or atomic)"), 75 SCOP_STAT(Alias, "Base address aliasing"), 76 SCOP_STAT(Other, ""), 77 SCOP_STAT(IntToPtr, "Integer to pointer conversions"), 78 SCOP_STAT(Alloca, "Stack allocations"), 79 SCOP_STAT(UnknownInst, "Unknown Instructions"), 80 SCOP_STAT(Entry, "Contains entry block"), 81 SCOP_STAT(Unprofitable, "Assumed to be unprofitable"), 82 SCOP_STAT(LastOther, ""), 83 }; 84 85 namespace polly { 86 87 /// Small string conversion via raw_string_stream. 88 template <typename T> std::string operator+(Twine LHS, const T &RHS) { 89 std::string Buf; 90 raw_string_ostream fmt(Buf); 91 fmt << RHS; 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.getStableDebugLoc(); 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 // IndirectPredecessor. 244 245 std::string ReportIndirectPredecessor::getRemarkName() const { 246 return "IndirectPredecessor"; 247 } 248 249 const Value *ReportIndirectPredecessor::getRemarkBB() const { 250 if (Inst) 251 return Inst->getParent(); 252 return nullptr; 253 } 254 255 std::string ReportIndirectPredecessor::getMessage() const { 256 if (Inst) 257 return "Branch from indirect terminator: " + *Inst; 258 return getEndUserMessage(); 259 } 260 261 const DebugLoc &ReportIndirectPredecessor::getDebugLoc() const { 262 return DbgLoc; 263 } 264 265 std::string ReportIndirectPredecessor::getEndUserMessage() const { 266 return "Branch from indirect terminator."; 267 } 268 269 bool ReportIndirectPredecessor::classof(const RejectReason *RR) { 270 return RR->getKind() == RejectReasonKind::IndirectPredecessor; 271 } 272 273 //===----------------------------------------------------------------------===// 274 // ReportIrreducibleRegion. 275 276 std::string ReportIrreducibleRegion::getRemarkName() const { 277 return "IrreducibleRegion"; 278 } 279 280 const Value *ReportIrreducibleRegion::getRemarkBB() const { 281 return R->getEntry(); 282 } 283 284 std::string ReportIrreducibleRegion::getMessage() const { 285 return "Irreducible region encountered: " + R->getNameStr(); 286 } 287 288 const DebugLoc &ReportIrreducibleRegion::getDebugLoc() const { return DbgLoc; } 289 290 std::string ReportIrreducibleRegion::getEndUserMessage() const { 291 return "Irreducible region encountered in control flow."; 292 } 293 294 bool ReportIrreducibleRegion::classof(const RejectReason *RR) { 295 return RR->getKind() == RejectReasonKind::IrreducibleRegion; 296 } 297 298 //===----------------------------------------------------------------------===// 299 // ReportAffFunc. 300 301 ReportAffFunc::ReportAffFunc(const RejectReasonKind K, const Instruction *Inst) 302 : RejectReason(K), Inst(Inst) {} 303 304 bool ReportAffFunc::classof(const RejectReason *RR) { 305 return RR->getKind() >= RejectReasonKind::AffFunc && 306 RR->getKind() <= RejectReasonKind::LastAffFunc; 307 } 308 309 //===----------------------------------------------------------------------===// 310 // ReportUndefCond. 311 312 std::string ReportUndefCond::getRemarkName() const { return "UndefCond"; } 313 314 const Value *ReportUndefCond::getRemarkBB() const { return BB; } 315 316 std::string ReportUndefCond::getMessage() const { 317 return ("Condition based on 'undef' value in BB: " + BB->getName()).str(); 318 } 319 320 bool ReportUndefCond::classof(const RejectReason *RR) { 321 return RR->getKind() == RejectReasonKind::UndefCond; 322 } 323 324 //===----------------------------------------------------------------------===// 325 // ReportInvalidCond. 326 327 std::string ReportInvalidCond::getRemarkName() const { return "InvalidCond"; } 328 329 const Value *ReportInvalidCond::getRemarkBB() const { return BB; } 330 331 std::string ReportInvalidCond::getMessage() const { 332 return ("Condition in BB '" + BB->getName()).str() + 333 "' neither constant nor an icmp instruction"; 334 } 335 336 bool ReportInvalidCond::classof(const RejectReason *RR) { 337 return RR->getKind() == RejectReasonKind::InvalidCond; 338 } 339 340 //===----------------------------------------------------------------------===// 341 // ReportUndefOperand. 342 343 std::string ReportUndefOperand::getRemarkName() const { return "UndefOperand"; } 344 345 const Value *ReportUndefOperand::getRemarkBB() const { return BB; } 346 347 std::string ReportUndefOperand::getMessage() const { 348 return ("undef operand in branch at BB: " + BB->getName()).str(); 349 } 350 351 bool ReportUndefOperand::classof(const RejectReason *RR) { 352 return RR->getKind() == RejectReasonKind::UndefOperand; 353 } 354 355 //===----------------------------------------------------------------------===// 356 // ReportNonAffBranch. 357 358 std::string ReportNonAffBranch::getRemarkName() const { return "NonAffBranch"; } 359 360 const Value *ReportNonAffBranch::getRemarkBB() const { return BB; } 361 362 std::string ReportNonAffBranch::getMessage() const { 363 return ("Non affine branch in BB '" + BB->getName()).str() + 364 "' with LHS: " + *LHS + " and RHS: " + *RHS; 365 } 366 367 bool ReportNonAffBranch::classof(const RejectReason *RR) { 368 return RR->getKind() == RejectReasonKind::NonAffBranch; 369 } 370 371 //===----------------------------------------------------------------------===// 372 // ReportNoBasePtr. 373 374 std::string ReportNoBasePtr::getRemarkName() const { return "NoBasePtr"; } 375 376 const Value *ReportNoBasePtr::getRemarkBB() const { return Inst->getParent(); } 377 378 std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; } 379 380 bool ReportNoBasePtr::classof(const RejectReason *RR) { 381 return RR->getKind() == RejectReasonKind::NoBasePtr; 382 } 383 384 //===----------------------------------------------------------------------===// 385 // ReportUndefBasePtr. 386 387 std::string ReportUndefBasePtr::getRemarkName() const { return "UndefBasePtr"; } 388 389 const Value *ReportUndefBasePtr::getRemarkBB() const { 390 return Inst->getParent(); 391 } 392 393 std::string ReportUndefBasePtr::getMessage() const { 394 return "Undefined base pointer"; 395 } 396 397 bool ReportUndefBasePtr::classof(const RejectReason *RR) { 398 return RR->getKind() == RejectReasonKind::UndefBasePtr; 399 } 400 401 //===----------------------------------------------------------------------===// 402 // ReportVariantBasePtr. 403 404 std::string ReportVariantBasePtr::getRemarkName() const { 405 return "VariantBasePtr"; 406 } 407 408 const Value *ReportVariantBasePtr::getRemarkBB() const { 409 return Inst->getParent(); 410 } 411 412 std::string ReportVariantBasePtr::getMessage() const { 413 return "Base address not invariant in current region:" + *BaseValue; 414 } 415 416 std::string ReportVariantBasePtr::getEndUserMessage() const { 417 return "The base address of this array is not invariant inside the loop"; 418 } 419 420 bool ReportVariantBasePtr::classof(const RejectReason *RR) { 421 return RR->getKind() == RejectReasonKind::VariantBasePtr; 422 } 423 424 //===----------------------------------------------------------------------===// 425 // ReportDifferentArrayElementSize 426 427 std::string ReportDifferentArrayElementSize::getRemarkName() const { 428 return "DifferentArrayElementSize"; 429 } 430 431 const Value *ReportDifferentArrayElementSize::getRemarkBB() const { 432 return Inst->getParent(); 433 } 434 435 std::string ReportDifferentArrayElementSize::getMessage() const { 436 return "Access to one array through data types of different size"; 437 } 438 439 bool ReportDifferentArrayElementSize::classof(const RejectReason *RR) { 440 return RR->getKind() == RejectReasonKind::DifferentElementSize; 441 } 442 443 std::string ReportDifferentArrayElementSize::getEndUserMessage() const { 444 StringRef BaseName = BaseValue->getName(); 445 std::string Name = BaseName.empty() ? "UNKNOWN" : BaseName.str(); 446 return "The array \"" + Name + 447 "\" is accessed through elements that differ " 448 "in size"; 449 } 450 451 //===----------------------------------------------------------------------===// 452 // ReportNonAffineAccess. 453 454 std::string ReportNonAffineAccess::getRemarkName() const { 455 return "NonAffineAccess"; 456 } 457 458 const Value *ReportNonAffineAccess::getRemarkBB() const { 459 return Inst->getParent(); 460 } 461 462 std::string ReportNonAffineAccess::getMessage() const { 463 return "Non affine access function: " + *AccessFunction; 464 } 465 466 bool ReportNonAffineAccess::classof(const RejectReason *RR) { 467 return RR->getKind() == RejectReasonKind::NonAffineAccess; 468 } 469 470 std::string ReportNonAffineAccess::getEndUserMessage() const { 471 StringRef BaseName = BaseValue->getName(); 472 std::string Name = BaseName.empty() ? "UNKNOWN" : BaseName.str(); 473 return "The array subscript of \"" + Name + "\" is not affine"; 474 } 475 476 //===----------------------------------------------------------------------===// 477 // ReportLoopBound. 478 479 ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount) 480 : RejectReason(RejectReasonKind::LoopBound), L(L), LoopCount(LoopCount), 481 Loc(L->getStartLoc()) {} 482 483 std::string ReportLoopBound::getRemarkName() const { return "LoopBound"; } 484 485 const Value *ReportLoopBound::getRemarkBB() const { return L->getHeader(); } 486 487 std::string ReportLoopBound::getMessage() const { 488 return "Non affine loop bound '" + *LoopCount + 489 "' in loop: " + L->getHeader()->getName(); 490 } 491 492 const DebugLoc &ReportLoopBound::getDebugLoc() const { return Loc; } 493 494 bool ReportLoopBound::classof(const RejectReason *RR) { 495 return RR->getKind() == RejectReasonKind::LoopBound; 496 } 497 498 std::string ReportLoopBound::getEndUserMessage() const { 499 return "Failed to derive an affine function from the loop bounds."; 500 } 501 502 //===----------------------------------------------------------------------===// 503 // ReportLoopHasNoExit. 504 505 std::string ReportLoopHasNoExit::getRemarkName() const { 506 return "LoopHasNoExit"; 507 } 508 509 const Value *ReportLoopHasNoExit::getRemarkBB() const { return L->getHeader(); } 510 511 std::string ReportLoopHasNoExit::getMessage() const { 512 return "Loop " + L->getHeader()->getName() + " has no exit."; 513 } 514 515 bool ReportLoopHasNoExit::classof(const RejectReason *RR) { 516 return RR->getKind() == RejectReasonKind::LoopHasNoExit; 517 } 518 519 const DebugLoc &ReportLoopHasNoExit::getDebugLoc() const { return Loc; } 520 521 std::string ReportLoopHasNoExit::getEndUserMessage() const { 522 return "Loop cannot be handled because it has no exit."; 523 } 524 525 //===----------------------------------------------------------------------===// 526 // ReportLoopHasMultipleExits. 527 528 std::string ReportLoopHasMultipleExits::getRemarkName() const { 529 return "ReportLoopHasMultipleExits"; 530 } 531 532 const Value *ReportLoopHasMultipleExits::getRemarkBB() const { 533 return L->getHeader(); 534 } 535 536 std::string ReportLoopHasMultipleExits::getMessage() const { 537 return "Loop " + L->getHeader()->getName() + " has multiple exits."; 538 } 539 540 bool ReportLoopHasMultipleExits::classof(const RejectReason *RR) { 541 return RR->getKind() == RejectReasonKind::LoopHasMultipleExits; 542 } 543 544 const DebugLoc &ReportLoopHasMultipleExits::getDebugLoc() const { return Loc; } 545 546 std::string ReportLoopHasMultipleExits::getEndUserMessage() const { 547 return "Loop cannot be handled because it has multiple exits."; 548 } 549 550 //===----------------------------------------------------------------------===// 551 // ReportLoopOnlySomeLatches 552 553 std::string ReportLoopOnlySomeLatches::getRemarkName() const { 554 return "LoopHasNoExit"; 555 } 556 557 const Value *ReportLoopOnlySomeLatches::getRemarkBB() const { 558 return L->getHeader(); 559 } 560 561 std::string ReportLoopOnlySomeLatches::getMessage() const { 562 return "Not all latches of loop " + L->getHeader()->getName() + 563 " part of scop."; 564 } 565 566 bool ReportLoopOnlySomeLatches::classof(const RejectReason *RR) { 567 return RR->getKind() == RejectReasonKind::LoopHasNoExit; 568 } 569 570 const DebugLoc &ReportLoopOnlySomeLatches::getDebugLoc() const { return Loc; } 571 572 std::string ReportLoopOnlySomeLatches::getEndUserMessage() const { 573 return "Loop cannot be handled because not all latches are part of loop " 574 "region."; 575 } 576 577 //===----------------------------------------------------------------------===// 578 // ReportFuncCall. 579 580 ReportFuncCall::ReportFuncCall(Instruction *Inst) 581 : RejectReason(RejectReasonKind::FuncCall), Inst(Inst) {} 582 583 std::string ReportFuncCall::getRemarkName() const { return "FuncCall"; } 584 585 const Value *ReportFuncCall::getRemarkBB() const { return Inst->getParent(); } 586 587 std::string ReportFuncCall::getMessage() const { 588 return "Call instruction: " + *Inst; 589 } 590 591 const DebugLoc &ReportFuncCall::getDebugLoc() const { 592 return Inst->getDebugLoc(); 593 } 594 595 std::string ReportFuncCall::getEndUserMessage() const { 596 return "This function call cannot be handled. " 597 "Try to inline it."; 598 } 599 600 bool ReportFuncCall::classof(const RejectReason *RR) { 601 return RR->getKind() == RejectReasonKind::FuncCall; 602 } 603 604 //===----------------------------------------------------------------------===// 605 // ReportNonSimpleMemoryAccess 606 607 ReportNonSimpleMemoryAccess::ReportNonSimpleMemoryAccess(Instruction *Inst) 608 : ReportOther(RejectReasonKind::NonSimpleMemoryAccess), Inst(Inst) {} 609 610 std::string ReportNonSimpleMemoryAccess::getRemarkName() const { 611 return "NonSimpleMemoryAccess"; 612 } 613 614 const Value *ReportNonSimpleMemoryAccess::getRemarkBB() const { 615 return Inst->getParent(); 616 } 617 618 std::string ReportNonSimpleMemoryAccess::getMessage() const { 619 return "Non-simple memory access: " + *Inst; 620 } 621 622 const DebugLoc &ReportNonSimpleMemoryAccess::getDebugLoc() const { 623 return Inst->getDebugLoc(); 624 } 625 626 std::string ReportNonSimpleMemoryAccess::getEndUserMessage() const { 627 return "Volatile memory accesses or memory accesses for atomic types " 628 "are not supported."; 629 } 630 631 bool ReportNonSimpleMemoryAccess::classof(const RejectReason *RR) { 632 return RR->getKind() == RejectReasonKind::NonSimpleMemoryAccess; 633 } 634 635 //===----------------------------------------------------------------------===// 636 // ReportAlias. 637 638 ReportAlias::ReportAlias(Instruction *Inst, AliasSet &AS) 639 : RejectReason(RejectReasonKind::Alias), Inst(Inst) { 640 append_range(Pointers, AS.getPointers()); 641 } 642 643 std::string ReportAlias::formatInvalidAlias(std::string Prefix, 644 std::string Suffix) const { 645 std::string Message; 646 raw_string_ostream OS(Message); 647 648 OS << Prefix; 649 650 for (PointerSnapshotTy::const_iterator PI = Pointers.begin(), 651 PE = Pointers.end(); 652 ;) { 653 const Value *V = *PI; 654 assert(V && "Diagnostic info does not match found LLVM-IR anymore."); 655 656 if (V->getName().empty()) 657 OS << "\" <unknown> \""; 658 else 659 OS << "\"" << V->getName() << "\""; 660 661 ++PI; 662 663 if (PI != PE) 664 OS << ", "; 665 else 666 break; 667 } 668 669 OS << Suffix; 670 671 return Message; 672 } 673 674 std::string ReportAlias::getRemarkName() const { return "Alias"; } 675 676 const Value *ReportAlias::getRemarkBB() const { return Inst->getParent(); } 677 678 std::string ReportAlias::getMessage() const { 679 return formatInvalidAlias("Possible aliasing: "); 680 } 681 682 std::string ReportAlias::getEndUserMessage() const { 683 return formatInvalidAlias("Accesses to the arrays ", 684 " may access the same memory."); 685 } 686 687 const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); } 688 689 bool ReportAlias::classof(const RejectReason *RR) { 690 return RR->getKind() == RejectReasonKind::Alias; 691 } 692 693 //===----------------------------------------------------------------------===// 694 // ReportOther. 695 696 std::string ReportOther::getRemarkName() const { return "UnknownRejectReason"; } 697 698 std::string ReportOther::getMessage() const { return "Unknown reject reason"; } 699 700 ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {} 701 702 bool ReportOther::classof(const RejectReason *RR) { 703 return RR->getKind() >= RejectReasonKind::Other && 704 RR->getKind() <= RejectReasonKind::LastOther; 705 } 706 707 //===----------------------------------------------------------------------===// 708 // ReportIntToPtr. 709 ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue) 710 : ReportOther(RejectReasonKind::IntToPtr), BaseValue(BaseValue) {} 711 712 std::string ReportIntToPtr::getRemarkName() const { return "IntToPtr"; } 713 714 const Value *ReportIntToPtr::getRemarkBB() const { 715 return BaseValue->getParent(); 716 } 717 718 std::string ReportIntToPtr::getMessage() const { 719 return "Find bad intToptr prt: " + *BaseValue; 720 } 721 722 const DebugLoc &ReportIntToPtr::getDebugLoc() const { 723 return BaseValue->getDebugLoc(); 724 } 725 726 bool ReportIntToPtr::classof(const RejectReason *RR) { 727 return RR->getKind() == RejectReasonKind::IntToPtr; 728 } 729 730 //===----------------------------------------------------------------------===// 731 // ReportAlloca. 732 733 ReportAlloca::ReportAlloca(Instruction *Inst) 734 : ReportOther(RejectReasonKind::Alloca), Inst(Inst) {} 735 736 std::string ReportAlloca::getRemarkName() const { return "Alloca"; } 737 738 const Value *ReportAlloca::getRemarkBB() const { return Inst->getParent(); } 739 740 std::string ReportAlloca::getMessage() const { 741 return "Alloca instruction: " + *Inst; 742 } 743 744 const DebugLoc &ReportAlloca::getDebugLoc() const { 745 return Inst->getDebugLoc(); 746 } 747 748 bool ReportAlloca::classof(const RejectReason *RR) { 749 return RR->getKind() == RejectReasonKind::Alloca; 750 } 751 752 //===----------------------------------------------------------------------===// 753 // ReportUnknownInst. 754 755 ReportUnknownInst::ReportUnknownInst(Instruction *Inst) 756 : ReportOther(RejectReasonKind::UnknownInst), Inst(Inst) {} 757 758 std::string ReportUnknownInst::getRemarkName() const { return "UnknownInst"; } 759 760 const Value *ReportUnknownInst::getRemarkBB() const { 761 return Inst->getParent(); 762 } 763 764 std::string ReportUnknownInst::getMessage() const { 765 return "Unknown instruction: " + *Inst; 766 } 767 768 const DebugLoc &ReportUnknownInst::getDebugLoc() const { 769 return Inst->getDebugLoc(); 770 } 771 772 bool ReportUnknownInst::classof(const RejectReason *RR) { 773 return RR->getKind() == RejectReasonKind::UnknownInst; 774 } 775 776 //===----------------------------------------------------------------------===// 777 // ReportEntry. 778 779 ReportEntry::ReportEntry(BasicBlock *BB) 780 : ReportOther(RejectReasonKind::Entry), BB(BB) {} 781 782 std::string ReportEntry::getRemarkName() const { return "Entry"; } 783 784 const Value *ReportEntry::getRemarkBB() const { return BB; } 785 786 std::string ReportEntry::getMessage() const { 787 return "Region containing entry block of function is invalid!"; 788 } 789 790 std::string ReportEntry::getEndUserMessage() const { 791 return "Scop contains function entry (not yet supported)."; 792 } 793 794 const DebugLoc &ReportEntry::getDebugLoc() const { 795 return BB->getTerminator()->getDebugLoc(); 796 } 797 798 bool ReportEntry::classof(const RejectReason *RR) { 799 return RR->getKind() == RejectReasonKind::Entry; 800 } 801 802 //===----------------------------------------------------------------------===// 803 // ReportUnprofitable. 804 805 ReportUnprofitable::ReportUnprofitable(Region *R) 806 : ReportOther(RejectReasonKind::Unprofitable), R(R) {} 807 808 std::string ReportUnprofitable::getRemarkName() const { return "Unprofitable"; } 809 810 const Value *ReportUnprofitable::getRemarkBB() const { return R->getEntry(); } 811 812 std::string ReportUnprofitable::getMessage() const { 813 return "Region can not profitably be optimized!"; 814 } 815 816 std::string ReportUnprofitable::getEndUserMessage() const { 817 return "No profitable polyhedral optimization found"; 818 } 819 820 const DebugLoc &ReportUnprofitable::getDebugLoc() const { 821 for (const BasicBlock *BB : R->blocks()) 822 for (const Instruction &Inst : *BB) 823 if (const DebugLoc &DL = Inst.getStableDebugLoc()) 824 return DL; 825 826 return R->getEntry()->getTerminator()->getDebugLoc(); 827 } 828 829 bool ReportUnprofitable::classof(const RejectReason *RR) { 830 return RR->getKind() == RejectReasonKind::Unprofitable; 831 } 832 } // namespace polly 833