LLVM 19.0.0git
ARMInstrInfo.cpp
Go to the documentation of this file.
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"
17#include "ARMTargetMachine.h"
19#include "llvm/ADT/STLExtras.h"
25#include "llvm/IR/Function.h"
27#include "llvm/MC/MCAsmInfo.h"
28#include "llvm/MC/MCInst.h"
29using namespace llvm;
30
32
33/// Return the noop instruction to use for a noop.
35 MCInst NopInst;
36 if (hasNOP()) {
37 NopInst.setOpcode(ARM::HINT);
41 } else {
42 NopInst.setOpcode(ARM::MOVr);
43 NopInst.addOperand(MCOperand::createReg(ARM::R0));
44 NopInst.addOperand(MCOperand::createReg(ARM::R0));
48 }
49 return NopInst;
50}
51
52unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const {
53 switch (Opc) {
54 default:
55 break;
56 case ARM::LDR_PRE_IMM:
57 case ARM::LDR_PRE_REG:
58 case ARM::LDR_POST_IMM:
59 case ARM::LDR_POST_REG:
60 return ARM::LDRi12;
61 case ARM::LDRH_PRE:
62 case ARM::LDRH_POST:
63 return ARM::LDRH;
64 case ARM::LDRB_PRE_IMM:
65 case ARM::LDRB_PRE_REG:
66 case ARM::LDRB_POST_IMM:
67 case ARM::LDRB_POST_REG:
68 return ARM::LDRBi12;
69 case ARM::LDRSH_PRE:
70 case ARM::LDRSH_POST:
71 return ARM::LDRSH;
72 case ARM::LDRSB_PRE:
73 case ARM::LDRSB_POST:
74 return ARM::LDRSB;
75 case ARM::STR_PRE_IMM:
76 case ARM::STR_PRE_REG:
77 case ARM::STR_POST_IMM:
78 case ARM::STR_POST_REG:
79 return ARM::STRi12;
80 case ARM::STRH_PRE:
81 case ARM::STRH_POST:
82 return ARM::STRH;
83 case ARM::STRB_PRE_IMM:
84 case ARM::STRB_PRE_REG:
85 case ARM::STRB_POST_IMM:
86 case ARM::STRB_POST_REG:
87 return ARM::STRBi12;
88 }
89
90 return 0;
91}
92
93void ARMInstrInfo::expandLoadStackGuard(MachineBasicBlock::iterator MI) const {
94 MachineFunction &MF = *MI->getParent()->getParent();
95 const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>();
96 const TargetMachine &TM = MF.getTarget();
97 Module &M = *MF.getFunction().getParent();
98
99 if (M.getStackProtectorGuard() == "tls") {
100 expandLoadStackGuardBase(MI, ARM::MRC, ARM::LDRi12);
101 return;
102 }
103
104 const GlobalValue *GV =
105 cast<GlobalValue>((*MI->memoperands_begin())->getValue());
106
107 bool ForceELFGOTPIC = Subtarget.isTargetELF() && !GV->isDSOLocal();
108 if (!Subtarget.useMovt() || ForceELFGOTPIC) {
109 // For ELF non-PIC, use GOT PIC code sequence as well because R_ARM_GOT_ABS
110 // does not have assembler support.
111 if (TM.isPositionIndependent() || ForceELFGOTPIC)
112 expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_pcrel, ARM::LDRi12);
113 else
114 expandLoadStackGuardBase(MI, ARM::LDRLIT_ga_abs, ARM::LDRi12);
115 return;
116 }
117
118 if (!TM.isPositionIndependent()) {
119 expandLoadStackGuardBase(MI, ARM::MOVi32imm, ARM::LDRi12);
120 return;
121 }
122
123 if (!Subtarget.isGVIndirectSymbol(GV)) {
124 expandLoadStackGuardBase(MI, ARM::MOV_ga_pcrel, ARM::LDRi12);
125 return;
126 }
127
128 MachineBasicBlock &MBB = *MI->getParent();
129 DebugLoc DL = MI->getDebugLoc();
130 Register Reg = MI->getOperand(0).getReg();
132
133 MIB = BuildMI(MBB, MI, DL, get(ARM::MOV_ga_pcrel_ldr), Reg)
140 MIB.addMemOperand(MMO);
141 BuildMI(MBB, MI, DL, get(ARM::LDRi12), Reg)
143 .addImm(0)
146}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
IRTranslator LLVM IR MI
const char LLVMTargetMachineRef TM
This file contains some templates that are useful if you are working with the STL at all.
void expandLoadStackGuardBase(MachineBasicBlock::iterator MI, unsigned LoadImmOpc, unsigned LoadOpc) const
unsigned getUnindexedOpcode(unsigned Opc) const override
ARMInstrInfo(const ARMSubtarget &STI)
MCInst getNop() const override
Return the noop instruction to use for a noop.
bool useMovt() const
bool isGVIndirectSymbol(const GlobalValue *GV) const
True if the GV will be accessed via an indirect symbol.
bool isTargetELF() const
Definition: ARMSubtarget.h:380
A debug info location.
Definition: DebugLoc.h:33
bool isDSOLocal() const
Definition: GlobalValue.h:305
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:655
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
void setOpcode(unsigned Op)
Definition: MCInst.h:197
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
A description of a memory reference used in the backend.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:76
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
Definition: ARMBaseInfo.h:288
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
static MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.