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 << ')'; }
/// 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()); } }
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 << ')'; }
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 << ')'; }
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; }