blob: 296a22fa45ad98f8a60457c7638cf0e9fb76802c [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 Parker0e2f0bd2018-08-16 11:54:09 +0000184 if (auto *ZExt = dyn_cast<ZExtInst>(V))
185 return UsesNarrowValue(ZExt->getOperand(0));
Sam Parker13567db2018-08-16 10:05:39 +0000186 if (auto *ICmp = dyn_cast<ICmpInst>(V))
187 return ICmp->isSigned();
Sam Parker3828c6f2018-07-23 12:27:47 +0000188
189 return isa<CallInst>(V);
190}
191
Sam Parker3828c6f2018-07-23 12:27:47 +0000192/// Return whether the instruction can be promoted within any modifications to
193/// it's operands or result.
194static bool isSafeOverflow(Instruction *I) {
Sam Parker8c4b9642018-08-10 13:57:13 +0000195 // FIXME Do we need NSW too?
Sam Parker3828c6f2018-07-23 12:27:47 +0000196 if (isa<OverflowingBinaryOperator>(I) && I->hasNoUnsignedWrap())
197 return true;
198
199 unsigned Opc = I->getOpcode();
200 if (Opc == Instruction::Add || Opc == Instruction::Sub) {
201 // We don't care if the add or sub could wrap if the value is decreasing
202 // and is only being used by an unsigned compare.
203 if (!I->hasOneUse() ||
204 !isa<ICmpInst>(*I->user_begin()) ||
205 !isa<ConstantInt>(I->getOperand(1)))
206 return false;
207
208 auto *CI = cast<ICmpInst>(*I->user_begin());
209 if (CI->isSigned())
210 return false;
211
212 bool NegImm = cast<ConstantInt>(I->getOperand(1))->isNegative();
213 bool IsDecreasing = ((Opc == Instruction::Sub) && !NegImm) ||
214 ((Opc == Instruction::Add) && NegImm);
215 if (!IsDecreasing)
216 return false;
217
218 LLVM_DEBUG(dbgs() << "ARM CGP: Allowing safe overflow for " << *I << "\n");
219 return true;
220 }
221
222 // Otherwise, if an instruction is using a negative immediate we will need
223 // to fix it up during the promotion.
224 for (auto &Op : I->operands()) {
225 if (auto *Const = dyn_cast<ConstantInt>(Op))
226 if (Const->isNegative())
227 return false;
228 }
229 return false;
230}
231
232static bool shouldPromote(Value *V) {
Sam Parker7def86b2018-08-15 07:52:35 +0000233 if (!isa<IntegerType>(V->getType()) || isSink(V)) {
234 LLVM_DEBUG(dbgs() << "ARM CGP: Don't need to promote: " << *V << "\n");
Sam Parker8c4b9642018-08-10 13:57:13 +0000235 return false;
Sam Parker7def86b2018-08-15 07:52:35 +0000236 }
Sam Parker8c4b9642018-08-10 13:57:13 +0000237
238 if (isSource(V))
239 return true;
240
Sam Parker3828c6f2018-07-23 12:27:47 +0000241 auto *I = dyn_cast<Instruction>(V);
242 if (!I)
243 return false;
244
Sam Parker8c4b9642018-08-10 13:57:13 +0000245 if (isa<ICmpInst>(I))
Sam Parker3828c6f2018-07-23 12:27:47 +0000246 return false;
247
Sam Parker3828c6f2018-07-23 12:27:47 +0000248 return true;
249}
250
251/// Return whether we can safely mutate V's type to ExtTy without having to be
252/// concerned with zero extending or truncation.
253static bool isPromotedResultSafe(Value *V) {
254 if (!isa<Instruction>(V))
255 return true;
256
257 if (isSigned(V))
258 return false;
259
260 // If I is only being used by something that will require its value to be
261 // truncated, then we don't care about the promoted result.
262 auto *I = cast<Instruction>(V);
263 if (I->hasOneUse() && isSink(*I->use_begin()))
264 return true;
265
266 if (isa<OverflowingBinaryOperator>(I))
267 return isSafeOverflow(I);
268 return true;
269}
270
271/// Return the intrinsic for the instruction that can perform the same
272/// operation but on a narrow type. This is using the parallel dsp intrinsics
273/// on scalar values.
Sam Parker8c4b9642018-08-10 13:57:13 +0000274static Intrinsic::ID getNarrowIntrinsic(Instruction *I) {
Sam Parker3828c6f2018-07-23 12:27:47 +0000275 // Whether we use the signed or unsigned versions of these intrinsics
276 // doesn't matter because we're not using the GE bits that they set in
277 // the APSR.
278 switch(I->getOpcode()) {
279 default:
280 break;
281 case Instruction::Add:
Sam Parker8c4b9642018-08-10 13:57:13 +0000282 return ARMCodeGenPrepare::TypeSize == 16 ? Intrinsic::arm_uadd16 :
Sam Parker3828c6f2018-07-23 12:27:47 +0000283 Intrinsic::arm_uadd8;
284 case Instruction::Sub:
Sam Parker8c4b9642018-08-10 13:57:13 +0000285 return ARMCodeGenPrepare::TypeSize == 16 ? Intrinsic::arm_usub16 :
Sam Parker3828c6f2018-07-23 12:27:47 +0000286 Intrinsic::arm_usub8;
287 }
288 llvm_unreachable("unhandled opcode for narrow intrinsic");
289}
290
291void IRPromoter::Mutate(Type *OrigTy,
292 SmallPtrSetImpl<Value*> &Visited,
293 SmallPtrSetImpl<Value*> &Leaves,
294 SmallPtrSetImpl<Instruction*> &Roots) {
295 IRBuilder<> Builder{Ctx};
296 Type *ExtTy = Type::getInt32Ty(M->getContext());
Sam Parker3828c6f2018-07-23 12:27:47 +0000297 SmallPtrSet<Value*, 8> Promoted;
Sam Parker8c4b9642018-08-10 13:57:13 +0000298 LLVM_DEBUG(dbgs() << "ARM CGP: Promoting use-def chains to from "
299 << ARMCodeGenPrepare::TypeSize << " to 32-bits\n");
Sam Parker3828c6f2018-07-23 12:27:47 +0000300
Sam Parker13567db2018-08-16 10:05:39 +0000301 // Cache original types.
302 DenseMap<Value*, Type*> TruncTysMap;
303 for (auto *V : Visited)
304 TruncTysMap[V] = V->getType();
305
Sam Parker3828c6f2018-07-23 12:27:47 +0000306 auto ReplaceAllUsersOfWith = [&](Value *From, Value *To) {
307 SmallVector<Instruction*, 4> Users;
308 Instruction *InstTo = dyn_cast<Instruction>(To);
309 for (Use &U : From->uses()) {
310 auto *User = cast<Instruction>(U.getUser());
311 if (InstTo && User->isIdenticalTo(InstTo))
312 continue;
313 Users.push_back(User);
314 }
315
316 for (auto &U : Users)
317 U->replaceUsesOfWith(From, To);
318 };
319
320 auto FixConst = [&](ConstantInt *Const, Instruction *I) {
321 Constant *NewConst = nullptr;
322 if (isSafeOverflow(I)) {
323 NewConst = (Const->isNegative()) ?
324 ConstantExpr::getSExt(Const, ExtTy) :
325 ConstantExpr::getZExt(Const, ExtTy);
326 } else {
327 uint64_t NewVal = *Const->getValue().getRawData();
328 if (Const->getType() == Type::getInt16Ty(Ctx))
329 NewVal &= 0xFFFF;
330 else
331 NewVal &= 0xFF;
332 NewConst = ConstantInt::get(ExtTy, NewVal);
333 }
334 I->replaceUsesOfWith(Const, NewConst);
335 };
336
337 auto InsertDSPIntrinsic = [&](Instruction *I) {
338 LLVM_DEBUG(dbgs() << "ARM CGP: Inserting DSP intrinsic for "
339 << *I << "\n");
340 Function *DSPInst =
Sam Parker8c4b9642018-08-10 13:57:13 +0000341 Intrinsic::getDeclaration(M, getNarrowIntrinsic(I));
Sam Parker3828c6f2018-07-23 12:27:47 +0000342 Builder.SetInsertPoint(I);
343 Builder.SetCurrentDebugLocation(I->getDebugLoc());
344 Value *Args[] = { I->getOperand(0), I->getOperand(1) };
345 CallInst *Call = Builder.CreateCall(DSPInst, Args);
346 ReplaceAllUsersOfWith(I, Call);
347 InstsToRemove.push_back(I);
348 NewInsts.insert(Call);
Sam Parker13567db2018-08-16 10:05:39 +0000349 TruncTysMap[Call] = OrigTy;
Sam Parker3828c6f2018-07-23 12:27:47 +0000350 };
351
352 auto InsertZExt = [&](Value *V, Instruction *InsertPt) {
353 LLVM_DEBUG(dbgs() << "ARM CGP: Inserting ZExt for " << *V << "\n");
354 Builder.SetInsertPoint(InsertPt);
355 if (auto *I = dyn_cast<Instruction>(V))
356 Builder.SetCurrentDebugLocation(I->getDebugLoc());
357 auto *ZExt = cast<Instruction>(Builder.CreateZExt(V, ExtTy));
358 if (isa<Argument>(V))
359 ZExt->moveBefore(InsertPt);
360 else
361 ZExt->moveAfter(InsertPt);
362 ReplaceAllUsersOfWith(V, ZExt);
363 NewInsts.insert(ZExt);
Sam Parker13567db2018-08-16 10:05:39 +0000364 TruncTysMap[ZExt] = TruncTysMap[V];
Sam Parker3828c6f2018-07-23 12:27:47 +0000365 };
366
367 // First, insert extending instructions between the leaves and their users.
368 LLVM_DEBUG(dbgs() << "ARM CGP: Promoting leaves:\n");
369 for (auto V : Leaves) {
370 LLVM_DEBUG(dbgs() << " - " << *V << "\n");
Sam Parker8c4b9642018-08-10 13:57:13 +0000371 if (auto *I = dyn_cast<Instruction>(V))
Sam Parker3828c6f2018-07-23 12:27:47 +0000372 InsertZExt(I, I);
373 else if (auto *Arg = dyn_cast<Argument>(V)) {
374 BasicBlock &BB = Arg->getParent()->front();
375 InsertZExt(Arg, &*BB.getFirstInsertionPt());
376 } else {
377 llvm_unreachable("unhandled leaf that needs extending");
378 }
379 Promoted.insert(V);
380 }
381
382 LLVM_DEBUG(dbgs() << "ARM CGP: Mutating the tree..\n");
383 // Then mutate the types of the instructions within the tree. Here we handle
384 // constant operands.
385 for (auto *V : Visited) {
386 if (Leaves.count(V))
387 continue;
388
Sam Parker3828c6f2018-07-23 12:27:47 +0000389 auto *I = cast<Instruction>(V);
390 if (Roots.count(I))
391 continue;
392
Sam Parker7def86b2018-08-15 07:52:35 +0000393 for (unsigned i = 0, e = I->getNumOperands(); i < e; ++i) {
394 Value *Op = I->getOperand(i);
395 if ((Op->getType() == ExtTy) || !isa<IntegerType>(Op->getType()))
Sam Parker3828c6f2018-07-23 12:27:47 +0000396 continue;
397
Sam Parker7def86b2018-08-15 07:52:35 +0000398 if (auto *Const = dyn_cast<ConstantInt>(Op))
Sam Parker3828c6f2018-07-23 12:27:47 +0000399 FixConst(Const, I);
Sam Parker7def86b2018-08-15 07:52:35 +0000400 else if (isa<UndefValue>(Op))
401 I->setOperand(i, UndefValue::get(ExtTy));
Sam Parker3828c6f2018-07-23 12:27:47 +0000402 }
403
404 if (shouldPromote(I)) {
405 I->mutateType(ExtTy);
406 Promoted.insert(I);
407 }
408 }
409
410 // Now we need to remove any zexts that have become unnecessary, as well
411 // as insert any intrinsics.
412 for (auto *V : Visited) {
413 if (Leaves.count(V))
414 continue;
Sam Parker8c4b9642018-08-10 13:57:13 +0000415
Sam Parker3828c6f2018-07-23 12:27:47 +0000416 if (!shouldPromote(V) || isPromotedResultSafe(V))
417 continue;
418
419 // Replace unsafe instructions with appropriate intrinsic calls.
420 InsertDSPIntrinsic(cast<Instruction>(V));
421 }
422
Sam Parker13567db2018-08-16 10:05:39 +0000423 auto InsertTrunc = [&](Value *V) -> Instruction* {
424 if (!isa<Instruction>(V) || !isa<IntegerType>(V->getType()))
425 return nullptr;
426
Sam Parker0e2f0bd2018-08-16 11:54:09 +0000427 if ((!Promoted.count(V) && !NewInsts.count(V)) || !TruncTysMap.count(V) ||
428 Leaves.count(V))
Sam Parker13567db2018-08-16 10:05:39 +0000429 return nullptr;
430
431 Type *TruncTy = TruncTysMap[V];
432 if (TruncTy == ExtTy)
433 return nullptr;
434
435 LLVM_DEBUG(dbgs() << "ARM CGP: Creating " << *TruncTy << " Trunc for "
436 << *V << "\n");
437 Builder.SetInsertPoint(cast<Instruction>(V));
438 auto *Trunc = cast<Instruction>(Builder.CreateTrunc(V, TruncTy));
439 NewInsts.insert(Trunc);
440 return Trunc;
441 };
442
Sam Parker3828c6f2018-07-23 12:27:47 +0000443 LLVM_DEBUG(dbgs() << "ARM CGP: Fixing up the roots:\n");
444 // Fix up any stores or returns that use the results of the promoted
445 // chain.
446 for (auto I : Roots) {
447 LLVM_DEBUG(dbgs() << " - " << *I << "\n");
Sam Parker13567db2018-08-16 10:05:39 +0000448
449 // Handle calls separately as we need to iterate over arg operands.
450 if (auto *Call = dyn_cast<CallInst>(I)) {
451 for (unsigned i = 0; i < Call->getNumArgOperands(); ++i) {
452 Value *Arg = Call->getArgOperand(i);
453 if (Instruction *Trunc = InsertTrunc(Arg)) {
454 Trunc->moveBefore(Call);
455 Call->setArgOperand(i, Trunc);
456 }
457 }
458 continue;
Sam Parker3828c6f2018-07-23 12:27:47 +0000459 }
460
Sam Parker13567db2018-08-16 10:05:39 +0000461 // Now handle the others.
Sam Parker3828c6f2018-07-23 12:27:47 +0000462 for (unsigned i = 0; i < I->getNumOperands(); ++i) {
Sam Parker13567db2018-08-16 10:05:39 +0000463 if (Instruction *Trunc = InsertTrunc(I->getOperand(i))) {
464 Trunc->moveBefore(I);
465 I->setOperand(i, Trunc);
Sam Parker3828c6f2018-07-23 12:27:47 +0000466 }
467 }
468 }
Sam Parker0e2f0bd2018-08-16 11:54:09 +0000469 LLVM_DEBUG(dbgs() << "ARM CGP: Mutation complete:\n");
Sam Parker3828c6f2018-07-23 12:27:47 +0000470}
471
Sam Parker8c4b9642018-08-10 13:57:13 +0000472/// We accept most instructions, as well as Arguments and ConstantInsts. We
473/// Disallow casts other than zext and truncs and only allow calls if their
474/// return value is zeroext. We don't allow opcodes that can introduce sign
475/// bits.
476bool ARMCodeGenPrepare::isSupportedValue(Value *V) {
477 LLVM_DEBUG(dbgs() << "ARM CGP: Is " << *V << " supported?\n");
478
Sam Parker13567db2018-08-16 10:05:39 +0000479 if (isa<ICmpInst>(V))
480 return true;
Sam Parker8c4b9642018-08-10 13:57:13 +0000481
482 // Memory instructions
483 if (isa<StoreInst>(V) || isa<GetElementPtrInst>(V))
484 return true;
485
486 // Branches and targets.
487 if( isa<BranchInst>(V) || isa<SwitchInst>(V) || isa<BasicBlock>(V))
488 return true;
489
490 // Non-instruction values that we can handle.
Sam Parker7def86b2018-08-15 07:52:35 +0000491 if ((isa<Constant>(V) && !isa<ConstantExpr>(V)) || isa<Argument>(V))
Sam Parker8c4b9642018-08-10 13:57:13 +0000492 return isSupportedType(V);
493
494 if (isa<PHINode>(V) || isa<SelectInst>(V) || isa<ReturnInst>(V) ||
495 isa<LoadInst>(V))
496 return isSupportedType(V);
497
Sam Parker8c4b9642018-08-10 13:57:13 +0000498 if (auto *Trunc = dyn_cast<TruncInst>(V))
499 return isSupportedType(Trunc->getOperand(0));
500
Sam Parker0e2f0bd2018-08-16 11:54:09 +0000501 if (auto *ZExt = dyn_cast<ZExtInst>(V))
502 return isSupportedType(ZExt->getOperand(0));
503
Sam Parker8c4b9642018-08-10 13:57:13 +0000504 // Special cases for calls as we need to check for zeroext
505 // TODO We should accept calls even if they don't have zeroext, as they can
506 // still be roots.
507 if (auto *Call = dyn_cast<CallInst>(V))
508 return isSupportedType(Call) &&
509 Call->hasRetAttr(Attribute::AttrKind::ZExt);
510
511 if (!isa<BinaryOperator>(V)) {
512 LLVM_DEBUG(dbgs() << "ARM CGP: No, not a binary operator.\n");
513 return false;
514 }
515 if (!isSupportedType(V))
516 return false;
517
518 bool res = !isSigned(V);
519 if (!res)
520 LLVM_DEBUG(dbgs() << "ARM CGP: No, it's a signed instruction.\n");
521 return res;
522}
523
524/// Check that the type of V would be promoted and that the original type is
525/// smaller than the targeted promoted type. Check that we're not trying to
526/// promote something larger than our base 'TypeSize' type.
527bool ARMCodeGenPrepare::isLegalToPromote(Value *V) {
528 if (isPromotedResultSafe(V))
529 return true;
530
531 auto *I = dyn_cast<Instruction>(V);
532 if (!I)
533 return false;
534
535 // If promotion is not safe, can we use a DSP instruction to natively
536 // handle the narrow type?
Sam Parker3828c6f2018-07-23 12:27:47 +0000537 if (!ST->hasDSP() || !EnableDSP || !isSupportedType(I))
538 return false;
539
540 if (ST->isThumb() && !ST->hasThumb2())
541 return false;
542
543 if (I->getOpcode() != Instruction::Add && I->getOpcode() != Instruction::Sub)
544 return false;
545
546 // TODO
547 // Would it be profitable? For Thumb code, these parallel DSP instructions
548 // are only Thumb-2, so we wouldn't be able to dual issue on Cortex-M33. For
549 // Cortex-A, specifically Cortex-A72, the latency is double and throughput is
550 // halved. They also do not take immediates as operands.
551 for (auto &Op : I->operands()) {
552 if (isa<Constant>(Op)) {
553 if (!EnableDSPWithImms)
554 return false;
555 }
556 }
557 return true;
558}
559
Sam Parker3828c6f2018-07-23 12:27:47 +0000560bool ARMCodeGenPrepare::TryToPromote(Value *V) {
561 OrigTy = V->getType();
562 TypeSize = OrigTy->getPrimitiveSizeInBits();
Sam Parkerfabf7fe2018-08-15 13:29:50 +0000563 if (TypeSize > 16 || TypeSize < 8)
Sam Parker8c4b9642018-08-10 13:57:13 +0000564 return false;
Sam Parker3828c6f2018-07-23 12:27:47 +0000565
566 if (!isSupportedValue(V) || !shouldPromote(V) || !isLegalToPromote(V))
567 return false;
568
Sam Parker8c4b9642018-08-10 13:57:13 +0000569 LLVM_DEBUG(dbgs() << "ARM CGP: TryToPromote: " << *V << ", TypeSize = "
570 << TypeSize << "\n");
Sam Parker3828c6f2018-07-23 12:27:47 +0000571
572 SetVector<Value*> WorkList;
573 SmallPtrSet<Value*, 8> Leaves;
574 SmallPtrSet<Instruction*, 4> Roots;
575 WorkList.insert(V);
576 SmallPtrSet<Value*, 16> CurrentVisited;
577 CurrentVisited.clear();
578
579 // Return true if the given value can, or has been, visited. Add V to the
580 // worklist if needed.
581 auto AddLegalInst = [&](Value *V) {
582 if (CurrentVisited.count(V))
583 return true;
584
585 if (!isSupportedValue(V) || (shouldPromote(V) && !isLegalToPromote(V))) {
586 LLVM_DEBUG(dbgs() << "ARM CGP: Can't handle: " << *V << "\n");
587 return false;
588 }
589
590 WorkList.insert(V);
591 return true;
592 };
593
594 // Iterate through, and add to, a tree of operands and users in the use-def.
595 while (!WorkList.empty()) {
596 Value *V = WorkList.back();
597 WorkList.pop_back();
598 if (CurrentVisited.count(V))
599 continue;
600
Sam Parker7def86b2018-08-15 07:52:35 +0000601 // Ignore non-instructions, other than arguments.
Sam Parker3828c6f2018-07-23 12:27:47 +0000602 if (!isa<Instruction>(V) && !isSource(V))
603 continue;
604
605 // If we've already visited this value from somewhere, bail now because
606 // the tree has already been explored.
607 // TODO: This could limit the transform, ie if we try to promote something
608 // from an i8 and fail first, before trying an i16.
609 if (AllVisited.count(V)) {
610 LLVM_DEBUG(dbgs() << "ARM CGP: Already visited this: " << *V << "\n");
611 return false;
612 }
613
614 CurrentVisited.insert(V);
615 AllVisited.insert(V);
616
617 // Calls can be both sources and sinks.
618 if (isSink(V))
619 Roots.insert(cast<Instruction>(V));
620 if (isSource(V))
621 Leaves.insert(V);
622 else if (auto *I = dyn_cast<Instruction>(V)) {
623 // Visit operands of any instruction visited.
624 for (auto &U : I->operands()) {
625 if (!AddLegalInst(U))
626 return false;
627 }
628 }
629
630 // Don't visit users of a node which isn't going to be mutated unless its a
631 // source.
632 if (isSource(V) || shouldPromote(V)) {
633 for (Use &U : V->uses()) {
634 if (!AddLegalInst(U.getUser()))
635 return false;
636 }
637 }
638 }
639
Sam Parker3828c6f2018-07-23 12:27:47 +0000640 LLVM_DEBUG(dbgs() << "ARM CGP: Visited nodes:\n";
641 for (auto *I : CurrentVisited)
642 I->dump();
643 );
Sam Parker7def86b2018-08-15 07:52:35 +0000644 unsigned ToPromote = 0;
645 for (auto *V : CurrentVisited) {
646 if (Leaves.count(V))
647 continue;
648 if (Roots.count(cast<Instruction>(V)))
649 continue;
650 ++ToPromote;
651 }
652
653 if (ToPromote < 2)
654 return false;
Sam Parker3828c6f2018-07-23 12:27:47 +0000655
656 Promoter->Mutate(OrigTy, CurrentVisited, Leaves, Roots);
657 return true;
658}
659
660bool ARMCodeGenPrepare::doInitialization(Module &M) {
661 Promoter = new IRPromoter(&M);
662 return false;
663}
664
665bool ARMCodeGenPrepare::runOnFunction(Function &F) {
666 if (skipFunction(F) || DisableCGP)
667 return false;
668
669 auto *TPC = &getAnalysis<TargetPassConfig>();
670 if (!TPC)
671 return false;
672
673 const TargetMachine &TM = TPC->getTM<TargetMachine>();
674 ST = &TM.getSubtarget<ARMSubtarget>(F);
675 bool MadeChange = false;
676 LLVM_DEBUG(dbgs() << "ARM CGP: Running on " << F.getName() << "\n");
677
678 // Search up from icmps to try to promote their operands.
679 for (BasicBlock &BB : F) {
680 auto &Insts = BB.getInstList();
681 for (auto &I : Insts) {
682 if (AllVisited.count(&I))
683 continue;
684
685 if (isa<ICmpInst>(I)) {
686 auto &CI = cast<ICmpInst>(I);
687
688 // Skip signed or pointer compares
689 if (CI.isSigned() || !isa<IntegerType>(CI.getOperand(0)->getType()))
690 continue;
691
692 LLVM_DEBUG(dbgs() << "ARM CGP: Searching from: " << CI << "\n");
693 for (auto &Op : CI.operands()) {
Sam Parker8c4b9642018-08-10 13:57:13 +0000694 if (auto *I = dyn_cast<Instruction>(Op))
695 MadeChange |= TryToPromote(I);
Sam Parker3828c6f2018-07-23 12:27:47 +0000696 }
697 }
698 }
699 Promoter->Cleanup();
700 LLVM_DEBUG(if (verifyFunction(F, &dbgs())) {
701 dbgs();
702 report_fatal_error("Broken function after type promotion");
703 });
704 }
705 if (MadeChange)
706 LLVM_DEBUG(dbgs() << "After ARMCodeGenPrepare: " << F << "\n");
707
708 return MadeChange;
709}
710
Matt Morehousea70685f2018-07-23 17:00:45 +0000711bool ARMCodeGenPrepare::doFinalization(Module &M) {
712 delete Promoter;
713 return false;
714}
715
Sam Parker3828c6f2018-07-23 12:27:47 +0000716INITIALIZE_PASS_BEGIN(ARMCodeGenPrepare, DEBUG_TYPE,
717 "ARM IR optimizations", false, false)
718INITIALIZE_PASS_END(ARMCodeGenPrepare, DEBUG_TYPE, "ARM IR optimizations",
719 false, false)
720
721char ARMCodeGenPrepare::ID = 0;
Sam Parker8c4b9642018-08-10 13:57:13 +0000722unsigned ARMCodeGenPrepare::TypeSize = 0;
Sam Parker3828c6f2018-07-23 12:27:47 +0000723
724FunctionPass *llvm::createARMCodeGenPreparePass() {
725 return new ARMCodeGenPrepare();
726}