LLVM: lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

21#include

22

23using namespace llvm;

25

26#define DEBUG_TYPE "legalizer-info"

27

29 switch (Action) {

31 OS << "Legal";

32 break;

34 OS << "NarrowScalar";

35 break;

37 OS << "WidenScalar";

38 break;

40 OS << "FewerElements";

41 break;

43 OS << "MoreElements";

44 break;

46 OS << "Bitcast";

47 break;

49 OS << "Lower";

50 break;

52 OS << "Libcall";

53 break;

55 OS << "Custom";

56 break;

58 OS << "Unsupported";

59 break;

61 OS << "NotFound";

62 break;

63 }

64 return OS;

65}

66

68

69

70

71 setScalarAction(TargetOpcode::G_ANYEXT, 1, {{1, Legal}});

72 setScalarAction(TargetOpcode::G_ZEXT, 1, {{1, Legal}});

73 setScalarAction(TargetOpcode::G_SEXT, 1, {{1, Legal}});

74 setScalarAction(TargetOpcode::G_TRUNC, 0, {{1, Legal}});

75 setScalarAction(TargetOpcode::G_TRUNC, 1, {{1, Legal}});

76

77 setScalarAction(TargetOpcode::G_INTRINSIC, 0, {{1, Legal}});

78 setScalarAction(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS, 0, {{1, Legal}});

79 setScalarAction(TargetOpcode::G_INTRINSIC_CONVERGENT, 0, {{1, Legal}});

80 setScalarAction(TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS, 0,

82

93

102 setScalarAction(TargetOpcode::G_FNEG, 0, {{1, Lower}});

103}

104

106 assert(TablesInitialized == false);

107

108 for (unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) {

109 const unsigned Opcode = FirstOp + OpcodeIdx;

110 for (unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].size();

111 ++TypeIdx) {

112

113

114

116

117 std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions;

118

119 std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;

120 for (auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) {

121 const LLT Type = LLT2Action.first;

123

124 auto SizeAction = std::make_pair(Type.getSizeInBits(), Action);

125 if (Type.isPointer())

126 AddressSpace2SpecifiedActions[Type.getAddressSpace()].push_back(

127 SizeAction);

128 else if (Type.isVector())

129 ElemSize2SpecifiedActions[Type.getElementType().getSizeInBits()]

130 .push_back(SizeAction);

131 else

132 ScalarSpecifiedActions.push_back(SizeAction);

133 }

134

135

136 {

137

138

140 if (TypeIdx < ScalarSizeChangeStrategies[OpcodeIdx].size() &&

141 ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)

142 S = ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx];

144 checkPartialSizeAndActionsVector(ScalarSpecifiedActions);

145 setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions));

146 }

147

148

149 for (auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) {

150 llvm::sort(PointerSpecifiedActions.second);

151 checkPartialSizeAndActionsVector(PointerSpecifiedActions.second);

152

153

154 setPointerAction(

155 Opcode, TypeIdx, PointerSpecifiedActions.first,

157 }

158

159

161 for (auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {

162 llvm::sort(VectorSpecifiedActions.second);

163 const uint16_t ElementSize = VectorSpecifiedActions.first;

164 ElementSizesSeen.push_back({ElementSize, Legal});

165 checkPartialSizeAndActionsVector(VectorSpecifiedActions.second);

166

167

168

169

171 for (SizeAndAction BitsizeAndAction : VectorSpecifiedActions.second) {

172 assert(BitsizeAndAction.first % ElementSize == 0);

173 const uint16_t NumElements = BitsizeAndAction.first / ElementSize;

174 NumElementsActions.push_back({NumElements, BitsizeAndAction.second});

175 }

176 setVectorNumElementAction(

177 Opcode, TypeIdx, ElementSize,

179 }

183 if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].size() &&

184 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)

185 VectorElementSizeChangeStrategy =

186 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx];

187 setScalarInVectorAction(

188 Opcode, TypeIdx, VectorElementSizeChangeStrategy(ElementSizesSeen));

