blob: 164b255cd44ba3d34084d42dc73b5043492c44c6 [file] [log] [blame]
Sam Parker3828c6f2018-07-23 12:27:47 +00001//===----- ARMCodeGenPrepare.cpp ------------------------------------------===//
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/// \file
11/// This pass inserts intrinsics to handle small types that would otherwise be
12/// promoted during legalization. Here we can manually promote types or insert
13/// intrinsics which can handle narrow types that aren't supported by the
14/// register classes.
15//
16//===----------------------------------------------------------------------===//
17
18#include "ARM.h"
19#include "ARMSubtarget.h"
20#include "ARMTargetMachine.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/CodeGen/Passes.h"
23#include "llvm/CodeGen/TargetPassConfig.h"
24#include "llvm/IR/Attributes.h"
25#include "llvm/IR/BasicBlock.h"
26#include "llvm/IR/IRBuilder.h"
27#include "llvm/IR/Constants.h"
28#include "llvm/IR/InstrTypes.h"
29#include "llvm/IR/Instruction.h"
30#include "llvm/IR/Instructions.h"
31#include "llvm/IR/IntrinsicInst.h"
32#include "llvm/IR/Intrinsics.h"
33#include "llvm/IR/Type.h"
34#include "llvm/IR/Value.h"
35#include "llvm/IR/Verifier.h"
36#include "llvm/Pass.h"
37#include "llvm/Support/Casting.h"
38#include "llvm/Support/CommandLine.h"
39
40#define DEBUG_TYPE "arm-codegenprepare"
41
42using namespace llvm;
43
44static cl::opt<bool>
Reid Klecknerb32ff462018-07-31 23:09:42 +000045DisableCGP("arm-disable-cgp", cl::Hidden, cl::init(true),
Sam Parker3828c6f2018-07-23 12:27:47 +000046 cl::desc("Disable ARM specific CodeGenPrepare pass"));
47
48static cl::opt<bool>
49EnableDSP("arm-enable-scalar-dsp", cl::Hidden, cl::init(false),
50 cl::desc("Use DSP instructions for scalar operations"));
51
52static cl::opt<bool>
53EnableDSPWithImms("arm-enable-scalar-dsp-imms", cl::Hidden, cl::init(false),
54 cl::desc("Use DSP instructions for scalar operations\
55 with immediate operands"));
56
57namespace {
58
59class IRPromoter {
60 SmallPtrSet<Value*, 8> NewInsts;
61 SmallVector<Instruction*, 4> InstsToRemove;
62 Module *M = nullptr;
63 LLVMContext &Ctx;
64
65public:
66 IRPromoter(Module *M) : M(M), Ctx(M->getContext()) { }
67
68 void Cleanup() {
69 for (auto *I : InstsToRemove) {
70 LLVM_DEBUG(dbgs() << "ARM CGP: Removing " << *I << "\n");
71 I->dropAllReferences();
72 I->eraseFromParent();
73 }
74 InstsToRemove.clear();
75 NewInsts.clear();
76 }
77
78 void Mutate(Type *OrigTy,
79 SmallPtrSetImpl<Value*> &Visited,
80 SmallPtrSetImpl<Value*> &Leaves,
81 SmallPtrSetImpl<Instruction*> &Roots);
82};
83
84class ARMCodeGenPrepare : public FunctionPass {
85 const ARMSubtarget *ST = nullptr;
86 IRPromoter *Promoter = nullptr;
87 std::set<Value*> AllVisited;
Sam Parker3828c6f2018-07-23 12:27:47 +000088
Sam Parker3828c6f2018-07-23 12:27:47 +000089 bool isSupportedValue(Value *V);
90 bool isLegalToPromote(Value *V);
91 bool TryToPromote(Value *V);
92
93public:
94 static char ID;
Sam Parker8c4b9642018-08-10 13:57:13 +000095 static unsigned TypeSize;
96 Type *OrigTy = nullptr;
Sam Parker3828c6f2018-07-23 12:27:47 +000097
98 ARMCodeGenPrepare() : FunctionPass(ID) {}
99
Sam Parker3828c6f2018-07-23 12:27:47 +0000100 void getAnalysisUsage(AnalysisUsage &AU) const override {
101 AU.addRequired<TargetPassConfig>();
102 }
103
104 StringRef getPassName() const override { return "ARM IR optimizations"; }
105
106 bool doInitialization(Module &M) override;
107 bool runOnFunction(Function &F) override;
Matt Morehousea70685f2018-07-23 17:00:45 +0000108 bool doFinalization(Module &M) override;
Sam Parker3828c6f2018-07-23 12:27:47 +0000109};
110
111}
112
113/// Can the given value generate sign bits.
114static bool isSigned(Value *V) {
115 if (!isa<Instruction>(V))
116 return false;
117
118 unsigned Opc = cast<Instruction>(V)->getOpcode();
119 return Opc == Instruction::AShr || Opc == Instruction::SDiv ||
120 Opc == Instruction::SRem;
121}
122
123/// Some instructions can use 8- and 16-bit operands, and we don't need to
124/// promote anything larger. We disallow booleans to make life easier when
125/// dealing with icmps but allow any other integer that is <= 16 bits. Void
126/// types are accepted so we can handle switches.
127static bool isSupportedType(Value *V) {
Sam Parker8c4b9642018-08-10 13:57:13 +0000128 LLVM_DEBUG(dbgs() << "ARM CGP: isSupportedType: " << *V << "\n");
129 Type *Ty = V->getType();
Sam Parker7def86b2018-08-15 07:52:35 +0000130
131 // Allow voids and pointers, these won't be promoted.
132 if (Ty->isVoidTy() || Ty->isPointerTy())
Sam Parker3828c6f2018-07-23 12:27:47 +0000133 return true;
134
Sam Parker8c4b9642018-08-10 13:57:13 +0000135 if (auto *Ld = dyn_cast<LoadInst>(V))
136 Ty = cast<PointerType>(Ld->getPointerOperandType())->getElementType();
137
138 const IntegerType *IntTy = dyn_cast<IntegerType>(Ty);
139 if (!IntTy) {
140 LLVM_DEBUG(dbgs() << "ARM CGP: No, not an integer.\n");
Sam Parker3828c6f2018-07-23 12:27:47 +0000141 return false;
Sam Parker8c4b9642018-08-10 13:57:13 +0000142 }
Sam Parker3828c6f2018-07-23 12:27:47 +0000143
Sam Parker8c4b9642018-08-10 13:57:13 +0000144 return IntTy->getBitWidth() == ARMCodeGenPrepare::TypeSize;
145}
Sam Parker3828c6f2018-07-23 12:27:47 +0000146
Sam Parker8c4b9642018-08-10 13:57:13 +0000147/// Return true if the given value is a leaf in the use-def chain, producing
148/// a narrow (i8, i16) value. These values will be zext to start the promotion
149/// of the tree to i32. We guarantee that these won't populate the upper bits
150/// of the register. ZExt on the loads will be free, and the same for call
151/// return values because we only accept ones that guarantee a zeroext ret val.
152/// Many arguments will have the zeroext attribute too, so those would be free
153/// too.
154static bool isSource(Value *V) {
Sam Parker7def86b2018-08-15 07:52:35 +0000155 if (!isa<IntegerType>(V->getType()))
156 return false;
Sam Parker8c4b9642018-08-10 13:57:13 +0000157 // TODO Allow truncs and zext to be sources.
158 if (isa<Argument>(V))
159 return true;
160 else if (isa<LoadInst>(V))
161 return true;
162 else if (auto *Call = dyn_cast<CallInst>(V))
163 return Call->hasRetAttr(Attribute::AttrKind::ZExt);
164 return false;
Sam Parker3828c6f2018-07-23 12:27:47 +0000165}
166
167/// Return true if V will require any promoted values to be truncated for the
Sam Parker8c4b9642018-08-10 13:57:13 +0000168/// the IR to remain valid. We can't mutate the value type of these
169/// instructions.
Sam Parker3828c6f2018-07-23 12:27:47 +0000170static bool isSink(Value *V) {
Sam Parker8c4b9642018-08-10 13:57:13 +0000171 // TODO The truncate also isn't actually necessary because we would already
172 // proved that the data value is kept within the range of the original data
173 // type.
Sam Parker3828c6f2018-07-23 12:27:47 +0000174 auto UsesNarrowValue = [](Value *V) {
Sam Parker8c4b9642018-08-10 13:57:13 +0000175 return V->getType()->getScalarSizeInBits() == ARMCodeGenPrepare::TypeSize;
Sam Parker3828c6f2018-07-23 12:27:47 +0000176 };
177
178 if (auto *Store = dyn_cast<StoreInst>(V))
179 return UsesNarrowValue(Store->getValueOperand());
180 if (auto *Return = dyn_cast<ReturnInst>(V))
181 return UsesNarrowValue(Return->getReturnValue());
Sam Parker8c4b9642018-08-10 13:57:13 +0000182 if (auto *Trunc = dyn_cast<TruncInst>(V))
183 return UsesNarrowValue(Trunc->getOperand(0));
Sam Parker13567db2018-08-16 10:05:39 +0000184 if (auto *ICmp = dyn_cast<ICmpInst>(V))
185 return ICmp->isSigned();
Sam Parker3828c6f2018-07-23 12:27:47 +0000186
187 return isa<CallInst>(V);
188}
189
Sam Parker3828c6f2018-07-23 12:27:47 +0000190/// Return whether the instruction can be promoted within any modifications to
191/// it's operands or result.
192static bool isSafeOverflow(Instruction *I) {
Sam Parker8c4b9642018-08-10 13:57:13 +0000193 // FIXME Do we need NSW too?
Sam Parker3828c6f2018-07-23 12:27:47 +0000194 if (isa<OverflowingBinaryOperator>(I) && I->hasNoUnsignedWrap())
195 return true;
196
197 unsigned Opc = I->getOpcode();
198 if (Opc == Instruction::Add || Opc == Instruction::Sub) {
199 // We don't care if the add or sub could wrap if the value is decreasing
200 // and is only being used by an unsigned compare.
201 if (!I->hasOneUse() ||
202 !isa<ICmpInst>(*I->user_begin()) ||
203 !isa<ConstantInt>(I->getOperand(1)))
204 return false;
205
206 auto *CI = cast<ICmpInst>(*I->user_begin());
207 if (CI->isSigned())
208 return false;
209
210 bool NegImm = cast<ConstantInt>(I->getOperand(1))->isNegative();
211 bool IsDecreasing = ((Opc == Instruction::Sub) && !NegImm) ||
212 ((Opc == Instruction::Add) && NegImm);
213 if (!IsDecreasing)
214 return false;
215
216 LLVM_DEBUG(dbgs() << "ARM CGP: Allowing safe overflow for " << *I << "\n");
217 return true;
218 }
219
220 // Otherwise, if an instruction is using a negative immediate we will need
221 // to fix it up during the promotion.
222 for (auto &Op : I->operands()) {
223 if (auto *Const = dyn_cast<ConstantInt>(Op))
224 if (Const->isNegative())
225 return false;
226 }
227 return false;
228}
229
230static bool shouldPromote(Value *V) {
Sam Parker7def86b2018-08-15 07:52:35 +0000231 if (!isa<IntegerType>(V->getType()) || isSink(V)) {
232 LLVM_DEBUG(dbgs() << "ARM CGP: Don't need to promote: " << *V << "\n");
Sam Parker8c4b9642018-08-10 13:57:13 +0000233 return false;
Sam Parker7def86b2018-08-15 07:52:35 +0000234 }
Sam Parker8c4b9642018-08-10 13:57:13 +0000235
236 if (isSource(V))
237 return true;
238
Sam Parker3828c6f2018-07-23 12:27:47 +0000239 auto *I = dyn_cast<Instruction>(V);
240 if (!I)
241 return false;
242
Sam Parker8c4b9642018-08-10 13:57:13 +0000243 if (isa<ICmpInst>(I))
Sam Parker3828c6f2018-07-23 12:27:47 +0000244 return false;
245
Sam Parker3828c6f2018-07-23 12:27:47 +0000246 return true;
247}
248
249/// Return whether we can safely mutate V's type to ExtTy without having to be
250/// concerned with zero extending or truncation.
251static bool isPromotedResultSafe(Value *V) {
252 if (!isa<Instruction>(V))
253 return true;
254
255 if (isSigned(V))
256 return false;
257
258 // If I is only being used by something that will require its value to be
259 // truncated, then we don't care about the promoted result.
260 auto *I = cast<Instruction>(V);
261 if (I->hasOneUse() && isSink(*I->use_begin()))
262 return true;
263
264 if (isa<OverflowingBinaryOperator>(I))
265 return isSafeOverflow(I);
266 return true;
267}
268
269/// Return the intrinsic for the instruction that can perform the same
270/// operation but on a narrow type. This is using the parallel dsp intrinsics
271/// on scalar values.
Sam Parker8c4b9642018-08-10 13:57:13 +0000272static Intrinsic::ID getNarrowIntrinsic(Instruction *I) {
Sam Parker3828c6f2018-07-23 12:27:47 +0000273 // Whether we use the signed or unsigned versions of these intrinsics
274 // doesn't matter because we're not using the GE bits that they set in
275 // the APSR.
276 switch(I->getOpcode()) {
277 default:
278 break;
279 case Instruction::Add:
Sam Parker8c4b9642018-08-10 13:57:13 +0000280 return ARMCodeGenPrepare::TypeSize == 16 ? Intrinsic::arm_uadd16 :
Sam Parker3828c6f2018-07-23 12:27:47 +0000281 Intrinsic::arm_uadd8;
282 case Instruction::Sub:
Sam Parker8c4b9642018-08-10 13:57:13 +0000283 return ARMCodeGenPrepare::TypeSize == 16 ? Intrinsic::arm_usub16 :
Sam Parker3828c6f2018-07-23 12:27:47 +0000284 Intrinsic::arm_usub8;
285 }
286 llvm_unreachable("unhandled opcode for narrow intrinsic");
287}
288
289void IRPromoter::Mutate(Type *OrigTy,
290 SmallPtrSetImpl<Value*> &Visited,
291 SmallPtrSetImpl<Value*> &Leaves,
292 SmallPtrSetImpl<Instruction*> &Roots) {
293 IRBuilder<> Builder{Ctx};
294 Type *ExtTy = Type::getInt32Ty(M->getContext());
Sam Parker3828c6f2018-07-23 12:27:47 +0000295 SmallPtrSet<Value*, 8> Promoted;
Sam Parker8c4b9642018-08-10 13:57:13 +0000296 LLVM_DEBUG(dbgs() << "ARM CGP: Promoting use-def chains to from "
297 << ARMCodeGenPrepare::TypeSize << " to 32-bits\n");
Sam Parker3828c6f2018-07-23 12:27:47 +0000298
Sam Parker13567db2018-08-16 10:05:39 +0000299 // Cache original types.
300 DenseMap<Value*, Type*> TruncTysMap;
301 for (auto *V : Visited)
302 TruncTysMap[V] = V->getType();
303
Sam Parker3828c6f2018-07-23 12:27:47 +0000304 auto ReplaceAllUsersOfWith = [&](Value *From, Value *To) {
305 SmallVector<Instruction*, 4> Users;
306 Instruction *InstTo = dyn_cast<Instruction>(To);
307 for (Use &U : From->uses()) {
308 auto *User = cast<Instruction>(U.getUser());
309 if (InstTo && User->isIdenticalTo(InstTo))
310 continue;
311 Users.push_back(User);
312 }
313
314 for (auto &U : Users)
315 U->replaceUsesOfWith(From, To);
316 };
317
318 auto FixConst = [&](ConstantInt *Const, Instruction *I) {
319 Constant *NewConst = nullptr;
320 if (isSafeOverflow(I)) {
321 NewConst = (Const->isNegative()) ?
322 ConstantExpr::getSExt(Const, ExtTy) :
323 ConstantExpr::getZExt(Const, ExtTy);
324 } else {
325 uint64_t NewVal = *Const->getValue().getRawData();
326 if (Const->getType() == Type::getInt16Ty(Ctx))
327 NewVal &= 0xFFFF;
328 else
329 NewVal &= 0xFF;
330 NewConst = ConstantInt::get(ExtTy, NewVal);
331 }
332 I->replaceUsesOfWith(Const, NewConst);
333 };
334
335 auto InsertDSPIntrinsic = [&](Instruction *I) {
336 LLVM_DEBUG(dbgs() << "ARM CGP: Inserting DSP intrinsic for "
337 << *I << "\n");
338 Function *DSPInst =
Sam Parker8c4b9642018-08-10 13:57:13 +0000339 Intrinsic::getDeclaration(M, getNarrowIntrinsic(I));
Sam Parker3828c6f2018-07-23 12:27:47 +0000340 Builder.SetInsertPoint(I);
341 Builder.SetCurrentDebugLocation(I->getDebugLoc());
342 Value *Args[] = { I->getOperand(0), I->getOperand(1) };
343 CallInst *Call = Builder.CreateCall(DSPInst, Args);
344 ReplaceAllUsersOfWith(I, Call);
345 InstsToRemove.push_back(I);
346 NewInsts.insert(Call);
Sam Parker13567db2018-08-16 10:05:39 +0000347 TruncTysMap[Call] = OrigTy;
Sam Parker3828c6f2018-07-23 12:27:47 +0000348 };
349
350 auto InsertZExt = [&](Value *V, Instruction *InsertPt) {
351 LLVM_DEBUG(dbgs() << "ARM CGP: Inserting ZExt for " << *V << "\n");
352 Builder.SetInsertPoint(InsertPt);
353 if (auto *I = dyn_cast<Instruction>(V))
354 Builder.SetCurrentDebugLocation(I->getDebugLoc());
355 auto *ZExt = cast<Instruction>(Builder.CreateZExt(V, ExtTy));
356 if (isa<Argument>(V))
357 ZExt->moveBefore(InsertPt);
358 else
359 ZExt->moveAfter(InsertPt);
360 ReplaceAllUsersOfWith(V, ZExt);
361 NewInsts.insert(ZExt);
Sam Parker13567db2018-08-16 10:05:39 +0000362 TruncTysMap[ZExt] = TruncTysMap[V];
Sam Parker3828c6f2018-07-23 12:27:47 +0000363 };
364
365 // First, insert extending instructions between the leaves and their users.
366 LLVM_DEBUG(dbgs() << "ARM CGP: Promoting leaves:\n");
367 for (auto V : Leaves) {
368 LLVM_DEBUG(dbgs() << " - " << *V << "\n");
Sam Parker8c4b9642018-08-10 13:57:13 +0000369 if (auto *I = dyn_cast<Instruction>(V))
Sam Parker3828c6f2018-07-23 12:27:47 +0000370 InsertZExt(I, I);
371 else if (auto *Arg = dyn_cast<Argument>(V)) {
372 BasicBlock &BB = Arg->getParent()->front();
373 InsertZExt(Arg, &*BB.getFirstInsertionPt());
374 } else {
375 llvm_unreachable("unhandled leaf that needs extending");
376 }
377 Promoted.insert(V);
378 }
379
380 LLVM_DEBUG(dbgs() << "ARM CGP: Mutating the tree..\n");
381 // Then mutate the types of the instructions within the tree. Here we handle
382 // constant operands.
383 for (auto *V : Visited) {
384 if (Leaves.count(V))
385 continue;
386
Sam Parker3828c6f2018-07-23 12:27:47 +0000387 auto *I = cast<Instruction>(V);
388 if (Roots.count(I))
389 continue;
390
Sam Parker7def86b2018-08-15 07:52:35 +0000391 for (unsigned i = 0, e = I->getNumOperands(); i < e; ++i) {
392 Value *Op = I->getOperand(i);
393 if ((Op->getType() == ExtTy) || !isa<IntegerType>(Op->getType()))
Sam Parker3828c6f2018-07-23 12:27:47 +0000394 continue;
395
Sam Parker7def86b2018-08-15 07:52:35 +0000396 if (auto *Const = dyn_cast<ConstantInt>(Op))
Sam Parker3828c6f2018-07-23 12:27:47 +0000397 FixConst(Const, I);
Sam Parker7def86b2018-08-15 07:52:35 +0000398 else if (isa<UndefValue>(Op))
399 I->setOperand(i, UndefValue::get(ExtTy));
Sam Parker3828c6f2018-07-23 12:27:47 +0000400 }
401
402 if (shouldPromote(I)) {
403 I->mutateType(ExtTy);
404 Promoted.insert(I);
405 }
406 }
407
408 // Now we need to remove any zexts that have become unnecessary, as well
409 // as insert any intrinsics.
410 for (auto *V : Visited) {
411 if (Leaves.count(V))
412 continue;
Sam Parker8c4b9642018-08-10 13:57:13 +0000413
Sam Parker3828c6f2018-07-23 12:27:47 +0000414 if (!shouldPromote(V) || isPromotedResultSafe(V))
415 continue;
416
417 // Replace unsafe instructions with appropriate intrinsic calls.
418 InsertDSPIntrinsic(cast<Instruction>(V));
419 }
420
Sam Parker13567db2018-08-16 10:05:39 +0000421 auto InsertTrunc = [&](Value *V) -> Instruction* {
422 if (!isa<Instruction>(V) || !isa<IntegerType>(V->getType()))
423 return nullptr;
424
425 if ((!Promoted.count(V) && !NewInsts.count(V)) || !TruncTysMap.count(V))
426 return nullptr;
427
428 Type *TruncTy = TruncTysMap[V];
429 if (TruncTy == ExtTy)
430 return nullptr;
431
432 LLVM_DEBUG(dbgs() << "ARM CGP: Creating " << *TruncTy << " Trunc for "
433 << *V << "\n");
434 Builder.SetInsertPoint(cast<Instruction>(V));
435 auto *Trunc = cast<Instruction>(Builder.CreateTrunc(V, TruncTy));
436 NewInsts.insert(Trunc);
437 return Trunc;
438 };
439
Sam Parker3828c6f2018-07-23 12:27:47 +0000440 LLVM_DEBUG(dbgs() << "ARM CGP: Fixing up the roots:\n");
441 // Fix up any stores or returns that use the results of the promoted
442 // chain.
443 for (auto I : Roots) {
444 LLVM_DEBUG(dbgs() << " - " << *I << "\n");
Sam Parker13567db2018-08-16 10:05:39 +0000445
446 // Handle calls separately as we need to iterate over arg operands.
447 if (auto *Call = dyn_cast<CallInst>(I)) {
448 for (unsigned i = 0; i < Call->getNumArgOperands(); ++i) {
449 Value *Arg = Call->getArgOperand(i);
450 if (Instruction *Trunc = InsertTrunc(Arg)) {
451 Trunc->moveBefore(Call);
452 Call->setArgOperand(i, Trunc);
453 }
454 }
455 continue;
Sam Parker3828c6f2018-07-23 12:27:47 +0000456 }
457
Sam Parker13567db2018-08-16 10:05:39 +0000458 // Now handle the others.
Sam Parker3828c6f2018-07-23 12:27:47 +0000459 for (unsigned i = 0; i < I->getNumOperands(); ++i) {
Sam Parker13567db2018-08-16 10:05:39 +0000460 if (Instruction *Trunc = InsertTrunc(I->getOperand(i))) {
461 Trunc->moveBefore(I);
462 I->setOperand(i, Trunc);
Sam Parker3828c6f2018-07-23 12:27:47 +0000463 }
464 }
465 }
466 LLVM_DEBUG(dbgs() << "ARM CGP: Mutation complete.\n");
467}
468
Sam Parker8c4b9642018-08-10 13:57:13 +0000469/// We accept most instructions, as well as Arguments and ConstantInsts. We
470/// Disallow casts other than zext and truncs and only allow calls if their
471/// return value is zeroext. We don't allow opcodes that can introduce sign
472/// bits.
473bool ARMCodeGenPrepare::isSupportedValue(Value *V) {
474 LLVM_DEBUG(dbgs() << "ARM CGP: Is " << *V << " supported?\n");
475
Sam Parker13567db2018-08-16 10:05:39 +0000476 if (isa<ICmpInst>(V))
477 return true;
Sam Parker8c4b9642018-08-10 13:57:13 +0000478
479 // Memory instructions
480 if (isa<StoreInst>(V) || isa<GetElementPtrInst>(V))
481 return true;
482
483 // Branches and targets.
484 if( isa<BranchInst>(V) || isa<SwitchInst>(V) || isa<BasicBlock>(V))
485 return true;
486
487 // Non-instruction values that we can handle.
Sam Parker7def86b2018-08-15 07:52:35 +0000488 if ((isa<Constant>(V) && !isa<ConstantExpr>(V)) || isa<Argument>(V))
Sam Parker8c4b9642018-08-10 13:57:13 +0000489 return isSupportedType(V);
490
491 if (isa<PHINode>(V) || isa<SelectInst>(V) || isa<ReturnInst>(V) ||
492 isa<LoadInst>(V))
493 return isSupportedType(V);
494
495 // Currently, Trunc is the only cast we support.
496 if (auto *Trunc = dyn_cast<TruncInst>(V))
497 return isSupportedType(Trunc->getOperand(0));
498
499 // Special cases for calls as we need to check for zeroext
500 // TODO We should accept calls even if they don't have zeroext, as they can
501 // still be roots.
502 if (auto *Call = dyn_cast<CallInst>(V))
503 return isSupportedType(Call) &&
504 Call->hasRetAttr(Attribute::AttrKind::ZExt);
505
506 if (!isa<BinaryOperator>(V)) {
507 LLVM_DEBUG(dbgs() << "ARM CGP: No, not a binary operator.\n");
508 return false;
509 }
510 if (!isSupportedType(V))
511 return false;
512
513 bool res = !isSigned(V);
514 if (!res)
515 LLVM_DEBUG(dbgs() << "ARM CGP: No, it's a signed instruction.\n");
516 return res;
517}
518
519/// Check that the type of V would be promoted and that the original type is
520/// smaller than the targeted promoted type. Check that we're not trying to
521/// promote something larger than our base 'TypeSize' type.
522bool ARMCodeGenPrepare::isLegalToPromote(Value *V) {
523 if (isPromotedResultSafe(V))
524 return true;
525
526 auto *I = dyn_cast<Instruction>(V);
527 if (!I)
528 return false;
529
530 // If promotion is not safe, can we use a DSP instruction to natively
531 // handle the narrow type?
Sam Parker3828c6f2018-07-23 12:27:47 +0000532 if (!ST->hasDSP() || !EnableDSP || !isSupportedType(I))
533 return false;
534
535 if (ST->isThumb() && !ST->hasThumb2())
536 return false;
537
538 if (I->getOpcode() != Instruction::Add && I->getOpcode() != Instruction::Sub)
539 return false;
540
541 // TODO
542 // Would it be profitable? For Thumb code, these parallel DSP instructions
543 // are only Thumb-2, so we wouldn't be able to dual issue on Cortex-M33. For
544 // Cortex-A, specifically Cortex-A72, the latency is double and throughput is
545 // halved. They also do not take immediates as operands.
546 for (auto &Op : I->operands()) {
547 if (isa<Constant>(Op)) {
548 if (!EnableDSPWithImms)
549 return false;
550 }
551 }
552 return true;
553}
554
Sam Parker3828c6f2018-07-23 12:27:47 +0000555bool ARMCodeGenPrepare::TryToPromote(Value *V) {
556 OrigTy = V->getType();
557 TypeSize = OrigTy->getPrimitiveSizeInBits();
Sam Parkerfabf7fe2018-08-15 13:29:50 +0000558 if (TypeSize > 16 || TypeSize < 8)
Sam Parker8c4b9642018-08-10 13:57:13 +0000559 return false;
Sam Parker3828c6f2018-07-23 12:27:47 +0000560
561 if (!isSupportedValue(V) || !shouldPromote(V) || !isLegalToPromote(V))
562 return false;
563
Sam Parker8c4b9642018-08-10 13:57:13 +0000564 LLVM_DEBUG(dbgs() << "ARM CGP: TryToPromote: " << *V << ", TypeSize = "
565 << TypeSize << "\n");
Sam Parker3828c6f2018-07-23 12:27:47 +0000566
567 SetVector<Value*> WorkList;
568 SmallPtrSet<Value*, 8> Leaves;
569 SmallPtrSet<Instruction*, 4> Roots;
570 WorkList.insert(V);
571 SmallPtrSet<Value*, 16> CurrentVisited;
572 CurrentVisited.clear();
573
574 // Return true if the given value can, or has been, visited. Add V to the
575 // worklist if needed.
576 auto AddLegalInst = [&](Value *V) {
577 if (CurrentVisited.count(V))
578 return true;
579
580 if (!isSupportedValue(V) || (shouldPromote(V) && !isLegalToPromote(V))) {
581 LLVM_DEBUG(dbgs() << "ARM CGP: Can't handle: " << *V << "\n");
582 return false;
583 }
584
585 WorkList.insert(V);
586 return true;
587 };
588
589 // Iterate through, and add to, a tree of operands and users in the use-def.
590 while (!WorkList.empty()) {
591 Value *V = WorkList.back();
592 WorkList.pop_back();
593 if (CurrentVisited.count(V))
594 continue;
595
Sam Parker7def86b2018-08-15 07:52:35 +0000596 // Ignore non-instructions, other than arguments.
Sam Parker3828c6f2018-07-23 12:27:47 +0000597 if (!isa<Instruction>(V) && !isSource(V))
598 continue;
599
600 // If we've already visited this value from somewhere, bail now because
601 // the tree has already been explored.
602 // TODO: This could limit the transform, ie if we try to promote something
603 // from an i8 and fail first, before trying an i16.
604 if (AllVisited.count(V)) {
605 LLVM_DEBUG(dbgs() << "ARM CGP: Already visited this: " << *V << "\n");
606 return false;
607 }
608
609 CurrentVisited.insert(V);
610 AllVisited.insert(V);
611
612 // Calls can be both sources and sinks.
613 if (isSink(V))
614 Roots.insert(cast<Instruction>(V));
615 if (isSource(V))
616 Leaves.insert(V);
617 else if (auto *I = dyn_cast<Instruction>(V)) {
618 // Visit operands of any instruction visited.
619 for (auto &U : I->operands()) {
620 if (!AddLegalInst(U))
621 return false;
622 }
623 }
624
625 // Don't visit users of a node which isn't going to be mutated unless its a
626 // source.
627 if (isSource(V) || shouldPromote(V)) {
628 for (Use &U : V->uses()) {
629 if (!AddLegalInst(U.getUser()))
630 return false;
631 }
632 }
633 }
634
Sam Parker3828c6f2018-07-23 12:27:47 +0000635 LLVM_DEBUG(dbgs() << "ARM CGP: Visited nodes:\n";
636 for (auto *I : CurrentVisited)
637 I->dump();
638 );
Sam Parker7def86b2018-08-15 07:52:35 +0000639 unsigned ToPromote = 0;
640 for (auto *V : CurrentVisited) {
641 if (Leaves.count(V))
642 continue;
643 if (Roots.count(cast<Instruction>(V)))
644 continue;
645 ++ToPromote;
646 }
647
648 if (ToPromote < 2)
649 return false;
Sam Parker3828c6f2018-07-23 12:27:47 +0000650
651 Promoter->Mutate(OrigTy, CurrentVisited, Leaves, Roots);
652 return true;
653}
654
655bool ARMCodeGenPrepare::doInitialization(Module &M) {
656 Promoter = new IRPromoter(&M);
657 return false;
658}
659
660bool ARMCodeGenPrepare::runOnFunction(Function &F) {
661 if (skipFunction(F) || DisableCGP)
662 return false;
663
664 auto *TPC = &getAnalysis<TargetPassConfig>();
665 if (!TPC)
666 return false;
667
668 const TargetMachine &TM = TPC->getTM<TargetMachine>();
669 ST = &TM.getSubtarget<ARMSubtarget>(F);
670 bool MadeChange = false;
671 LLVM_DEBUG(dbgs() << "ARM CGP: Running on " << F.getName() << "\n");
672
673 // Search up from icmps to try to promote their operands.
674 for (BasicBlock &BB : F) {
675 auto &Insts = BB.getInstList();
676 for (auto &I : Insts) {
677 if (AllVisited.count(&I))
678 continue;
679
680 if (isa<ICmpInst>(I)) {
681 auto &CI = cast<ICmpInst>(I);
682
683 // Skip signed or pointer compares
684 if (CI.isSigned() || !isa<IntegerType>(CI.getOperand(0)->getType()))
685 continue;
686
687 LLVM_DEBUG(dbgs() << "ARM CGP: Searching from: " << CI << "\n");
688 for (auto &Op : CI.operands()) {
Sam Parker8c4b9642018-08-10 13:57:13 +0000689 if (auto *I = dyn_cast<Instruction>(Op))
690 MadeChange |= TryToPromote(I);
Sam Parker3828c6f2018-07-23 12:27:47 +0000691 }
692 }
693 }
694 Promoter->Cleanup();
695 LLVM_DEBUG(if (verifyFunction(F, &dbgs())) {
696 dbgs();
697 report_fatal_error("Broken function after type promotion");
698 });
699 }
700 if (MadeChange)
701 LLVM_DEBUG(dbgs() << "After ARMCodeGenPrepare: " << F << "\n");
702
703 return MadeChange;
704}
705
Matt Morehousea70685f2018-07-23 17:00:45 +0000706bool ARMCodeGenPrepare::doFinalization(Module &M) {
707 delete Promoter;
708 return false;
709}
710
Sam Parker3828c6f2018-07-23 12:27:47 +0000711INITIALIZE_PASS_BEGIN(ARMCodeGenPrepare, DEBUG_TYPE,
712 "ARM IR optimizations", false, false)
713INITIALIZE_PASS_END(ARMCodeGenPrepare, DEBUG_TYPE, "ARM IR optimizations",
714 false, false)
715
716char ARMCodeGenPrepare::ID = 0;
Sam Parker8c4b9642018-08-10 13:57:13 +0000717unsigned ARMCodeGenPrepare::TypeSize = 0;
Sam Parker3828c6f2018-07-23 12:27:47 +0000718
719FunctionPass *llvm::createARMCodeGenPreparePass() {
720 return new ARMCodeGenPrepare();
721}