void MSP430InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIdx, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const { DebugLoc DL; if (MI != MBB.end()) DL = MI->getDebugLoc(); MachineFunction &MF = *MBB.getParent(); MachineFrameInfo &MFI = *MF.getFrameInfo(); MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIdx), MachineMemOperand::MOStore, MFI.getObjectSize(FrameIdx), MFI.getObjectAlignment(FrameIdx)); errs()<<"storeRegToStackSlot\n"; if (RC == &MSP430::GR16RegClass) { BuildMI(MBB, MI, DL, get(MSP430::MOV16mr)) .addFrameIndex(FrameIdx).addImm(0) .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); outs()<<"Offset: " << MMO->getOffset() << "\n"; } else if (RC == &MSP430::GR8RegClass) BuildMI(MBB, MI, DL, get(MSP430::MOV8mr)) .addFrameIndex(FrameIdx).addImm(0) .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); else llvm_unreachable("Cannot store this register to stack slot!"); }
/// getHazardType - We return hazard for any non-branch instruction that would /// terminate the dispatch group. We turn NoopHazard for any /// instructions that wouldn't terminate the dispatch group that would cause a /// pipeline flush. ScheduleHazardRecognizer::HazardType PPCHazardRecognizer970:: getHazardType(SUnit *SU, int Stalls) { assert(Stalls == 0 && "PPC hazards don't support scoreboard lookahead"); MachineInstr *MI = SU->getInstr(); if (MI->isDebugValue()) return NoHazard; unsigned Opcode = MI->getOpcode(); bool isFirst, isSingle, isCracked, isLoad, isStore; PPCII::PPC970_Unit InstrType = GetInstrType(Opcode, isFirst, isSingle, isCracked, isLoad, isStore); if (InstrType == PPCII::PPC970_Pseudo) return NoHazard; // We can only issue a PPC970_First/PPC970_Single instruction (such as // crand/mtspr/etc) if this is the first cycle of the dispatch group. if (NumIssued != 0 && (isFirst || isSingle)) return Hazard; // If this instruction is cracked into two ops by the decoder, we know that // it is not a branch and that it cannot issue if 3 other instructions are // already in the dispatch group. if (isCracked && NumIssued > 2) return Hazard; switch (InstrType) { default: llvm_unreachable("Unknown instruction type!"); case PPCII::PPC970_FXU: case PPCII::PPC970_LSU: case PPCII::PPC970_FPU: case PPCII::PPC970_VALU: case PPCII::PPC970_VPERM: // We can only issue a branch as the last instruction in a group. if (NumIssued == 4) return Hazard; break; case PPCII::PPC970_CRU: // We can only issue a CR instruction in the first two slots. if (NumIssued >= 2) return Hazard; break; case PPCII::PPC970_BRU: break; } // Do not allow MTCTR and BCTRL to be in the same dispatch group. if (HasCTRSet && Opcode == PPC::BCTRL) return NoopHazard; // If this is a load following a store, make sure it's not to the same or // overlapping address. if (isLoad && NumStores && !MI->memoperands_empty()) { MachineMemOperand *MO = *MI->memoperands_begin(); if (isLoadOfStoredAddress(MO->getSize(), MO->getOffset(), MO->getValue())) return NoopHazard; } return NoHazard; }
bool AMDGPUDAGToDAGISel::isCPLoad(const LoadSDNode *N) const { MachineMemOperand *MMO = N->getMemOperand(); if (checkType(N->getSrcValue(), AMDGPUAS::PRIVATE_ADDRESS)) { if (MMO) { const Value *V = MMO->getValue(); const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V); if (PSV && PSV == PseudoSourceValue::getConstantPool()) { return true; } } } return false; }
/// isLoadFromConstantMemory - Return true if the given instruction is a /// load from constant memory. Machine LICM will hoist these even if they are /// not re-materializable. bool MachineLICM::isLoadFromConstantMemory(MachineInstr *MI) { if (!MI->getDesc().mayLoad()) return false; if (!MI->hasOneMemOperand()) return false; MachineMemOperand *MMO = *MI->memoperands_begin(); if (MMO->isVolatile()) return false; if (!MMO->getValue()) return false; const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(MMO->getValue()); if (PSV) { MachineFunction &MF = *MI->getParent()->getParent(); return PSV->isConstant(MF.getFrameInfo()); } else { return AA->pointsToConstantMemory(MMO->getValue()); } }
bool AMDGPUDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int cbID) { if (checkType(N->getSrcValue(), AMDGPUAS::CONSTANT_ADDRESS)) { return true; } MachineMemOperand *MMO = N->getMemOperand(); const Value *V = MMO->getValue(); const Value *BV = getBasePointerValue(V); if (MMO && MMO->getValue() && ((V && dyn_cast<GlobalValue>(V)) || (BV && dyn_cast<GlobalValue>( getBasePointerValue(MMO->getValue()))))) { return checkType(N->getSrcValue(), AMDGPUAS::PRIVATE_ADDRESS); } else { return false; } }
// Check if the machine memory operand MMO is aliased with any of the // stores in the store group Stores. bool HexagonStoreWidening::instrAliased(InstrGroup &Stores, const MachineMemOperand &MMO) { if (!MMO.getValue()) return true; MemoryLocation L(MMO.getValue(), MMO.getSize(), MMO.getAAInfo()); for (auto SI : Stores) { const MachineMemOperand &SMO = getStoreTarget(SI); if (!SMO.getValue()) return true; MemoryLocation SL(SMO.getValue(), SMO.getSize(), SMO.getAAInfo()); if (AA->alias(L, SL)) return true; } return false; }
/// ScanForSpillSlotRefs - Scan all the machine instructions for spill slot /// references and update spill slot weights. void StackSlotColoring::ScanForSpillSlotRefs(MachineFunction &MF) { SSRefs.resize(MFI->getObjectIndexEnd()); // FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands. for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); MBBI != E; ++MBBI) { MachineBasicBlock *MBB = &*MBBI; for (MachineBasicBlock::iterator MII = MBB->begin(), EE = MBB->end(); MII != EE; ++MII) { MachineInstr &MI = *MII; for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { MachineOperand &MO = MI.getOperand(i); if (!MO.isFI()) continue; int FI = MO.getIndex(); if (FI < 0) continue; if (!LS->hasInterval(FI)) continue; LiveInterval &li = LS->getInterval(FI); if (!MI.isDebugValue()) li.weight += LiveIntervals::getSpillWeight(false, true, MBFI, MI); } for (MachineInstr::mmo_iterator MMOI = MI.memoperands_begin(), EE = MI.memoperands_end(); MMOI != EE; ++MMOI) { MachineMemOperand *MMO = *MMOI; if (const FixedStackPseudoSourceValue *FSV = dyn_cast_or_null<FixedStackPseudoSourceValue>( MMO->getPseudoValue())) { int FI = FSV->getFrameIndex(); if (FI >= 0) SSRefs[FI].push_back(MMO); } } } } }
void PPCHazardRecognizer970::EmitInstruction(SUnit *SU) { MachineInstr *MI = SU->getInstr(); if (MI->isDebugValue()) return; unsigned Opcode = MI->getOpcode(); bool isFirst, isSingle, isCracked, isLoad, isStore; PPCII::PPC970_Unit InstrType = GetInstrType(Opcode, isFirst, isSingle, isCracked, isLoad, isStore); if (InstrType == PPCII::PPC970_Pseudo) return; // Update structural hazard information. if (Opcode == PPC::MTCTR || Opcode == PPC::MTCTR8) HasCTRSet = true; // Track the address stored to. if (isStore && NumStores < 4 && !MI->memoperands_empty()) { MachineMemOperand *MO = *MI->memoperands_begin(); StoreSize[NumStores] = MO->getSize(); StoreOffset[NumStores] = MO->getOffset(); StoreValue[NumStores] = MO->getValue(); ++NumStores; } if (InstrType == PPCII::PPC970_BRU || isSingle) NumIssued = 4; // Terminate a d-group. ++NumIssued; // If this instruction is cracked into two ops by the decoder, remember that // we issued two pieces. if (isCracked) ++NumIssued; if (NumIssued == 5) EndDispatchGroup(); }
void StackColoring::remapInstructions(DenseMap<int, int> &SlotRemap) { unsigned FixedInstr = 0; unsigned FixedMemOp = 0; unsigned FixedDbg = 0; MachineModuleInfo *MMI = &MF->getMMI(); // Remap debug information that refers to stack slots. MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), VE = VMap.end(); VI != VE; ++VI) { const MDNode *Var = VI->first; if (!Var) continue; std::pair<unsigned, DebugLoc> &VP = VI->second; if (SlotRemap.count(VP.first)) { DEBUG(dbgs()<<"Remapping debug info for ["<<Var->getName()<<"].\n"); VP.first = SlotRemap[VP.first]; FixedDbg++; } } // Keep a list of *allocas* which need to be remapped. DenseMap<const AllocaInst*, const AllocaInst*> Allocas; for (DenseMap<int, int>::const_iterator it = SlotRemap.begin(), e = SlotRemap.end(); it != e; ++it) { const AllocaInst *From = MFI->getObjectAllocation(it->first); const AllocaInst *To = MFI->getObjectAllocation(it->second); assert(To && From && "Invalid allocation object"); Allocas[From] = To; } // Remap all instructions to the new stack slots. MachineFunction::iterator BB, BBE; MachineBasicBlock::iterator I, IE; for (BB = MF->begin(), BBE = MF->end(); BB != BBE; ++BB) for (I = BB->begin(), IE = BB->end(); I != IE; ++I) { // Skip lifetime markers. We'll remove them soon. if (I->getOpcode() == TargetOpcode::LIFETIME_START || I->getOpcode() == TargetOpcode::LIFETIME_END) continue; // Update the MachineMemOperand to use the new alloca. for (MachineInstr::mmo_iterator MM = I->memoperands_begin(), E = I->memoperands_end(); MM != E; ++MM) { MachineMemOperand *MMO = *MM; const Value *V = MMO->getValue(); if (!V) continue; const PseudoSourceValue *PSV = dyn_cast<const PseudoSourceValue>(V); if (PSV && PSV->isConstant(MFI)) continue; // Climb up and find the original alloca. V = GetUnderlyingObject(V); // If we did not find one, or if the one that we found is not in our // map, then move on. if (!V || !isa<AllocaInst>(V)) { // Clear mem operand since we don't know for sure that it doesn't // alias a merged alloca. MMO->setValue(0); continue; } const AllocaInst *AI= cast<AllocaInst>(V); if (!Allocas.count(AI)) continue; MMO->setValue(Allocas[AI]); FixedMemOp++; } // Update all of the machine instruction operands. for (unsigned i = 0 ; i < I->getNumOperands(); ++i) { MachineOperand &MO = I->getOperand(i); if (!MO.isFI()) continue; int FromSlot = MO.getIndex(); // Don't touch arguments. if (FromSlot<0) continue; // Only look at mapped slots. if (!SlotRemap.count(FromSlot)) continue; // In a debug build, check that the instruction that we are modifying is // inside the expected live range. If the instruction is not inside // the calculated range then it means that the alloca usage moved // outside of the lifetime markers, or that the user has a bug. // NOTE: Alloca address calculations which happen outside the lifetime // zone are are okay, despite the fact that we don't have a good way // for validating all of the usages of the calculation. #ifndef NDEBUG bool TouchesMemory = I->mayLoad() || I->mayStore(); // If we *don't* protect the user from escaped allocas, don't bother // validating the instructions. if (!I->isDebugValue() && TouchesMemory && ProtectFromEscapedAllocas) { SlotIndex Index = Indexes->getInstructionIndex(I); LiveInterval *Interval = Intervals[FromSlot]; assert(Interval->find(Index) != Interval->end() && "Found instruction usage outside of live range."); } #endif // Fix the machine instructions. int ToSlot = SlotRemap[FromSlot]; MO.setIndex(ToSlot); FixedInstr++; } } DEBUG(dbgs()<<"Fixed "<<FixedMemOp<<" machine memory operands.\n"); DEBUG(dbgs()<<"Fixed "<<FixedDbg<<" debug locations.\n"); DEBUG(dbgs()<<"Fixed "<<FixedInstr<<" machine instructions.\n"); }
void MIPrinter::print(const MachineMemOperand &Op) { OS << '('; // TODO: Print operand's target specific flags. if (Op.isVolatile()) OS << "volatile "; if (Op.isNonTemporal()) OS << "non-temporal "; if (Op.isInvariant()) OS << "invariant "; if (Op.isLoad()) OS << "load "; else { assert(Op.isStore() && "Non load machine operand must be a store"); OS << "store "; } OS << Op.getSize() << (Op.isLoad() ? " from " : " into "); if (const Value *Val = Op.getValue()) { printIRValueReference(*Val); } else { const PseudoSourceValue *PVal = Op.getPseudoValue(); assert(PVal && "Expected a pseudo source value"); switch (PVal->kind()) { case PseudoSourceValue::Stack: OS << "stack"; break; case PseudoSourceValue::GOT: OS << "got"; break; case PseudoSourceValue::JumpTable: OS << "jump-table"; break; case PseudoSourceValue::ConstantPool: OS << "constant-pool"; break; case PseudoSourceValue::FixedStack: printStackObjectReference( cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex()); break; case PseudoSourceValue::GlobalValueCallEntry: OS << "call-entry "; cast<GlobalValuePseudoSourceValue>(PVal)->getValue()->printAsOperand( OS, /*PrintType=*/false, MST); break; case PseudoSourceValue::ExternalSymbolCallEntry: OS << "call-entry $"; printLLVMNameWithoutPrefix( OS, cast<ExternalSymbolPseudoSourceValue>(PVal)->getSymbol()); break; } } printOffset(Op.getOffset()); if (Op.getBaseAlignment() != Op.getSize()) OS << ", align " << Op.getBaseAlignment(); auto AAInfo = Op.getAAInfo(); if (AAInfo.TBAA) { OS << ", !tbaa "; AAInfo.TBAA->printAsOperand(OS, MST); } if (AAInfo.Scope) { OS << ", !alias.scope "; AAInfo.Scope->printAsOperand(OS, MST); } if (AAInfo.NoAlias) { OS << ", !noalias "; AAInfo.NoAlias->printAsOperand(OS, MST); } if (Op.getRanges()) { OS << ", !range "; Op.getRanges()->printAsOperand(OS, MST); } OS << ')'; }
DeadMemOpElimination::instr_iterator DeadMemOpElimination::handleMemOp(instr_iterator I, DefMapTy &Defs, AliasSetTracker &AST) { MachineInstr *MI = I; MachineMemOperand *MO = *MI->memoperands_begin(); // AliasAnalysis cannot handle offset right now, so we pretend to write a // a big enough size to the location pointed by the base pointer. uint64_t Size = MO->getSize() + MO->getOffset(); AliasSet *ASet = &AST.getAliasSetForPointer(const_cast<Value*>(MO->getValue()), Size, 0); MachineInstr *&LastMI = Defs[ASet]; bool canHandleLastStore = LastMI && ASet->isMustAlias() && LastMI->getOpcode() != VTM::VOpInternalCall // FIXME: We may need to remember the last // definition for all predicates. && isPredIdentical(LastMI, MI); if (canHandleLastStore) { MachineMemOperand *LastMO = *LastMI->memoperands_begin(); // We can only handle last store if and only if their memory operand have // the must-alias address and the same size. canHandleLastStore = LastMO->getSize() == MO->getSize() && !LastMO->isVolatile() && MachineMemOperandAlias(MO, LastMO, AA, SE) == AliasAnalysis::MustAlias; } // FIXME: These elimination is only valid if we are in single-thread mode! if (VInstrInfo::mayStore(MI)) { if (canHandleLastStore) { // Dead store find, remove it. LastMI->eraseFromParent(); ++DeadStoreEliminated; } // Update the definition. LastMI = MI; return I; } // Now MI is a load. if (!canHandleLastStore) return I; // Loading the value that just be stored, the load is not necessary. MachineOperand LoadedMO = MI->getOperand(0); MachineOperand StoredMO = LastMI->getOperand(2); // Simply replace the load by a copy. DebugLoc dl = MI->getDebugLoc(); I = *BuildMI(*MI->getParent(), I, dl, VInstrInfo::getDesc(VTM::VOpMove)) .addOperand(LoadedMO).addOperand(StoredMO). addOperand(*VInstrInfo::getPredOperand(MI)). addOperand(*VInstrInfo::getTraceOperand(MI)); MI->eraseFromParent(); ++DeadLoadEliminated; return I; }
void VDAGToDAGISel::LowerMemAccessISel(SDNode *N, SelectionDAG &DAG, bool isStore) { LSBaseSDNode *LSNode = cast<LSBaseSDNode>(N); // FIXME: Handle the index. assert(LSNode->isUnindexed() && "Indexed load/store is not supported!"); EVT VT = LSNode->getMemoryVT(); unsigned VTSize = VT.getSizeInBits(); SDValue StoreVal = isStore ? cast<StoreSDNode>(LSNode)->getValue() : DAG.getUNDEF(VT); LLVMContext *Cntx = DAG.getContext(); EVT CmdVT = EVT::getIntegerVT(*Cntx, VFUMemBus::CMDWidth); SDValue SDOps[] = {// The chain. LSNode->getChain(), // The Value to store (if any), and the address. LSNode->getBasePtr(), StoreVal, // Is load? DAG.getTargetConstant(isStore, CmdVT), // Byte enable. DAG.getTargetConstant(getByteEnable(VT.getStoreSize()), MVT::i8) }; unsigned DataBusWidth = getFUDesc<VFUMemBus>()->getDataWidth(); MachineMemOperand *MemOp = LSNode->getMemOperand(); if (unsigned AS = MemOp->getPointerInfo().getAddrSpace()) { VFInfo *VFI = DAG.getMachineFunction().getInfo<VFInfo>(); DataBusWidth = VFI->getBRamInfo(AS).ElemSizeInBytes * 8; } assert(DataBusWidth >= VTSize && "Unexpected large data!"); MVT DataBusVT = EVT::getIntegerVT(*DAG.getContext(), DataBusWidth).getSimpleVT(); DebugLoc dl = N->getDebugLoc(); SDValue Result = DAG.getMemIntrinsicNode(VTMISD::MemAccess, dl, // Result and the chain. DAG.getVTList(DataBusVT, MVT::Other), // SDValue operands SDOps, array_lengthof(SDOps), // Memory operands. LSNode->getMemoryVT(), MemOp); if (isStore) { DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result.getValue(1)); return; } SDValue Val = Result; // Truncate the data bus, the system bus should place the valid data start // from LSM. if (DataBusWidth > VTSize) Val = VTargetLowering::getTruncate(DAG, dl, Result, VTSize); // Check if this an extend load. LoadSDNode *LD = cast<LoadSDNode>(LSNode); ISD::LoadExtType ExtType = LD->getExtensionType(); if (ExtType != ISD::NON_EXTLOAD) { unsigned DstSize = LD->getValueSizeInBits(0); Val = VTargetLowering::getExtend(DAG, dl, Val, DstSize, ExtType == ISD::SEXTLOAD); } // Do we need to replace the result of the load operation? SDValue NewValues[] = { Val, Result.getValue(1) }; DAG.ReplaceAllUsesWith(N, NewValues); }
void VPreRegAllocSched::buildMemDepEdges(VSchedGraph &G, ArrayRef<VSUnit*> SUs){ // The schedule unit and the corresponding memory operand. typedef std::vector<std::pair<MachineMemOperand*, VSUnit*> > MemOpMapTy; MemOpMapTy VisitedOps; Loop *IRL = LI->getLoopFor(G.getEntryBB()->getBasicBlock()); typedef ArrayRef<VSUnit*>::iterator it; for (it I = SUs.begin(), E = SUs.end(); I != E; ++I) { VSUnit *DstU = *I; MachineInstr *DstMI = DstU->getRepresentativePtr(); // Skip the non-memory operation and non-call operation. if (!mayAccessMemory(DstMI->getDesc())) continue; bool isDstWrite = VInstrInfo::mayStore(DstMI); // Dirty Hack: Is the const_cast safe? MachineMemOperand *DstMO = 0; // TODO: Also try to get the address information for call instruction. if (!DstMI->memoperands_empty() && !DstMI->hasVolatileMemoryRef()) { assert(DstMI->hasOneMemOperand() && "Can not handle multiple mem ops!"); assert(!DstMI->hasVolatileMemoryRef() && "Can not handle volatile op!"); // FIXME: DstMO maybe null in a VOpCmdSeq if ((DstMO = /*ASSIGNMENT*/ *DstMI->memoperands_begin())){ assert(!isa<PseudoSourceValue>(DstMO->getValue()) && "Unexpected frame stuffs!"); } } typedef MemOpMapTy::iterator visited_it; for (visited_it I = VisitedOps.begin(), E = VisitedOps.end(); I != E; ++I) { MachineMemOperand *SrcMO = I->first; VSUnit *SrcU = I->second; MachineInstr *SrcMI = SrcU->getRepresentativePtr(); bool MayBothActive = !VInstrInfo::isPredicateMutex(SrcMI, DstMI); if (!MayBothActive) ++MutexPredNoAlias; // Handle unanalyzable memory access. if (DstMO == 0 || SrcMO == 0) { // Build the Src -> Dst dependence. unsigned Latency = G.getStepsToFinish(SrcMI); //if (MayBothActive || SrcMO != DstMO) DstU->addDep<true>(SrcU, VDEdge::CreateMemDep(Latency, 0)); // Build the Dst -> Src (in next iteration) dependence, the dependence // occur even if SrcMI and DstMI are mutual exclusive. if (G.enablePipeLine()) { Latency = G.getStepsToFinish(SrcMI); SrcU->addDep<true>(DstU, VDEdge::CreateMemDep(Latency, 1)); } // Go on handle next visited SUnit. continue; } bool isSrcWrite = VInstrInfo::mayStore(SrcMI); // Ignore RAR dependence. if (!isDstWrite && !isSrcWrite) continue; if (!isMachineMemOperandAlias(SrcMO, DstMO, AA, SE)) continue; if (G.enablePipeLine()) { assert(IRL && "Can not handle machine loop without IR loop!"); DEBUG(SrcMI->dump(); dbgs() << "vs\n"; DstMI->dump(); dbgs() << '\n'); // Dst not depend on Src if they are mutual exclusive. if (MayBothActive) { // Compute the iterate distance. int DepDst = analyzeLoopDep(SrcMO, DstMO, *IRL, true); if (DepDst >= 0) { unsigned Latency = G.getStepsToFinish(SrcMI); DstU->addDep<true>(SrcU, VDEdge::CreateMemDep(Latency, DepDst)); } } // We need to compute if Src depend on Dst even if Dst not depend on Src. // Because dependence depends on execute order, if SrcMI and DstMI are // mutual exclusive. int DepDst = analyzeLoopDep(DstMO, SrcMO, *IRL, false); if (DepDst >=0 ) { unsigned Latency = G.getStepsToFinish(SrcMI); SrcU->addDep<true>(DstU, VDEdge::CreateMemDep(Latency, DepDst)); } } else if (MayBothActive) { unsigned Latency = G.getStepsToFinish(SrcMI); DstU->addDep<true>(SrcU, VDEdge::CreateMemDep(Latency, 0)); } }
/// This returns true if the two MIs need a chain edge betwee them. /// If these are not even memory operations, we still may need /// chain deps between them. The question really is - could /// these two MIs be reordered during scheduling from memory dependency /// point of view. static bool MIsNeedChainEdge(AliasAnalysis *AA, const MachineFrameInfo *MFI, MachineInstr *MIa, MachineInstr *MIb) { // Cover a trivial case - no edge is need to itself. if (MIa == MIb) return false; if (isUnsafeMemoryObject(MIa, MFI) || isUnsafeMemoryObject(MIb, MFI)) return true; // If we are dealing with two "normal" loads, we do not need an edge // between them - they could be reordered. if (!MIa->mayStore() && !MIb->mayStore()) return false; // To this point analysis is generic. From here on we do need AA. if (!AA) return true; MachineMemOperand *MMOa = *MIa->memoperands_begin(); MachineMemOperand *MMOb = *MIb->memoperands_begin(); // FIXME: Need to handle multiple memory operands to support all targets. if (!MIa->hasOneMemOperand() || !MIb->hasOneMemOperand()) llvm_unreachable("Multiple memory operands."); // The following interface to AA is fashioned after DAGCombiner::isAlias // and operates with MachineMemOperand offset with some important // assumptions: // - LLVM fundamentally assumes flat address spaces. // - MachineOperand offset can *only* result from legalization and // cannot affect queries other than the trivial case of overlap // checking. // - These offsets never wrap and never step outside // of allocated objects. // - There should never be any negative offsets here. // // FIXME: Modify API to hide this math from "user" // FIXME: Even before we go to AA we can reason locally about some // memory objects. It can save compile time, and possibly catch some // corner cases not currently covered. assert ((MMOa->getOffset() >= 0) && "Negative MachineMemOperand offset"); assert ((MMOb->getOffset() >= 0) && "Negative MachineMemOperand offset"); int64_t MinOffset = std::min(MMOa->getOffset(), MMOb->getOffset()); int64_t Overlapa = MMOa->getSize() + MMOa->getOffset() - MinOffset; int64_t Overlapb = MMOb->getSize() + MMOb->getOffset() - MinOffset; AliasAnalysis::AliasResult AAResult = AA->alias( AliasAnalysis::Location(MMOa->getValue(), Overlapa, MMOa->getTBAAInfo()), AliasAnalysis::Location(MMOb->getValue(), Overlapb, MMOb->getTBAAInfo())); return (AAResult != AliasAnalysis::NoAlias); }
void MIPrinter::print(const LLVMContext &Context, const TargetInstrInfo &TII, const MachineMemOperand &Op) { OS << '('; if (Op.isVolatile()) OS << "volatile "; if (Op.isNonTemporal()) OS << "non-temporal "; if (Op.isDereferenceable()) OS << "dereferenceable "; if (Op.isInvariant()) OS << "invariant "; if (Op.getFlags() & MachineMemOperand::MOTargetFlag1) OS << '"' << getTargetMMOFlagName(TII, MachineMemOperand::MOTargetFlag1) << "\" "; if (Op.getFlags() & MachineMemOperand::MOTargetFlag2) OS << '"' << getTargetMMOFlagName(TII, MachineMemOperand::MOTargetFlag2) << "\" "; if (Op.getFlags() & MachineMemOperand::MOTargetFlag3) OS << '"' << getTargetMMOFlagName(TII, MachineMemOperand::MOTargetFlag3) << "\" "; assert((Op.isLoad() || Op.isStore()) && "machine memory operand must be a load or store (or both)"); if (Op.isLoad()) OS << "load "; if (Op.isStore()) OS << "store "; printSyncScope(Context, Op.getSyncScopeID()); if (Op.getOrdering() != AtomicOrdering::NotAtomic) OS << toIRString(Op.getOrdering()) << ' '; if (Op.getFailureOrdering() != AtomicOrdering::NotAtomic) OS << toIRString(Op.getFailureOrdering()) << ' '; OS << Op.getSize(); if (const Value *Val = Op.getValue()) { OS << ((Op.isLoad() && Op.isStore()) ? " on " : Op.isLoad() ? " from " : " into "); printIRValueReference(*Val); } else if (const PseudoSourceValue *PVal = Op.getPseudoValue()) { OS << ((Op.isLoad() && Op.isStore()) ? " on " : Op.isLoad() ? " from " : " into "); assert(PVal && "Expected a pseudo source value"); switch (PVal->kind()) { case PseudoSourceValue::Stack: OS << "stack"; break; case PseudoSourceValue::GOT: OS << "got"; break; case PseudoSourceValue::JumpTable: OS << "jump-table"; break; case PseudoSourceValue::ConstantPool: OS << "constant-pool"; break; case PseudoSourceValue::FixedStack: printStackObjectReference( cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex()); break; case PseudoSourceValue::GlobalValueCallEntry: OS << "call-entry "; cast<GlobalValuePseudoSourceValue>(PVal)->getValue()->printAsOperand( OS, /*PrintType=*/false, MST); break; case PseudoSourceValue::ExternalSymbolCallEntry: OS << "call-entry $"; printLLVMNameWithoutPrefix( OS, cast<ExternalSymbolPseudoSourceValue>(PVal)->getSymbol()); break; case PseudoSourceValue::TargetCustom: llvm_unreachable("TargetCustom pseudo source values are not supported"); break; } } MachineOperand::printOperandOffset(OS, Op.getOffset()); if (Op.getBaseAlignment() != Op.getSize()) OS << ", align " << Op.getBaseAlignment(); auto AAInfo = Op.getAAInfo(); if (AAInfo.TBAA) { OS << ", !tbaa "; AAInfo.TBAA->printAsOperand(OS, MST); } if (AAInfo.Scope) { OS << ", !alias.scope "; AAInfo.Scope->printAsOperand(OS, MST); } if (AAInfo.NoAlias) { OS << ", !noalias "; AAInfo.NoAlias->printAsOperand(OS, MST); } if (Op.getRanges()) { OS << ", !range "; Op.getRanges()->printAsOperand(OS, MST); } OS << ')'; }
void MIPrinter::print(const MachineMemOperand &Op) { OS << '('; // TODO: Print operand's target specific flags. if (Op.isVolatile()) OS << "volatile "; if (Op.isNonTemporal()) OS << "non-temporal "; if (Op.isInvariant()) OS << "invariant "; if (Op.isLoad()) OS << "load "; else { assert(Op.isStore() && "Non load machine operand must be a store"); OS << "store "; } OS << Op.getSize() << (Op.isLoad() ? " from " : " into "); if (const Value *Val = Op.getValue()) printIRValueReference(*Val); // TODO: Print PseudoSourceValue. printOffset(Op.getOffset()); if (Op.getBaseAlignment() != Op.getSize()) OS << ", align " << Op.getBaseAlignment(); // TODO: Print the metadata attributes. OS << ')'; }
void StackColoring::remapInstructions(DenseMap<int, int> &SlotRemap) { unsigned FixedInstr = 0; unsigned FixedMemOp = 0; unsigned FixedDbg = 0; MachineModuleInfo *MMI = &MF->getMMI(); // Remap debug information that refers to stack slots. MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), VE = VMap.end(); VI != VE; ++VI) { const MDNode *Var = VI->first; if (!Var) continue; std::pair<unsigned, DebugLoc> &VP = VI->second; if (SlotRemap.count(VP.first)) { DEBUG(dbgs()<<"Remapping debug info for ["<<Var->getName()<<"].\n"); VP.first = SlotRemap[VP.first]; FixedDbg++; } } // Keep a list of *allocas* which need to be remapped. DenseMap<const Value*, const Value*> Allocas; for (DenseMap<int, int>::iterator it = SlotRemap.begin(), e = SlotRemap.end(); it != e; ++it) { const Value *From = MFI->getObjectAllocation(it->first); const Value *To = MFI->getObjectAllocation(it->second); assert(To && From && "Invalid allocation object"); Allocas[From] = To; } // Remap all instructions to the new stack slots. MachineFunction::iterator BB, BBE; MachineBasicBlock::iterator I, IE; for (BB = MF->begin(), BBE = MF->end(); BB != BBE; ++BB) for (I = BB->begin(), IE = BB->end(); I != IE; ++I) { // Skip lifetime markers. We'll remove them soon. if (I->getOpcode() == TargetOpcode::LIFETIME_START || I->getOpcode() == TargetOpcode::LIFETIME_END) continue; // Update the MachineMemOperand to use the new alloca. for (MachineInstr::mmo_iterator MM = I->memoperands_begin(), E = I->memoperands_end(); MM != E; ++MM) { MachineMemOperand *MMO = *MM; const Value *V = MMO->getValue(); if (!V) continue; // Climb up and find the original alloca. V = GetUnderlyingObject(V); // If we did not find one, or if the one that we found is not in our // map, then move on. if (!V || !Allocas.count(V)) continue; MMO->setValue(Allocas[V]); FixedMemOp++; } // Update all of the machine instruction operands. for (unsigned i = 0 ; i < I->getNumOperands(); ++i) { MachineOperand &MO = I->getOperand(i); if (!MO.isFI()) continue; int FromSlot = MO.getIndex(); // Don't touch arguments. if (FromSlot<0) continue; // Only look at mapped slots. if (!SlotRemap.count(FromSlot)) continue; // In a debug build, check that the instruction that we are modifying is // inside the expected live range. If the instruction is not inside // the calculated range then it means that the alloca usage moved // outside of the lifetime markers. #ifndef NDEBUG SlotIndex Index = Indexes->getInstructionIndex(I); LiveInterval* Interval = Intervals[FromSlot]; assert(Interval->find(Index) != Interval->end() && "Found instruction usage outside of live range."); #endif // Fix the machine instructions. int ToSlot = SlotRemap[FromSlot]; MO.setIndex(ToSlot); FixedInstr++; } } DEBUG(dbgs()<<"Fixed "<<FixedMemOp<<" machine memory operands.\n"); DEBUG(dbgs()<<"Fixed "<<FixedDbg<<" debug locations.\n"); DEBUG(dbgs()<<"Fixed "<<FixedInstr<<" machine instructions.\n"); }