189 }

190 }

191

192 TablesInitialized = true;

193}

194

195

196

197

198

199std::pair<LegacyLegalizeAction, LLT>

200LegacyLegalizerInfo::getAspectAction(const InstrAspect &Aspect) const {

201 assert(TablesInitialized && "backend forgot to call computeTables");

202

203

205 return findScalarLegalAction(Aspect);

207 return findVectorLegalAction(Aspect);

208}

209

215 unsigned LargestSizeSoFar = 0;

216 if (v.size() >= 1 && v[0].first != 1)

217 result.push_back({1, IncreaseAction});

218 for (size_t i = 0; i < v.size(); ++i) {

219 result.push_back(v[i]);

220 LargestSizeSoFar = v[i].first;

221 if (i + 1 < v.size() && v[i + 1].first != v[i].first + 1) {

222 result.push_back({LargestSizeSoFar + 1, IncreaseAction});

223 LargestSizeSoFar = v[i].first + 1;

224 }

225 }

226 result.push_back({LargestSizeSoFar + 1, DecreaseAction});

227 return result;

228}

229

235 if (v.size() == 0 || v[0].first != 1)

236 result.push_back({1, IncreaseAction});

237 for (size_t i = 0; i < v.size(); ++i) {

238 result.push_back(v[i]);

239 if (i + 1 == v.size() || v[i + 1].first != v[i].first + 1) {

240 result.push_back({v[i].first + 1, DecreaseAction});

241 }

242 }

243 return result;

244}

245

247LegacyLegalizerInfo::findAction(const SizeAndActionsVec &Vec, const uint32_t Size) {

249

250

251

254 assert(It != Vec.begin() && "Does Vec not start with size 1?");

255 int VecIdx = It - Vec.begin() - 1;

256

258 switch (Action) {

264 return {Size, Action};

266

267

270 [[fallthrough]];

272

273

274

275

276

277

278

279 for (int i = VecIdx - 1; i >= 0; --i)

282 return {Vec[i].first, Action};

284 }

287

288 for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)

291 return {Vec[i].first, Action};

293 }

298 }

300}

301

302std::pair<LegacyLegalizeAction, LLT>

303LegacyLegalizerInfo::findScalarLegalAction(const InstrAspect &Aspect) const {

305 if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)

310 auto &PA = AddrSpace2PointerActions[OpcodeIdx];

312 if (It == PA.end())

314 Actions = It->second;

315 } else {

316 Actions = ScalarActions[OpcodeIdx];

317 }

318 if (Aspect.Idx >= Actions.size())

321

322

328}

329

330std::pair<LegacyLegalizeAction, LLT>

331LegacyLegalizerInfo::findVectorLegalAction(const InstrAspect &Aspect) const {

333

334

335 if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)

338 const unsigned TypeIdx = Aspect.Idx;

339 if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].size())

342 ScalarInVectorActions[OpcodeIdx][TypeIdx];

343

344 LLT IntermediateType;

345 auto ElementSizeAndAction =

348 ElementSizeAndAction.first);

349 if (ElementSizeAndAction.second != Legal)

350 return {ElementSizeAndAction.second, IntermediateType};

351

352 auto i = NumElements2Actions[OpcodeIdx].find(

354 if (i == NumElements2Actions[OpcodeIdx].end()) {

355 return {NotFound, IntermediateType};

356 }

358 auto NumElementsAndAction =

359 findAction(NumElementsVec, IntermediateType.getNumElements());

360 return {NumElementsAndAction.second,

363}

364

366 assert(Opcode >= FirstOp && Opcode <= LastOp && "Unsupported opcode");

367 return Opcode - FirstOp;

368}

369

370

373 for (unsigned i = 0; i < Query.Types.size(); ++i) {

374 auto Action = getAspectAction({Query.Opcode, i, Query.Types[i]});

375 if (Action.first != Legal) {

376 LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i << " Action="

377 << Action.first << ", " << Action.second << "\n");

378 return {Action.first, i, Action.second};

379 } else

