// FIXME: Does this need to check IEEE bit on function? bool SIFoldOperands::tryFoldOMod(MachineInstr &MI) { const MachineOperand *RegOp; int OMod; std::tie(RegOp, OMod) = isOMod(MI); if (OMod == SIOutMods::NONE || !RegOp->isReg() || RegOp->getSubReg() != AMDGPU::NoSubRegister || !hasOneNonDBGUseInst(*MRI, RegOp->getReg())) return false; MachineInstr *Def = MRI->getVRegDef(RegOp->getReg()); MachineOperand *DefOMod = TII->getNamedOperand(*Def, AMDGPU::OpName::omod); if (!DefOMod || DefOMod->getImm() != SIOutMods::NONE) return false; // Clamp is applied after omod. If the source already has clamp set, don't // fold it. if (TII->hasModifiersSet(*Def, AMDGPU::OpName::clamp)) return false; DEBUG(dbgs() << "Folding omod " << MI << " into " << *Def << '\n'); DefOMod->setImm(OMod); MRI->replaceRegWith(MI.getOperand(0).getReg(), Def->getOperand(0).getReg()); MI.eraseFromParent(); return true; }
void SIRegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg, int64_t Offset) const { MachineBasicBlock *MBB = MI.getParent(); MachineFunction *MF = MBB->getParent(); const SISubtarget &Subtarget = MF->getSubtarget<SISubtarget>(); const SIInstrInfo *TII = Subtarget.getInstrInfo(); #ifndef NDEBUG // FIXME: Is it possible to be storing a frame index to itself? bool SeenFI = false; for (const MachineOperand &MO: MI.operands()) { if (MO.isFI()) { if (SeenFI) llvm_unreachable("should not see multiple frame indices"); SeenFI = true; } } #endif MachineOperand *FIOp = TII->getNamedOperand(MI, AMDGPU::OpName::vaddr); assert(FIOp && FIOp->isFI() && "frame index must be address operand"); assert(TII->isMUBUF(MI)); MachineOperand *OffsetOp = TII->getNamedOperand(MI, AMDGPU::OpName::offset); int64_t NewOffset = OffsetOp->getImm() + Offset; assert(isUInt<12>(NewOffset) && "offset should be legal"); FIOp->ChangeToRegister(BaseReg, false); OffsetOp->setImm(NewOffset); }
void HexagonPeephole::ChangeOpInto(MachineOperand &Dst, MachineOperand &Src) { assert (&Dst != &Src && "Cannot duplicate into itself"); switch (Dst.getType()) { case MachineOperand::MO_Register: if (Src.isReg()) { Dst.setReg(Src.getReg()); } else if (Src.isImm()) { Dst.ChangeToImmediate(Src.getImm()); } else { llvm_unreachable("Unexpected src operand type"); } break; case MachineOperand::MO_Immediate: if (Src.isImm()) { Dst.setImm(Src.getImm()); } else if (Src.isReg()) { Dst.ChangeToRegister(Src.getReg(), Src.isDef(), Src.isImplicit(), Src.isKill(), Src.isDead(), Src.isUndef(), Src.isDebug()); } else { llvm_unreachable("Unexpected src operand type"); } break; default: llvm_unreachable("Unexpected dst operand type"); break; } }
void SIRegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg, int64_t Offset) const { MachineBasicBlock *MBB = MI.getParent(); MachineFunction *MF = MBB->getParent(); const SISubtarget &Subtarget = MF->getSubtarget<SISubtarget>(); const SIInstrInfo *TII = Subtarget.getInstrInfo(); #ifndef NDEBUG // FIXME: Is it possible to be storing a frame index to itself? bool SeenFI = false; for (const MachineOperand &MO: MI.operands()) { if (MO.isFI()) { if (SeenFI) llvm_unreachable("should not see multiple frame indices"); SeenFI = true; } } #endif MachineOperand *FIOp = TII->getNamedOperand(MI, AMDGPU::OpName::vaddr); assert(FIOp && FIOp->isFI() && "frame index must be address operand"); assert(TII->isMUBUF(MI)); MachineOperand *OffsetOp = TII->getNamedOperand(MI, AMDGPU::OpName::offset); int64_t NewOffset = OffsetOp->getImm() + Offset; if (isUInt<12>(NewOffset)) { // If we have a legal offset, fold it directly into the instruction. FIOp->ChangeToRegister(BaseReg, false); OffsetOp->setImm(NewOffset); return; } // The offset is not legal, so we must insert an add of the offset. MachineRegisterInfo &MRI = MF->getRegInfo(); unsigned NewReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); DebugLoc DL = MI.getDebugLoc(); assert(Offset != 0 && "Non-zero offset expected"); unsigned UnusedCarry = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass); unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass); // In the case the instruction already had an immediate offset, here only // the requested new offset is added because we are leaving the original // immediate in place. BuildMI(*MBB, MI, DL, TII->get(AMDGPU::S_MOV_B32), OffsetReg) .addImm(Offset); BuildMI(*MBB, MI, DL, TII->get(AMDGPU::V_ADD_I32_e64), NewReg) .addReg(UnusedCarry, RegState::Define | RegState::Dead) .addReg(OffsetReg, RegState::Kill) .addReg(BaseReg); FIOp->ChangeToRegister(NewReg, false); }
/// Add 4 to the displacement of operand MO. static void fixDisp(MachineOperand &MO) { switch (MO.getType()) { default: llvm_unreachable("Unhandled operand type."); case MachineOperand::MO_Immediate: MO.setImm(MO.getImm() + 4); break; case MachineOperand::MO_GlobalAddress: case MachineOperand::MO_ConstantPoolIndex: case MachineOperand::MO_BlockAddress: case MachineOperand::MO_TargetIndex: case MachineOperand::MO_ExternalSymbol: MO.setOffset(MO.getOffset() + 4); break; } }
bool SIFoldOperands::tryFoldClamp(MachineInstr &MI) { const MachineOperand *ClampSrc = isClamp(MI); if (!ClampSrc || !hasOneNonDBGUseInst(*MRI, ClampSrc->getReg())) return false; MachineInstr *Def = MRI->getVRegDef(ClampSrc->getReg()); if (!TII->hasFPClamp(*Def)) return false; MachineOperand *DefClamp = TII->getNamedOperand(*Def, AMDGPU::OpName::clamp); if (!DefClamp) return false; DEBUG(dbgs() << "Folding clamp " << *DefClamp << " into " << *Def << '\n'); // Clamp is applied after omod, so it is OK if omod is set. DefClamp->setImm(1); MRI->replaceRegWith(MI.getOperand(0).getReg(), Def->getOperand(0).getReg()); MI.eraseFromParent(); return true; }