blob: edd5ccfd9cd478c8e1f15fafaf9329525383bbdf [file] [log] [blame]
Tim Northover75ad0772016-07-20 21:13:29 +00001//===---- lib/CodeGen/GlobalISel/MachineLegalizer.cpp - IRTranslator -------==//
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//
10// Implement an interface to specify and query how an illegal operation on a
11// given type should be expanded.
12//
13// Issues to be resolved:
14// + Make it fast.
15// + Support weird types like i3, <7 x i3>, ...
16// + Operations with more than one type (ICMP, CMPXCHG, intrinsics, ...)
17//
18//===----------------------------------------------------------------------===//
19
20#include "llvm/CodeGen/MachineInstr.h"
21#include "llvm/CodeGen/ValueTypes.h"
22#include "llvm/CodeGen/GlobalISel/MachineLegalizer.h"
23#include "llvm/IR/Type.h"
24#include "llvm/Target/TargetOpcodes.h"
25using namespace llvm;
26
27MachineLegalizer::MachineLegalizer() : TablesInitialized(false) {
28 DefaultActions[TargetOpcode::G_ADD] = NarrowScalar;
29}
30
31bool MachineLegalizer::legalizeInstr(MachineInstr &MI) const {
32 llvm_unreachable("Unimplemented functionality");
33}
34
35void MachineLegalizer::computeTables() {
36 for (auto &Op : Actions) {
37 LLT Ty = Op.first.second;
38 if (!Ty.isVector())
39 continue;
40
41 auto &Entry =
42 MaxLegalVectorElts[std::make_pair(Op.first.first, Ty.getElementType())];
43 Entry = std::max(Entry, Ty.getNumElements());
44 }
45
46 TablesInitialized = true;
47}
48
49// FIXME: inefficient implementation for now. Without ComputeValueVTs we're
50// probably going to need specialized lookup structures for various types before
51// we have any hope of doing well with something like <13 x i3>. Even the common
52// cases should do better than what we have now.
53std::pair<MachineLegalizer::LegalizeAction, LLT>
54MachineLegalizer::getAction(unsigned Opcode, LLT Ty) const {
55 assert(TablesInitialized && "backend forgot to call computeTables");
56 // These *have* to be implemented for now, they're the fundamental basis of
57 // how everything else is transformed.
58
59 auto ActionIt = Actions.find(std::make_pair(Opcode, Ty));
60 if (ActionIt != Actions.end())
61 return findLegalAction(Opcode, Ty, ActionIt->second);
62
63 if (!Ty.isVector()) {
64 auto DefaultAction = DefaultActions.find(Opcode);
65 if (DefaultAction != DefaultActions.end() && DefaultAction->second == Legal)
66 return std::make_pair(Legal, Ty);
67
68 assert(DefaultAction->second == NarrowScalar && "unexpected default");
69 return findLegalAction(Opcode, Ty, NarrowScalar);
70 }
71
72 LLT EltTy = Ty.getElementType();
73 int NumElts = Ty.getNumElements();
74
75 auto ScalarAction = ScalarInVectorActions.find(std::make_pair(Opcode, EltTy));
76 if (ScalarAction != ScalarInVectorActions.end() &&
77 ScalarAction->second != Legal)
78 return findLegalAction(Opcode, EltTy, ScalarAction->second);
79
80 // The element type is legal in principle, but the number of elements is
81 // wrong.
82 auto MaxLegalElts = MaxLegalVectorElts.lookup(std::make_pair(Opcode, EltTy));
83 if (MaxLegalElts > NumElts)
84 return findLegalAction(Opcode, Ty, MoreElements);
85
86 if (MaxLegalElts == 0) {
87 // Scalarize if there's no legal vector type, which is just a special case
88 // of FewerElements.
89 return std::make_pair(FewerElements, EltTy);
90 }
91
92 return findLegalAction(Opcode, Ty, FewerElements);
93}
94
95std::pair<MachineLegalizer::LegalizeAction, LLT>
96MachineLegalizer::getAction(MachineInstr &MI) const {
97 return getAction(MI.getOpcode(), MI.getType());
98}
99
100bool MachineLegalizer::isLegal(MachineInstr &MI) const {
101 return getAction(MI).first == Legal;
102}
103
104LLT MachineLegalizer::findLegalType(unsigned Opcode, LLT Ty,
105 LegalizeAction Action) const {
106 switch(Action) {
107 default:
108 llvm_unreachable("Cannot find legal type");
109 case Legal:
110 return Ty;
111 case NarrowScalar: {
112 return findLegalType(Opcode, Ty,
113 [&](LLT Ty) -> LLT { return Ty.halfScalarSize(); });
114 }
115 case WidenScalar: {
116 return findLegalType(Opcode, Ty,
117 [&](LLT Ty) -> LLT { return Ty.doubleScalarSize(); });
118 }
119 case FewerElements: {
120 return findLegalType(Opcode, Ty,
121 [&](LLT Ty) -> LLT { return Ty.halfElements(); });
122 }
123 case MoreElements: {
124 return findLegalType(
125 Opcode, Ty, [&](LLT Ty) -> LLT { return Ty.doubleElements(); });
126 }
127 }
128}