1 //===-- Thumb1InstrInfo.cpp - Thumb-1 Instruction Information -------------===// 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 // This file contains the Thumb-1 implementation of the TargetInstrInfo class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "Thumb1InstrInfo.h" 14 #include "ARMSubtarget.h" 15 #include "llvm/ADT/BitVector.h" 16 #include "llvm/CodeGen/LiveRegUnits.h" 17 #include "llvm/CodeGen/MachineFrameInfo.h" 18 #include "llvm/CodeGen/MachineInstrBuilder.h" 19 #include "llvm/CodeGen/MachineMemOperand.h" 20 #include "llvm/IR/Module.h" 21 #include "llvm/MC/MCInst.h" 22 #include "llvm/MC/MCInstBuilder.h" 23 24 using namespace llvm; 25 26 Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget &STI) 27 : ARMBaseInstrInfo(STI) {} 28 29 /// Return the noop instruction to use for a noop. 30 MCInst Thumb1InstrInfo::getNop() const { 31 return MCInstBuilder(ARM::tMOVr) 32 .addReg(ARM::R8) 33 .addReg(ARM::R8) 34 .addImm(ARMCC::AL) 35 .addReg(0); 36 } 37 38 unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc) const { 39 return 0; 40 } 41 42 void Thumb1InstrInfo::copyPhysReg(MachineBasicBlock &MBB, 43 MachineBasicBlock::iterator I, 44 const DebugLoc &DL, MCRegister DestReg, 45 MCRegister SrcReg, bool KillSrc, 46 bool RenamableDest, bool RenamableSrc) const { 47 // Need to check the arch. 48 MachineFunction &MF = *MBB.getParent(); 49 const ARMSubtarget &st = MF.getSubtarget<ARMSubtarget>(); 50 51 assert(ARM::GPRRegClass.contains(DestReg, SrcReg) && 52 "Thumb1 can only copy GPR registers"); 53 54 if (st.hasV6Ops() || ARM::hGPRRegClass.contains(SrcReg) || 55 !ARM::tGPRRegClass.contains(DestReg)) 56 BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg) 57 .addReg(SrcReg, getKillRegState(KillSrc)) 58 .add(predOps(ARMCC::AL)); 59 else { 60 const TargetRegisterInfo *RegInfo = st.getRegisterInfo(); 61 LiveRegUnits UsedRegs(*RegInfo); 62 UsedRegs.addLiveOuts(MBB); 63 64 auto InstUpToI = MBB.end(); 65 while (InstUpToI != I) 66 // The pre-decrement is on purpose here. 67 // We want to have the liveness right before I. 68 UsedRegs.stepBackward(*--InstUpToI); 69 70 if (UsedRegs.available(ARM::CPSR)) { 71 BuildMI(MBB, I, DL, get(ARM::tMOVSr), DestReg) 72 .addReg(SrcReg, getKillRegState(KillSrc)) 73 ->addRegisterDead(ARM::CPSR, RegInfo); 74 return; 75 } 76 77 // Use high register to move source to destination 78 // if movs is not an option. 79 BitVector Allocatable = RegInfo->getAllocatableSet( 80 MF, RegInfo->getRegClass(ARM::hGPRRegClassID)); 81 82 Register TmpReg = ARM::NoRegister; 83 // Prefer R12 as it is known to not be preserved anyway 84 if (UsedRegs.available(ARM::R12) && Allocatable.test(ARM::R12)) { 85 TmpReg = ARM::R12; 86 } else { 87 for (Register Reg : Allocatable.set_bits()) { 88 if (UsedRegs.available(Reg)) { 89 TmpReg = Reg; 90 break; 91 } 92 } 93 } 94 95 if (TmpReg) { 96 BuildMI(MBB, I, DL, get(ARM::tMOVr), TmpReg) 97 .addReg(SrcReg, getKillRegState(KillSrc)) 98 .add(predOps(ARMCC::AL)); 99 BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg) 100 .addReg(TmpReg, getKillRegState(true)) 101 .add(predOps(ARMCC::AL)); 102 return; 103 } 104 105 // 'MOV lo, lo' is unpredictable on < v6, so use the stack to do it 106 BuildMI(MBB, I, DL, get(ARM::tPUSH)) 107 .add(predOps(ARMCC::AL)) 108 .addReg(SrcReg, getKillRegState(KillSrc)); 109 BuildMI(MBB, I, DL, get(ARM::tPOP)) 110 .add(predOps(ARMCC::AL)) 111 .addReg(DestReg, getDefRegState(true)); 112 } 113 } 114 115 void Thumb1InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 116 MachineBasicBlock::iterator I, 117 Register SrcReg, bool isKill, int FI, 118 const TargetRegisterClass *RC, 119 const TargetRegisterInfo *TRI, 120 Register VReg, 121 MachineInstr::MIFlag Flags) const { 122 assert((RC == &ARM::tGPRRegClass || 123 (SrcReg.isPhysical() && isARMLowRegister(SrcReg))) && 124 "Unknown regclass!"); 125 126 if (RC == &ARM::tGPRRegClass || 127 (SrcReg.isPhysical() && isARMLowRegister(SrcReg))) { 128 DebugLoc DL; 129 if (I != MBB.end()) DL = I->getDebugLoc(); 130 131 MachineFunction &MF = *MBB.getParent(); 132 MachineFrameInfo &MFI = MF.getFrameInfo(); 133 MachineMemOperand *MMO = MF.getMachineMemOperand( 134 MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore, 135 MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); 136 BuildMI(MBB, I, DL, get(ARM::tSTRspi)) 137 .addReg(SrcReg, getKillRegState(isKill)) 138 .addFrameIndex(FI) 139 .addImm(0) 140 .addMemOperand(MMO) 141 .add(predOps(ARMCC::AL)); 142 } 143 } 144 145 void Thumb1InstrInfo::loadRegFromStackSlot( 146 MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register DestReg, 147 int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, 148 Register VReg, MachineInstr::MIFlag Flags) const { 149 assert((RC->hasSuperClassEq(&ARM::tGPRRegClass) || 150 (DestReg.isPhysical() && isARMLowRegister(DestReg))) && 151 "Unknown regclass!"); 152 153 if (RC->hasSuperClassEq(&ARM::tGPRRegClass) || 154 (DestReg.isPhysical() && isARMLowRegister(DestReg))) { 155 DebugLoc DL; 156 if (I != MBB.end()) DL = I->getDebugLoc(); 157 158 MachineFunction &MF = *MBB.getParent(); 159 MachineFrameInfo &MFI = MF.getFrameInfo(); 160 MachineMemOperand *MMO = MF.getMachineMemOperand( 161 MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad, 162 MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); 163 BuildMI(MBB, I, DL, get(ARM::tLDRspi), DestReg) 164 .addFrameIndex(FI) 165 .addImm(0) 166 .addMemOperand(MMO) 167 .add(predOps(ARMCC::AL)); 168 } 169 } 170 171 void Thumb1InstrInfo::expandLoadStackGuard( 172 MachineBasicBlock::iterator MI) const { 173 MachineFunction &MF = *MI->getParent()->getParent(); 174 const ARMSubtarget &ST = MF.getSubtarget<ARMSubtarget>(); 175 const auto *GV = cast<GlobalValue>((*MI->memoperands_begin())->getValue()); 176 177 assert(MF.getFunction().getParent()->getStackProtectorGuard() != "tls" && 178 "TLS stack protector not supported for Thumb1 targets"); 179 180 unsigned Instr; 181 if (!GV->isDSOLocal()) 182 Instr = ARM::tLDRLIT_ga_pcrel; 183 else if (ST.genExecuteOnly() && ST.hasV8MBaselineOps()) 184 Instr = ARM::t2MOVi32imm; 185 else if (ST.genExecuteOnly()) 186 Instr = ARM::tMOVi32imm; 187 else 188 Instr = ARM::tLDRLIT_ga_abs; 189 expandLoadStackGuardBase(MI, Instr, ARM::tLDRi); 190 } 191 192 bool Thumb1InstrInfo::canCopyGluedNodeDuringSchedule(SDNode *N) const { 193 // In Thumb1 the scheduler may need to schedule a cross-copy between GPRS and CPSR 194 // but this is not always possible there, so allow the Scheduler to clone tADCS and tSBCS 195 // even if they have glue. 196 // FIXME. Actually implement the cross-copy where it is possible (post v6) 197 // because these copies entail more spilling. 198 unsigned Opcode = N->getMachineOpcode(); 199 if (Opcode == ARM::tADCS || Opcode == ARM::tSBCS) 200 return true; 201 202 return false; 203 } 204