380 LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i << " Legal\n");

381 }

384}

385

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

Interface for Targets to specify which operations they can successfully select and how the others sho...

Interface for Targets to specify which operations they can successfully select and how the others sho...

static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)

size_t size() const

size - Get the array size.

constexpr unsigned getScalarSizeInBits() const

constexpr bool isScalar() const

static constexpr LLT scalar(unsigned SizeInBits)

Get a low-level scalar or aggregate "bag of bits".

constexpr uint16_t getNumElements() const

Returns the number of elements in a vector LLT.

constexpr bool isVector() const

constexpr TypeSize getSizeInBits() const

Returns the total size of the type. Must only be called on sized types.

constexpr bool isPointer() const

constexpr unsigned getAddressSpace() const

static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)

Get a low-level fixed-width vector of some number of elements and element width.

std::function< SizeAndActionsVec(const SizeAndActionsVec &v)> SizeChangeStrategy

static LLVM_ABI SizeAndActionsVec decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec &v, LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction, LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction)

Helper function to implement many typical SizeChangeStrategy functions.

Definition LegacyLegalizerInfo.cpp:231

static SizeAndActionsVec widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v)

static SizeAndActionsVec moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v)

A SizeChangeStrategy for the common case where legalization for a particular vector operation consist...

LLVM_ABI void computeTables()

Compute any ancillary tables needed to quickly decide how an operation should be handled.

Definition LegacyLegalizerInfo.cpp:105

std::vector< SizeAndAction > SizeAndActionsVec

static bool needsLegalizingToDifferentSize(const LegacyLegalizeActions::LegacyLegalizeAction Action)

LLVM_ABI unsigned getOpcodeIdxForOpcode(unsigned Opcode) const

Definition LegacyLegalizerInfo.cpp:365

static SizeAndActionsVec widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v)

A SizeChangeStrategy for the common case where legalization for a particular operation consists of wi...

LLVM_ABI LegacyLegalizeActionStep getAction(const LegalityQuery &Query) const

Definition LegacyLegalizerInfo.cpp:372

void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode, const unsigned TypeIdx, SizeChangeStrategy S)

The setAction calls record the non-size-changing legalization actions to take on specificly-sized typ...

std::pair< uint16_t, LegacyLegalizeActions::LegacyLegalizeAction > SizeAndAction

static SizeAndActionsVec unsupportedForDifferentSizes(const SizeAndActionsVec &v)

A SizeChangeStrategy for the common case where legalization for a particular operation consists of on...

static LLVM_ABI SizeAndActionsVec increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec &v, LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction, LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction)

Helper function to implement many typical SizeChangeStrategy functions.

Definition LegacyLegalizerInfo.cpp:211

static SizeAndActionsVec narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v)

LLVM_ABI LegacyLegalizerInfo()

Definition LegacyLegalizerInfo.cpp:67

The instances of the Type class are immutable: once they are created, they are never changed.

This class implements an extremely fast bulk output stream that can only output to a stream.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ Bitcast

Perform the operation on a different, but equivalently sized type.

@ MoreElements

The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...

@ FewerElements

The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...

@ Unsupported

This operation is completely unsupported on the target.

@ NarrowScalar

The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.

@ Lower

The operation itself must be expressed in terms of simpler actions on this target.

@ Custom

The target wants to do something special with this combination of operand and type.

@ NotFound

Sentinel value for when no action was found in the specified table.

@ WidenScalar

The operation should be implemented in terms of a wider scalar base-type.

@ Libcall

The operation should be implemented as a call to some kind of runtime support library.

This is an optimization pass for GlobalISel generic memory operations.

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

auto partition_point(R &&Range, Predicate P)

Binary search for the first iterator in a range where a predicate is false.

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)

ArrayRef(const T &OneElt) -> ArrayRef< T >

Legalization is decided based on an instruction's opcode, which type slot we're considering,...

The LegalityQuery object bundles together all the information that's needed to decide whether a given...