ARMInstrInfo.cpp revision 360784
1//===-- ARMInstrInfo.cpp - ARM 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 ARM implementation of the TargetInstrInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "ARMInstrInfo.h"
14#include "ARM.h"
15#include "ARMConstantPoolValue.h"
16#include "ARMMachineFunctionInfo.h"
17#include "ARMTargetMachine.h"
18#include "MCTargetDesc/ARMAddressingModes.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/CodeGen/LiveVariables.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineJumpTableInfo.h"
24#include "llvm/CodeGen/MachineRegisterInfo.h"
25#include "llvm/IR/Function.h"
26#include "llvm/IR/GlobalVariable.h"
27#include "llvm/MC/MCAsmInfo.h"
28#include "llvm/MC/MCInst.h"
29using namespace llvm;
30
31ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI)
32    : ARMBaseInstrInfo(STI), RI() {}
33
34/// Return the noop instruction to use for a noop.
35void ARMInstrInfo::getNoop(MCInst &NopInst) const {
36  if (hasNOP()) {
37    NopInst.setOpcode(ARM::HINT);
38    NopInst.addOperand(MCOperand::createImm(0));
39    NopInst.addOperand(MCOperand::createImm(ARMCC::AL));
40    NopInst.addOperand(MCOperand::createReg(0));
41  } else {
42    NopInst.setOpcode(ARM::MOVr);
43    NopInst.addOperand(MCOperand::createReg(ARM::R0));
44    NopInst.addOperand(MCOperand::createReg(ARM::R0));
45    NopInst.addOperand(MCOperand::createImm(ARMCC::AL));
46    NopInst.addOperand(MCOperand::createReg(0));
47    NopInst.addOperand(MCOperand::createReg(0));
48  }
49}
50
51unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const {
52  switch (Opc) {
53  default:
54    break;
55  case ARM::LDR_PRE_IMM:
56  case ARM::LDR_PRE_REG:
57  case ARM::LDR_POST_IMM:
58  case ARM::LDR_POST_REG:
59    return ARM::LDRi12;
60  case ARM::LDRH_PRE:
61  case ARM::LDRH_POST:
62    return ARM::LDRH;
63  case ARM::LDRB_PRE_IMM:
64  case ARM::LDRB_PRE_REG:
65  case ARM::LDRB_POST_IMM:
66  case ARM::LDRB_POST_REG:
67    return ARM::LDRBi12;
68  case ARM::LDRSH_PRE:
69  case ARM::LDRSH_POST:
70    return ARM::LDRSH;
71  case ARM::LDRSB_PRE:
72  case ARM::LDRSB_POST:
73    return ARM::LDRSB;
74  case ARM::STR_PRE_IMM:
75  case ARM::STR_PRE_REG:
76  case ARM::STR_POST_IMM:
77  case ARM::STR_POST_REG:
78    return ARM::STRi12;
79  case ARM::STRH_PRE:
80  case ARM::STRH_POST:
81    return ARM::STRH;
82  case ARM::STRB_PRE_IMM:
83  case ARM::STRB_PRE_REG:
84  case ARM::STRB_POST_IMM:
85  case ARM::STRB_POST_REG:
86    return ARM::STRBi12;
87  }
88
89  return 0;
90}
91
92void ARMInstrInfo::expandLoadStackGuard(MachineBasicBlock::iterator MI) const {
93  MachineFunction &MF = *MI->getParent()->getParent();
94  const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>();
95  const TargetMachine &TM = MF.getTarget();
96
97  if (!Subtarget.useMovt()) {
98    if (TM.isPositionIndependent())
99      expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_pcrel, ARM::LDRi12);
100    else
101      expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_abs, ARM::LDRi12);
102    return;
103  }
104
105  if (!TM.isPositionIndependent()) {
106    expandLoadStackGuardBase(MI, ARM::MOVi32imm, ARM::LDRi12);
107    return;
108  }
109
110  const GlobalValue *GV =
111      cast<GlobalValue>((*MI->memoperands_begin())->getValue());
112
113  if (!Subtarget.isGVIndirectSymbol(GV)) {
114    expandLoadStackGuardBase(MI, ARM::MOV_ga_pcrel, ARM::LDRi12);
115    return;
116  }
117
118  MachineBasicBlock &MBB = *MI->getParent();
119  DebugLoc DL = MI->getDebugLoc();
120  Register Reg = MI->getOperand(0).getReg();
121  MachineInstrBuilder MIB;
122
123  MIB = BuildMI(MBB, MI, DL, get(ARM::MOV_ga_pcrel_ldr), Reg)
124            .addGlobalAddress(GV, 0, ARMII::MO_NONLAZY);
125  auto Flags = MachineMemOperand::MOLoad |
126               MachineMemOperand::MODereferenceable |
127               MachineMemOperand::MOInvariant;
128  MachineMemOperand *MMO = MBB.getParent()->getMachineMemOperand(
129      MachinePointerInfo::getGOT(*MBB.getParent()), Flags, 4, 4);
130  MIB.addMemOperand(MMO);
131  BuildMI(MBB, MI, DL, get(ARM::LDRi12), Reg)
132      .addReg(Reg, RegState::Kill)
133      .addImm(0)
134      .cloneMemRefs(*MI)
135      .add(predOps(ARMCC::AL));
136}
137