blob: db8bfc9aac923e0acbe36a849e7ba325f78b874d [file] [log] [blame]
Ahmed Bougacha6756a2c2016-07-27 14:31:55 +00001//===- AArch64InstructionSelector.cpp ----------------------------*- C++ -*-==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10/// This file implements the targeting of the InstructionSelector class for
11/// AArch64.
12/// \todo This should be generated by TableGen.
13//===----------------------------------------------------------------------===//
14
15#include "AArch64InstructionSelector.h"
16#include "AArch64InstrInfo.h"
17#include "AArch64RegisterBankInfo.h"
18#include "AArch64RegisterInfo.h"
19#include "AArch64Subtarget.h"
20#include "llvm/CodeGen/MachineBasicBlock.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstr.h"
23#include "llvm/CodeGen/MachineInstrBuilder.h"
24#include "llvm/CodeGen/MachineRegisterInfo.h"
25#include "llvm/IR/Type.h"
26#include "llvm/Support/Debug.h"
27#include "llvm/Support/raw_ostream.h"
28
29#define DEBUG_TYPE "aarch64-isel"
30
31using namespace llvm;
32
33#ifndef LLVM_BUILD_GLOBAL_ISEL
34#error "You shouldn't build this"
35#endif
36
37AArch64InstructionSelector::AArch64InstructionSelector(
38 const AArch64Subtarget &STI, const AArch64RegisterBankInfo &RBI)
39 : InstructionSelector(), TII(*STI.getInstrInfo()),
40 TRI(*STI.getRegisterInfo()), RBI(RBI) {}
41
42/// Select the AArch64 opcode for the basic binary operation \p GenericOpc
43/// (such as G_OR or G_ADD), appropriate for the register bank \p RegBankID
44/// and of size \p OpSize.
45/// \returns \p GenericOpc if the combination is unsupported.
46static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID,
47 unsigned OpSize) {
48 switch (RegBankID) {
49 case AArch64::GPRRegBankID:
50 switch (OpSize) {
51 case 32:
52 switch (GenericOpc) {
53 case TargetOpcode::G_OR:
54 return AArch64::ORRWrr;
Ahmed Bougacha61a79282016-07-28 16:58:31 +000055 case TargetOpcode::G_AND:
56 return AArch64::ANDWrr;
Ahmed Bougacha6756a2c2016-07-27 14:31:55 +000057 case TargetOpcode::G_ADD:
58 return AArch64::ADDWrr;
59 default:
60 return GenericOpc;
61 }
62 case 64:
63 switch (GenericOpc) {
64 case TargetOpcode::G_OR:
65 return AArch64::ORRXrr;
Ahmed Bougacha61a79282016-07-28 16:58:31 +000066 case TargetOpcode::G_AND:
67 return AArch64::ANDXrr;
Ahmed Bougacha6756a2c2016-07-27 14:31:55 +000068 case TargetOpcode::G_ADD:
69 return AArch64::ADDXrr;
70 default:
71 return GenericOpc;
72 }
73 }
74 };
75 return GenericOpc;
76}
77
78bool AArch64InstructionSelector::select(MachineInstr &I) const {
79 assert(I.getParent() && "Instruction should be in a basic block!");
80 assert(I.getParent()->getParent() && "Instruction should be in a function!");
81
82 MachineBasicBlock &MBB = *I.getParent();
83 MachineFunction &MF = *MBB.getParent();
84 MachineRegisterInfo &MRI = MF.getRegInfo();
85
86 // FIXME: Is there *really* nothing to be done here? This assumes that
87 // no upstream pass introduces things like generic vreg on copies or
88 // target-specific instructions.
89 // We should document (and verify) that assumption.
90 if (!isPreISelGenericOpcode(I.getOpcode()))
91 return true;
92
93 if (I.getNumOperands() != I.getNumExplicitOperands()) {
94 DEBUG(dbgs() << "Generic instruction has unexpected implicit operands\n");
95 return false;
96 }
97
98 LLT Ty = I.getType();
99 assert(Ty.isValid() && "Generic instruction doesn't have a type");
100
101 // FIXME: Support unsized instructions (e.g., G_BR).
102 if (!Ty.isSized()) {
103 DEBUG(dbgs() << "Unsized generic instructions are unsupported\n");
104 return false;
105 }
106
107 // The size (in bits) of the operation, or 0 for the label type.
108 const unsigned OpSize = Ty.getSizeInBits();
109
110 switch (I.getOpcode()) {
111 case TargetOpcode::G_OR:
Ahmed Bougacha61a79282016-07-28 16:58:31 +0000112 case TargetOpcode::G_AND:
Ahmed Bougacha6756a2c2016-07-27 14:31:55 +0000113 case TargetOpcode::G_ADD: {
114 DEBUG(dbgs() << "AArch64: Selecting: binop\n");
115
116 // Reject the various things we don't support yet.
117 {
118 const RegisterBank *PrevOpBank = nullptr;
119 for (auto &MO : I.operands()) {
120 // FIXME: Support non-register operands.
121 if (!MO.isReg()) {
122 DEBUG(dbgs() << "Generic inst non-reg operands are unsupported\n");
123 return false;
124 }
125
126 // FIXME: Can generic operations have physical registers operands? If
127 // so, this will need to be taught about that, and we'll need to get the
128 // bank out of the minimal class for the register.
129 // Either way, this needs to be documented (and possibly verified).
130 if (!TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
131 DEBUG(dbgs() << "Generic inst has physical register operand\n");
132 return false;
133 }
134
135 const RegisterBank *OpBank = RBI.getRegBank(MO.getReg(), MRI, TRI);
136 if (!OpBank) {
137 DEBUG(dbgs() << "Generic register has no bank or class\n");
138 return false;
139 }
140
141 if (PrevOpBank && OpBank != PrevOpBank) {
142 DEBUG(dbgs() << "Generic inst operands have different banks\n");
143 return false;
144 }
145 PrevOpBank = OpBank;
146 }
147 }
148
149 const unsigned DefReg = I.getOperand(0).getReg();
150 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
151
152 const unsigned NewOpc = selectBinaryOp(I.getOpcode(), RB.getID(), OpSize);
153 if (NewOpc == I.getOpcode())
154 return false;
155
156 I.setDesc(TII.get(NewOpc));
157 // FIXME: Should the type be always reset in setDesc?
Ahmed Bougacha46c05fc2016-07-28 16:58:27 +0000158 I.removeTypes();
Ahmed Bougacha6756a2c2016-07-27 14:31:55 +0000159
160 // Now that we selected an opcode, we need to constrain the register
161 // operands to use appropriate classes.
162 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
163 }
164 }
165
166 return false;
167}