namespace polly { static void getDebugLocations(const Region *R, DebugLoc &Begin, DebugLoc &End) { for (const BasicBlock *BB : R->blocks()) for (const Instruction &Inst : *BB) { DebugLoc DL = Inst.getDebugLoc(); if (!DL) continue; Begin = Begin ? std::min(Begin, DL) : DL; End = End ? std::max(End, DL) : DL; } } void emitRejectionRemarks(const llvm::Function &F, const RejectLog &Log) { LLVMContext &Ctx = F.getContext(); const Region *R = Log.region(); DebugLoc Begin, End; getDebugLocations(R, Begin, End); emitOptimizationRemarkMissed( Ctx, DEBUG_TYPE, F, Begin, "The following errors keep this region from being a Scop."); for (RejectReasonPtr RR : Log) { if (const DebugLoc &Loc = RR->getDebugLoc()) emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, Loc, RR->getEndUserMessage()); } emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, End, "Invalid Scop candidate ends here."); } void emitValidRemarks(const llvm::Function &F, const Region *R) { LLVMContext &Ctx = F.getContext(); DebugLoc Begin, End; getDebugLocations(R, Begin, End); emitOptimizationRemark(Ctx, DEBUG_TYPE, F, Begin, "A valid Scop begins here."); emitOptimizationRemark(Ctx, DEBUG_TYPE, F, End, "A valid Scop ends here."); } //===----------------------------------------------------------------------===// // RejectReason. const DebugLoc RejectReason::Unknown = DebugLoc(); const llvm::DebugLoc &RejectReason::getDebugLoc() const { // Allocate an empty DebugLoc and return it a reference to it. return Unknown; } // RejectLog. void RejectLog::print(raw_ostream &OS, int level) const { int j = 0; for (auto Reason : ErrorReports) OS.indent(level) << "[" << j++ << "] " << Reason->getMessage() << "\n"; } //===----------------------------------------------------------------------===// // ReportCFG. ReportCFG::ReportCFG(const RejectReasonKind K) : RejectReason(K) { ++BadCFGForScop; } bool ReportCFG::classof(const RejectReason *RR) { return RR->getKind() >= rrkCFG && RR->getKind() <= rrkLastCFG; } //===----------------------------------------------------------------------===// // ReportInvalidTerminator. std::string ReportInvalidTerminator::getMessage() const { return ("Invalid instruction terminates BB: " + BB->getName()).str(); } const DebugLoc &ReportInvalidTerminator::getDebugLoc() const { return BB->getTerminator()->getDebugLoc(); } bool ReportInvalidTerminator::classof(const RejectReason *RR) { return RR->getKind() == rrkInvalidTerminator; } //===----------------------------------------------------------------------===// // ReportAffFunc. ReportAffFunc::ReportAffFunc(const RejectReasonKind K, const Instruction *Inst) : RejectReason(K), Inst(Inst) { ++BadAffFuncForScop; } bool ReportAffFunc::classof(const RejectReason *RR) { return RR->getKind() >= rrkAffFunc && RR->getKind() <= rrkLastAffFunc; } //===----------------------------------------------------------------------===// // ReportUndefCond. std::string ReportUndefCond::getMessage() const { return ("Condition based on 'undef' value in BB: " + BB->getName()).str(); } bool ReportUndefCond::classof(const RejectReason *RR) { return RR->getKind() == rrkUndefCond; } //===----------------------------------------------------------------------===// // ReportInvalidCond. std::string ReportInvalidCond::getMessage() const { return ("Condition in BB '" + BB->getName()).str() + "' neither constant nor an icmp instruction"; } bool ReportInvalidCond::classof(const RejectReason *RR) { return RR->getKind() == rrkInvalidCond; } //===----------------------------------------------------------------------===// // ReportUnsignedCond. std::string ReportUnsignedCond::getMessage() const { return ("Condition in BB '" + BB->getName()).str() + "' performs a comparision on (not yet supported) unsigned integers."; } std::string ReportUnsignedCond::getEndUserMessage() const { return "Unsupported comparision on unsigned integers encountered"; } bool ReportUnsignedCond::classof(const RejectReason *RR) { return RR->getKind() == rrkUnsignedCond; } //===----------------------------------------------------------------------===// // ReportUndefOperand. std::string ReportUndefOperand::getMessage() const { return ("undef operand in branch at BB: " + BB->getName()).str(); } bool ReportUndefOperand::classof(const RejectReason *RR) { return RR->getKind() == rrkUndefOperand; } //===----------------------------------------------------------------------===// // ReportNonAffBranch. std::string ReportNonAffBranch::getMessage() const { return ("Non affine branch in BB '" + BB->getName()).str() + "' with LHS: " + *LHS + " and RHS: " + *RHS; } bool ReportNonAffBranch::classof(const RejectReason *RR) { return RR->getKind() == rrkNonAffBranch; } //===----------------------------------------------------------------------===// // ReportNoBasePtr. std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; } bool ReportNoBasePtr::classof(const RejectReason *RR) { return RR->getKind() == rrkNoBasePtr; } //===----------------------------------------------------------------------===// // ReportUndefBasePtr. std::string ReportUndefBasePtr::getMessage() const { return "Undefined base pointer"; } bool ReportUndefBasePtr::classof(const RejectReason *RR) { return RR->getKind() == rrkUndefBasePtr; } //===----------------------------------------------------------------------===// // ReportVariantBasePtr. std::string ReportVariantBasePtr::getMessage() const { return "Base address not invariant in current region:" + *BaseValue; } std::string ReportVariantBasePtr::getEndUserMessage() const { return "The base address of this array is not invariant inside the loop"; } bool ReportVariantBasePtr::classof(const RejectReason *RR) { return RR->getKind() == rrkVariantBasePtr; } //===----------------------------------------------------------------------===// // ReportDifferentArrayElementSize std::string ReportDifferentArrayElementSize::getMessage() const { return "Access to one array through data types of different size"; } bool ReportDifferentArrayElementSize::classof(const RejectReason *RR) { return RR->getKind() == rrkDifferentElementSize; } std::string ReportDifferentArrayElementSize::getEndUserMessage() const { llvm::StringRef BaseName = BaseValue->getName(); std::string Name = (BaseName.size() > 0) ? BaseName : "UNKNOWN"; return "The array \"" + Name + "\" is accessed through elements that differ " "in size"; } //===----------------------------------------------------------------------===// // ReportNonAffineAccess. std::string ReportNonAffineAccess::getMessage() const { return "Non affine access function: " + *AccessFunction; } bool ReportNonAffineAccess::classof(const RejectReason *RR) { return RR->getKind() == rrkNonAffineAccess; } std::string ReportNonAffineAccess::getEndUserMessage() const { llvm::StringRef BaseName = BaseValue->getName(); std::string Name = (BaseName.size() > 0) ? BaseName : "UNKNOWN"; return "The array subscript of \"" + Name + "\" is not affine"; } //===----------------------------------------------------------------------===// // ReportLoopBound. ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount) : RejectReason(rrkLoopBound), L(L), LoopCount(LoopCount), Loc(L->getStartLoc()) { ++BadLoopBoundForScop; } std::string ReportLoopBound::getMessage() const { return "Non affine loop bound '" + *LoopCount + "' in loop: " + L->getHeader()->getName(); } const DebugLoc &ReportLoopBound::getDebugLoc() const { return Loc; } bool ReportLoopBound::classof(const RejectReason *RR) { return RR->getKind() == rrkLoopBound; } std::string ReportLoopBound::getEndUserMessage() const { return "Failed to derive an affine function from the loop bounds."; } //===----------------------------------------------------------------------===// // ReportFuncCall. ReportFuncCall::ReportFuncCall(Instruction *Inst) : RejectReason(rrkFuncCall), Inst(Inst) { ++BadFuncCallForScop; } std::string ReportFuncCall::getMessage() const { return "Call instruction: " + *Inst; } const DebugLoc &ReportFuncCall::getDebugLoc() const { return Inst->getDebugLoc(); } std::string ReportFuncCall::getEndUserMessage() const { return "This function call cannot be handled. " "Try to inline it."; } bool ReportFuncCall::classof(const RejectReason *RR) { return RR->getKind() == rrkFuncCall; } //===----------------------------------------------------------------------===// // ReportNonSimpleMemoryAccess ReportNonSimpleMemoryAccess::ReportNonSimpleMemoryAccess(Instruction *Inst) : ReportOther(rrkNonSimpleMemoryAccess), Inst(Inst) {} std::string ReportNonSimpleMemoryAccess::getMessage() const { return "Non-simple memory access: " + *Inst; } const DebugLoc &ReportNonSimpleMemoryAccess::getDebugLoc() const { return Inst->getDebugLoc(); } std::string ReportNonSimpleMemoryAccess::getEndUserMessage() const { return "Volatile memory accesses or memory accesses for atomic types " "are not supported."; } bool ReportNonSimpleMemoryAccess::classof(const RejectReason *RR) { return RR->getKind() == rrkNonSimpleMemoryAccess; } //===----------------------------------------------------------------------===// // ReportAlias. ReportAlias::ReportAlias(Instruction *Inst, AliasSet &AS) : RejectReason(rrkAlias), Inst(Inst) { for (const auto &I : AS) Pointers.push_back(I.getValue()); ++BadAliasForScop; } std::string ReportAlias::formatInvalidAlias(std::string Prefix, std::string Suffix) const { std::string Message; raw_string_ostream OS(Message); OS << Prefix; for (PointerSnapshotTy::const_iterator PI = Pointers.begin(), PE = Pointers.end(); ;) { const Value *V = *PI; assert(V && "Diagnostic info does not match found LLVM-IR anymore."); if (V->getName().size() == 0) OS << "\"" << *V << "\""; else OS << "\"" << V->getName() << "\""; ++PI; if (PI != PE) OS << ", "; else break; } OS << Suffix; return OS.str(); } std::string ReportAlias::getMessage() const { return formatInvalidAlias("Possible aliasing: "); } std::string ReportAlias::getEndUserMessage() const { return formatInvalidAlias("Accesses to the arrays ", " may access the same memory."); } const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); } bool ReportAlias::classof(const RejectReason *RR) { return RR->getKind() == rrkAlias; } //===----------------------------------------------------------------------===// // ReportSimpleLoop. ReportSimpleLoop::ReportSimpleLoop() : RejectReason(rrkSimpleLoop) { ++BadSimpleLoopForScop; } std::string ReportSimpleLoop::getMessage() const { return "Loop not in simplify form is invalid!"; } bool ReportSimpleLoop::classof(const RejectReason *RR) { return RR->getKind() == rrkSimpleLoop; } //===----------------------------------------------------------------------===// // ReportOther. std::string ReportOther::getMessage() const { return "Unknown reject reason"; } ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) { ++BadOtherForScop; } bool ReportOther::classof(const RejectReason *RR) { return RR->getKind() >= rrkOther && RR->getKind() <= rrkLastOther; } //===----------------------------------------------------------------------===// // ReportIntToPtr. ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue) : ReportOther(rrkIntToPtr), BaseValue(BaseValue) {} std::string ReportIntToPtr::getMessage() const { return "Find bad intToptr prt: " + *BaseValue; } const DebugLoc &ReportIntToPtr::getDebugLoc() const { return BaseValue->getDebugLoc(); } bool ReportIntToPtr::classof(const RejectReason *RR) { return RR->getKind() == rrkIntToPtr; } //===----------------------------------------------------------------------===// // ReportAlloca. ReportAlloca::ReportAlloca(Instruction *Inst) : ReportOther(rrkAlloca), Inst(Inst) {} std::string ReportAlloca::getMessage() const { return "Alloca instruction: " + *Inst; } const DebugLoc &ReportAlloca::getDebugLoc() const { return Inst->getDebugLoc(); } bool ReportAlloca::classof(const RejectReason *RR) { return RR->getKind() == rrkAlloca; } //===----------------------------------------------------------------------===// // ReportUnknownInst. ReportUnknownInst::ReportUnknownInst(Instruction *Inst) : ReportOther(rrkUnknownInst), Inst(Inst) {} std::string ReportUnknownInst::getMessage() const { return "Unknown instruction: " + *Inst; } const DebugLoc &ReportUnknownInst::getDebugLoc() const { return Inst->getDebugLoc(); } bool ReportUnknownInst::classof(const RejectReason *RR) { return RR->getKind() == rrkUnknownInst; } //===----------------------------------------------------------------------===// // ReportEntry. ReportEntry::ReportEntry(BasicBlock *BB) : ReportOther(rrkEntry), BB(BB) {} std::string ReportEntry::getMessage() const { return "Region containing entry block of function is invalid!"; } const DebugLoc &ReportEntry::getDebugLoc() const { return BB->getTerminator()->getDebugLoc(); } bool ReportEntry::classof(const RejectReason *RR) { return RR->getKind() == rrkEntry; } //===----------------------------------------------------------------------===// // ReportUnprofitable. ReportUnprofitable::ReportUnprofitable(Region *R) : ReportOther(rrkUnprofitable), R(R) {} std::string ReportUnprofitable::getMessage() const { return "Region can not profitably be optimized!"; } std::string ReportUnprofitable::getEndUserMessage() const { return "No profitable polyhedral optimization found"; } const DebugLoc &ReportUnprofitable::getDebugLoc() const { for (const BasicBlock *BB : R->blocks()) for (const Instruction &Inst : *BB) if (const DebugLoc &DL = Inst.getDebugLoc()) return DL; return R->getEntry()->getTerminator()->getDebugLoc(); } bool ReportUnprofitable::classof(const RejectReason *RR) { return RR->getKind() == rrkUnprofitable; } } // namespace polly
void AVRFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.begin(); CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); DebugLoc DL = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc(); const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>(); const AVRInstrInfo &TII = *STI.getInstrInfo(); bool HasFP = hasFP(MF); // Interrupt handlers re-enable interrupts in function entry. if (CallConv == CallingConv::AVR_INTR) { BuildMI(MBB, MBBI, DL, TII.get(AVR::BSETs)) .addImm(0x07) .setMIFlag(MachineInstr::FrameSetup); } // Save the frame pointer if we have one. if (HasFP) { BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr)) .addReg(AVR::R29R28, RegState::Kill) .setMIFlag(MachineInstr::FrameSetup); } // Emit special prologue code to save R1, R0 and SREG in interrupt/signal // handlers before saving any other registers. if (CallConv == CallingConv::AVR_INTR || CallConv == CallingConv::AVR_SIGNAL) { BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr)) .addReg(AVR::R1R0, RegState::Kill) .setMIFlag(MachineInstr::FrameSetup); BuildMI(MBB, MBBI, DL, TII.get(AVR::INRdA), AVR::R0) .addImm(0x3f) .setMIFlag(MachineInstr::FrameSetup); BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHRr)) .addReg(AVR::R0, RegState::Kill) .setMIFlag(MachineInstr::FrameSetup); BuildMI(MBB, MBBI, DL, TII.get(AVR::EORRdRr)) .addReg(AVR::R0, RegState::Define) .addReg(AVR::R0, RegState::Kill) .addReg(AVR::R0, RegState::Kill) .setMIFlag(MachineInstr::FrameSetup); } // Early exit if the frame pointer is not needed in this function. if (!HasFP) { return; } const MachineFrameInfo &MFI = MF.getFrameInfo(); const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>(); unsigned FrameSize = MFI.getStackSize() - AFI->getCalleeSavedFrameSize(); // Skip the callee-saved push instructions. while ( (MBBI != MBB.end()) && MBBI->getFlag(MachineInstr::FrameSetup) && (MBBI->getOpcode() == AVR::PUSHRr || MBBI->getOpcode() == AVR::PUSHWRr)) { ++MBBI; } // Update Y with the new base value. BuildMI(MBB, MBBI, DL, TII.get(AVR::SPREAD), AVR::R29R28) .addReg(AVR::SP) .setMIFlag(MachineInstr::FrameSetup); // Mark the FramePtr as live-in in every block except the entry. for (MachineFunction::iterator I = std::next(MF.begin()), E = MF.end(); I != E; ++I) { I->addLiveIn(AVR::R29R28); } if (!FrameSize) { return; } // Reserve the necessary frame memory by doing FP -= <size>. unsigned Opcode = (isUInt<6>(FrameSize)) ? AVR::SBIWRdK : AVR::SUBIWRdK; MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opcode), AVR::R29R28) .addReg(AVR::R29R28, RegState::Kill) .addImm(FrameSize) .setMIFlag(MachineInstr::FrameSetup); // The SREG implicit def is dead. MI->getOperand(3).setIsDead(); // Write back R29R28 to SP and temporarily disable interrupts. BuildMI(MBB, MBBI, DL, TII.get(AVR::SPWRITE), AVR::SP) .addReg(AVR::R29R28) .setMIFlag(MachineInstr::FrameSetup); }
void fixTerminators(MachineBasicBlock *MBB) { SmallPtrSet<MachineBasicBlock*, 2> MissedSuccs; MissedSuccs.insert(MBB->succ_begin(), MBB->succ_end()); MachineInstr *FirstTerminator = 0; for (MachineBasicBlock::iterator II = MBB->getFirstTerminator(), IE = MBB->end(); II != IE; ++II) { MachineInstr *Inst = II; if (!VInstrInfo::isBrCndLike(Inst->getOpcode())) continue; MachineBasicBlock *TargetBB = Inst->getOperand(1).getMBB(); MachineOperand Cnd = Inst->getOperand(0); //bool inserted; //jt_it at; //tie(at, inserted) = Table.insert(std::make_pair(TargetBB, Cnd)); // BranchFolding may generate code that jumping to same bb with multiple // instruction, merge the condition. //if (!inserted) { // at->second = VInstrInfo::MergePred(Cnd, at->second, *MBB, // MBB->getFirstTerminator(), &MRI, // TII, VTM::VOpOr); //} // Change the unconditional branch after conditional branch to // conditional branch. if (FirstTerminator && VInstrInfo::isUnConditionalBranch(Inst)){ MachineOperand &TrueCnd = FirstTerminator->getOperand(0); MachineOperand &FalseCnd = Inst->getOperand(0); TrueCnd.setIsKill(false); FalseCnd.setReg(TrueCnd.getReg()); FalseCnd.setTargetFlags(TrueCnd.getTargetFlags()); VInstrInfo::ReversePredicateCondition(FalseCnd); } FirstTerminator = Inst; MissedSuccs.erase(TargetBB); } // Make sure each basic block have a terminator. if (!MissedSuccs.empty()) { assert(MissedSuccs.size() == 1 && "Fall through to multiple blocks?"); ++UnconditionalBranches; MachineOperand Cnd = VInstrInfo::CreatePredicate(); if (FirstTerminator) { MachineOperand &TrueCnd = FirstTerminator->getOperand(0); assert(TrueCnd.getReg() != 0 && "Two unconditional branch?"); // We will use the register somewhere else TrueCnd.setIsKill(false); Cnd = TrueCnd; VInstrInfo::ReversePredicateCondition(Cnd); } BuildMI(MBB, DebugLoc(), VInstrInfo::getDesc(VTM::VOpToStateb)) .addOperand(Cnd).addMBB(*MissedSuccs.begin()) .addOperand(VInstrInfo::CreatePredicate()) .addOperand(VInstrInfo::CreateTrace()); } //else if (Table.size() != MBB->succ_size()) { // // Also fix the CFG. // while (!MBB->succ_empty()) // MBB->removeSuccessor(MBB->succ_end() - 1); // for (jt_it JI = Table.begin(), JE = Table.end(); JI != JE; ++JI) // MBB->addSuccessor(JI->first); // // Try to correct the CFG. // TII->RemoveBranch(*MBB); // VInstrInfo::insertJumpTable(*MBB, Table, DebugLoc()); //} //Table.clear(); if (MBB->succ_size() == 0 && MBB->getFirstTerminator() == MBB->end()) { ++Unreachables; BuildMI(MBB, DebugLoc(), VInstrInfo::getDesc(VTM::VOpUnreachable)) .addOperand(VInstrInfo::CreatePredicate()) .addOperand(VInstrInfo::CreateTrace()); } }