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