LLVM  4.0.0
AArch64AddressTypePromotion.cpp
Go to the documentation of this file.
1 //===-- AArch64AddressTypePromotion.cpp --- Promote type for addr accesses -==//
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 // This pass tries to promote the computations use to obtained a sign extended
11 // value used into memory accesses.
12 // E.g.
13 // a = add nsw i32 b, 3
14 // d = sext i32 a to i64
15 // e = getelementptr ..., i64 d
16 //
17 // =>
18 // f = sext i32 b to i64
19 // a = add nsw i64 f, 3
20 // e = getelementptr ..., i64 a
21 //
22 // This is legal to do if the computations are marked with either nsw or nuw
23 // markers. Moreover, the current heuristic is simple: it does not create new
24 // sext operations, i.e., it gives up when a sext would have forked (e.g., if a
25 // = add i32 b, c, two sexts are required to promote the computation).
26 //
27 // FIXME: This pass may be useful for other targets too.
28 // ===---------------------------------------------------------------------===//
29 
30 #include "AArch64.h"
31 #include "llvm/ADT/DenseMap.h"
32 #include "llvm/ADT/SmallPtrSet.h"
33 #include "llvm/ADT/SmallVector.h"
34 #include "llvm/IR/Constants.h"
35 #include "llvm/IR/Dominators.h"
36 #include "llvm/IR/Function.h"
37 #include "llvm/IR/Instructions.h"
38 #include "llvm/IR/Module.h"
39 #include "llvm/IR/Operator.h"
40 #include "llvm/Pass.h"
42 #include "llvm/Support/Debug.h"
44 
45 using namespace llvm;
46 
47 #define DEBUG_TYPE "aarch64-type-promotion"
48 
49 static cl::opt<bool>
50 EnableMerge("aarch64-type-promotion-merge", cl::Hidden,
51  cl::desc("Enable merging of redundant sexts when one is dominating"
52  " the other."),
53  cl::init(true));
54 
55 #define AARCH64_TYPE_PROMO_NAME "AArch64 Address Type Promotion"
56 
57 //===----------------------------------------------------------------------===//
58 // AArch64AddressTypePromotion
59 //===----------------------------------------------------------------------===//
60 
61 namespace {
62 class AArch64AddressTypePromotion : public FunctionPass {
63 
64 public:
65  static char ID;
66  AArch64AddressTypePromotion()
67  : FunctionPass(ID), Func(nullptr), ConsideredSExtType(nullptr) {
69  }
70 
71  StringRef getPassName() const override { return AARCH64_TYPE_PROMO_NAME; }
72 
73  /// Iterate over the functions and promote the computation of interesting
74  // sext instructions.
75  bool runOnFunction(Function &F) override;
76 
77 private:
78  /// The current function.
79  Function *Func;
80  /// Filter out all sexts that does not have this type.
81  /// Currently initialized with Int64Ty.
82  Type *ConsideredSExtType;
83 
84  // This transformation requires dominator info.
85  void getAnalysisUsage(AnalysisUsage &AU) const override {
86  AU.setPreservesCFG();
90  }
91 
92  typedef SmallPtrSet<Instruction *, 32> SetOfInstructions;
93  typedef SmallVector<Instruction *, 16> Instructions;
94  typedef DenseMap<Value *, Instructions> ValueToInsts;
95 
96  /// Check if it is profitable to move a sext through this instruction.
97  /// Currently, we consider it is profitable if:
98  /// - Inst is used only once (no need to insert truncate).
99  /// - Inst has only one operand that will require a sext operation (we do
100  /// do not create new sext operation).
101  bool shouldGetThrough(const Instruction *Inst);
102 
103  /// Check if it is possible and legal to move a sext through this
104  /// instruction.
105  /// Current heuristic considers that we can get through:
106  /// - Arithmetic operation marked with the nsw or nuw flag.
107  /// - Other sext operation.
108  /// - Truncate operation if it was just dropping sign extended bits.
109  bool canGetThrough(const Instruction *Inst);
110 
111  /// Move sext operations through safe to sext instructions.
112  bool propagateSignExtension(Instructions &SExtInsts);
113 
114  /// Is this sext should be considered for code motion.
115  /// We look for sext with ConsideredSExtType and uses in at least one
116  // GetElementPtrInst.
117  bool shouldConsiderSExt(const Instruction *SExt) const;
118 
119  /// Collect all interesting sext operations, i.e., the ones with the right
120  /// type and used in memory accesses.
121  /// More precisely, a sext instruction is considered as interesting if it
122  /// is used in a "complex" getelementptr or it exits at least another
123  /// sext instruction that sign extended the same initial value.
124  /// A getelementptr is considered as "complex" if it has more than 2
125  // operands.
126  void analyzeSExtension(Instructions &SExtInsts);
127 
128  /// Merge redundant sign extension operations in common dominator.
129  void mergeSExts(ValueToInsts &ValToSExtendedUses,
130  SetOfInstructions &ToRemove);
131 };
132 } // end anonymous namespace.
133 
135 
136 INITIALIZE_PASS_BEGIN(AArch64AddressTypePromotion, "aarch64-type-promotion",
137  AARCH64_TYPE_PROMO_NAME, false, false)
139 INITIALIZE_PASS_END(AArch64AddressTypePromotion, "aarch64-type-promotion",
141 
143  return new AArch64AddressTypePromotion();
144 }
145 
146 bool AArch64AddressTypePromotion::canGetThrough(const Instruction *Inst) {
147  if (isa<SExtInst>(Inst))
148  return true;
149 
150  const BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Inst);
151  if (BinOp && isa<OverflowingBinaryOperator>(BinOp) &&
152  (BinOp->hasNoUnsignedWrap() || BinOp->hasNoSignedWrap()))
153  return true;
154 
155  // sext(trunc(sext)) --> sext
156  if (isa<TruncInst>(Inst) && isa<SExtInst>(Inst->getOperand(0))) {
157  const Instruction *Opnd = cast<Instruction>(Inst->getOperand(0));
158  // Check that the truncate just drop sign extended bits.
159  if (Inst->getType()->getIntegerBitWidth() >=
160  Opnd->getOperand(0)->getType()->getIntegerBitWidth() &&
161  Inst->getOperand(0)->getType()->getIntegerBitWidth() <=
162  ConsideredSExtType->getIntegerBitWidth())
163  return true;
164  }
165 
166  return false;
167 }
168 
169 bool AArch64AddressTypePromotion::shouldGetThrough(const Instruction *Inst) {
170  // If the type of the sext is the same as the considered one, this sext
171  // will become useless.
172  // Otherwise, we will have to do something to preserve the original value,
173  // unless it is used once.
174  if (isa<SExtInst>(Inst) &&
175  (Inst->getType() == ConsideredSExtType || Inst->hasOneUse()))
176  return true;
177 
178  // If the Inst is used more that once, we may need to insert truncate
179  // operations and we don't do that at the moment.
180  if (!Inst->hasOneUse())
181  return false;
182 
183  // This truncate is used only once, thus if we can get thourgh, it will become
184  // useless.
185  if (isa<TruncInst>(Inst))
186  return true;
187 
188  // If both operands are not constant, a new sext will be created here.
189  // Current heuristic is: each step should be profitable.
190  // Therefore we don't allow to increase the number of sext even if it may
191  // be profitable later on.
192  if (isa<BinaryOperator>(Inst) && isa<ConstantInt>(Inst->getOperand(1)))
193  return true;
194 
195  return false;
196 }
197 
198 static bool shouldSExtOperand(const Instruction *Inst, int OpIdx) {
199  return !(isa<SelectInst>(Inst) && OpIdx == 0);
200 }
201 
202 bool
203 AArch64AddressTypePromotion::shouldConsiderSExt(const Instruction *SExt) const {
204  if (SExt->getType() != ConsideredSExtType)
205  return false;
206 
207  for (const User *U : SExt->users()) {
208  if (isa<GetElementPtrInst>(U))
209  return true;
210  }
211 
212  return false;
213 }
214 
215 // Input:
216 // - SExtInsts contains all the sext instructions that are used directly in
217 // GetElementPtrInst, i.e., access to memory.
218 // Algorithm:
219 // - For each sext operation in SExtInsts:
220 // Let var be the operand of sext.
221 // while it is profitable (see shouldGetThrough), legal, and safe
222 // (see canGetThrough) to move sext through var's definition:
223 // * promote the type of var's definition.
224 // * fold var into sext uses.
225 // * move sext above var's definition.
226 // * update sext operand to use the operand of var that should be sign
227 // extended (by construction there is only one).
228 //
229 // E.g.,
230 // a = ... i32 c, 3
231 // b = sext i32 a to i64 <- is it legal/safe/profitable to get through 'a'
232 // ...
233 // = b
234 // => Yes, update the code
235 // b = sext i32 c to i64
236 // a = ... i64 b, 3
237 // ...
238 // = a
239 // Iterate on 'c'.
240 bool
241 AArch64AddressTypePromotion::propagateSignExtension(Instructions &SExtInsts) {
242  DEBUG(dbgs() << "*** Propagate Sign Extension ***\n");
243 
244  bool LocalChange = false;
245  SetOfInstructions ToRemove;
246  ValueToInsts ValToSExtendedUses;
247  while (!SExtInsts.empty()) {
248  // Get through simple chain.
249  Instruction *SExt = SExtInsts.pop_back_val();
250 
251  DEBUG(dbgs() << "Consider:\n" << *SExt << '\n');
252 
253  // If this SExt has already been merged continue.
254  if (SExt->use_empty() && ToRemove.count(SExt)) {
255  DEBUG(dbgs() << "No uses => marked as delete\n");
256  continue;
257  }
258 
259  // Now try to get through the chain of definitions.
260  while (auto *Inst = dyn_cast<Instruction>(SExt->getOperand(0))) {
261  DEBUG(dbgs() << "Try to get through:\n" << *Inst << '\n');
262  if (!canGetThrough(Inst) || !shouldGetThrough(Inst)) {
263  // We cannot get through something that is not an Instruction
264  // or not safe to SExt.
265  DEBUG(dbgs() << "Cannot get through\n");
266  break;
267  }
268 
269  LocalChange = true;
270  // If this is a sign extend, it becomes useless.
271  if (isa<SExtInst>(Inst) || isa<TruncInst>(Inst)) {
272  DEBUG(dbgs() << "SExt or trunc, mark it as to remove\n");
273  // We cannot use replaceAllUsesWith here because we may trigger some
274  // assertion on the type as all involved sext operation may have not
275  // been moved yet.
276  while (!Inst->use_empty()) {
277  Use &U = *Inst->use_begin();
279  assert(User && "User of sext is not an Instruction!");
280  User->setOperand(U.getOperandNo(), SExt);
281  }
282  ToRemove.insert(Inst);
283  SExt->setOperand(0, Inst->getOperand(0));
284  SExt->moveBefore(Inst);
285  continue;
286  }
287 
288  // Get through the Instruction:
289  // 1. Update its type.
290  // 2. Replace the uses of SExt by Inst.
291  // 3. Sign extend each operand that needs to be sign extended.
292 
293  // Step #1.
294  Inst->mutateType(SExt->getType());
295  // Step #2.
296  SExt->replaceAllUsesWith(Inst);
297  // Step #3.
298  Instruction *SExtForOpnd = SExt;
299 
300  DEBUG(dbgs() << "Propagate SExt to operands\n");
301  for (int OpIdx = 0, EndOpIdx = Inst->getNumOperands(); OpIdx != EndOpIdx;
302  ++OpIdx) {
303  DEBUG(dbgs() << "Operand:\n" << *(Inst->getOperand(OpIdx)) << '\n');
304  if (Inst->getOperand(OpIdx)->getType() == SExt->getType() ||
305  !shouldSExtOperand(Inst, OpIdx)) {
306  DEBUG(dbgs() << "No need to propagate\n");
307  continue;
308  }
309  // Check if we can statically sign extend the operand.
310  Value *Opnd = Inst->getOperand(OpIdx);
311  if (const ConstantInt *Cst = dyn_cast<ConstantInt>(Opnd)) {
312  DEBUG(dbgs() << "Statically sign extend\n");
313  Inst->setOperand(OpIdx, ConstantInt::getSigned(SExt->getType(),
314  Cst->getSExtValue()));
315  continue;
316  }
317  // UndefValue are typed, so we have to statically sign extend them.
318  if (isa<UndefValue>(Opnd)) {
319  DEBUG(dbgs() << "Statically sign extend\n");
320  Inst->setOperand(OpIdx, UndefValue::get(SExt->getType()));
321  continue;
322  }
323 
324  // Otherwise we have to explicity sign extend it.
325  assert(SExtForOpnd &&
326  "Only one operand should have been sign extended");
327 
328  SExtForOpnd->setOperand(0, Opnd);
329 
330  DEBUG(dbgs() << "Move before:\n" << *Inst << "\nSign extend\n");
331  // Move the sign extension before the insertion point.
332  SExtForOpnd->moveBefore(Inst);
333  Inst->setOperand(OpIdx, SExtForOpnd);
334  // If more sext are required, new instructions will have to be created.
335  SExtForOpnd = nullptr;
336  }
337  if (SExtForOpnd == SExt) {
338  DEBUG(dbgs() << "Sign extension is useless now\n");
339  ToRemove.insert(SExt);
340  break;
341  }
342  }
343 
344  // If the use is already of the right type, connect its uses to its argument
345  // and delete it.
346  // This can happen for an Instruction all uses of which are sign extended.
347  if (!ToRemove.count(SExt) &&
348  SExt->getType() == SExt->getOperand(0)->getType()) {
349  DEBUG(dbgs() << "Sign extension is useless, attach its use to "
350  "its argument\n");
351  SExt->replaceAllUsesWith(SExt->getOperand(0));
352  ToRemove.insert(SExt);
353  } else
354  ValToSExtendedUses[SExt->getOperand(0)].push_back(SExt);
355  }
356 
357  if (EnableMerge)
358  mergeSExts(ValToSExtendedUses, ToRemove);
359 
360  // Remove all instructions marked as ToRemove.
361  for (Instruction *I: ToRemove)
362  I->eraseFromParent();
363  return LocalChange;
364 }
365 
366 void AArch64AddressTypePromotion::mergeSExts(ValueToInsts &ValToSExtendedUses,
367  SetOfInstructions &ToRemove) {
368  DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
369 
370  for (auto &Entry : ValToSExtendedUses) {
371  Instructions &Insts = Entry.second;
372  Instructions CurPts;
373  for (Instruction *Inst : Insts) {
374  if (ToRemove.count(Inst))
375  continue;
376  bool inserted = false;
377  for (auto &Pt : CurPts) {
378  if (DT.dominates(Inst, Pt)) {
379  DEBUG(dbgs() << "Replace all uses of:\n" << *Pt << "\nwith:\n"
380  << *Inst << '\n');
381  Pt->replaceAllUsesWith(Inst);
382  ToRemove.insert(Pt);
383  Pt = Inst;
384  inserted = true;
385  break;
386  }
387  if (!DT.dominates(Pt, Inst))
388  // Give up if we need to merge in a common dominator as the
389  // expermients show it is not profitable.
390  continue;
391 
392  DEBUG(dbgs() << "Replace all uses of:\n" << *Inst << "\nwith:\n"
393  << *Pt << '\n');
394  Inst->replaceAllUsesWith(Pt);
395  ToRemove.insert(Inst);
396  inserted = true;
397  break;
398  }
399  if (!inserted)
400  CurPts.push_back(Inst);
401  }
402  }
403 }
404 
405 void AArch64AddressTypePromotion::analyzeSExtension(Instructions &SExtInsts) {
406  DEBUG(dbgs() << "*** Analyze Sign Extensions ***\n");
407 
409 
410  for (auto &BB : *Func) {
411  for (auto &II : BB) {
412  Instruction *SExt = &II;
413 
414  // Collect all sext operation per type.
415  if (!isa<SExtInst>(SExt) || !shouldConsiderSExt(SExt))
416  continue;
417 
418  DEBUG(dbgs() << "Found:\n" << (*SExt) << '\n');
419 
420  // Cases where we actually perform the optimization:
421  // 1. SExt is used in a getelementptr with more than 2 operand =>
422  // likely we can merge some computation if they are done on 64 bits.
423  // 2. The beginning of the SExt chain is SExt several time. =>
424  // code sharing is possible.
425 
426  bool insert = false;
427  // #1.
428  for (const User *U : SExt->users()) {
429  const Instruction *Inst = dyn_cast<GetElementPtrInst>(U);
430  if (Inst && Inst->getNumOperands() > 2) {
431  DEBUG(dbgs() << "Interesting use in GetElementPtrInst\n" << *Inst
432  << '\n');
433  insert = true;
434  break;
435  }
436  }
437 
438  // #2.
439  // Check the head of the chain.
440  Instruction *Inst = SExt;
441  Value *Last;
442  do {
443  int OpdIdx = 0;
444  const BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Inst);
445  if (BinOp && isa<ConstantInt>(BinOp->getOperand(0)))
446  OpdIdx = 1;
447  Last = Inst->getOperand(OpdIdx);
448  Inst = dyn_cast<Instruction>(Last);
449  } while (Inst && canGetThrough(Inst) && shouldGetThrough(Inst));
450 
451  DEBUG(dbgs() << "Head of the chain:\n" << *Last << '\n');
453  SeenChains.find(Last);
454  if (insert || AlreadySeen != SeenChains.end()) {
455  DEBUG(dbgs() << "Insert\n");
456  SExtInsts.push_back(SExt);
457  if (AlreadySeen != SeenChains.end() && AlreadySeen->second != nullptr) {
458  DEBUG(dbgs() << "Insert chain member\n");
459  SExtInsts.push_back(AlreadySeen->second);
460  SeenChains[Last] = nullptr;
461  }
462  } else {
463  DEBUG(dbgs() << "Record its chain membership\n");
464  SeenChains[Last] = SExt;
465  }
466  }
467  }
468 }
469 
470 bool AArch64AddressTypePromotion::runOnFunction(Function &F) {
471  if (skipFunction(F))
472  return false;
473 
474  if (F.isDeclaration())
475  return false;
476  Func = &F;
477  ConsideredSExtType = Type::getInt64Ty(Func->getContext());
478 
479  DEBUG(dbgs() << "*** " << getPassName() << ": " << Func->getName() << '\n');
480 
481  Instructions SExtInsts;
482  analyzeSExtension(SExtInsts);
483  return propagateSignExtension(SExtInsts);
484 }
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static bool shouldSExtOperand(const Instruction *Inst, int OpIdx)
unsigned getNumOperands() const
Definition: User.h:167
aarch64 type promotion
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:84
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:170
FunctionPass * createAArch64AddressTypePromotionPass()
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:53
A Use represents the edge between a Value definition and its users.
Definition: Use.h:56
#define F(x, y, z)
Definition: MD5.cpp:51
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:401
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Definition: Dominators.h:96
static cl::opt< bool > EnableMerge("aarch64-type-promotion-merge", cl::Hidden, cl::desc("Enable merging of redundant sexts when one is dominating"" the other."), cl::init(true))
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
Definition: Instructions.h:830
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:395
#define AARCH64_TYPE_PROMO_NAME
unsigned getOperandNo() const
Return the operand # of this use in its User.
Definition: Use.cpp:48
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
This file contains the declarations for the subclasses of Constant, which represent the different fla...
bool hasNoSignedWrap() const
Determine whether the no signed wrap flag is set.
Represent the analysis usage information of a pass.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
User * getUser() const
Returns the User that contains this Use.
Definition: Use.cpp:41
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
Value * getOperand(unsigned i) const
Definition: User.h:145
aarch64 type false
unsigned getIntegerBitWidth() const
Definition: DerivedTypes.h:96
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1337
bool dominates(const Instruction *Def, const Use &U) const
Return true if Def dominates a use in User.
Definition: Dominators.cpp:218
void initializeAArch64AddressTypePromotionPass(PassRegistry &)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
Definition: SmallPtrSet.h:425
This is the shared class of boolean and integer constants.
Definition: Constants.h:88
bool hasNoUnsignedWrap() const
Determine whether the no unsigned wrap flag is set.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:843
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:230
static ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
Definition: Constants.cpp:572
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:276
void setOperand(unsigned i, Value *Val)
Definition: User.h:150
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
iterator_range< user_iterator > users()
Definition: Value.h:370
use_iterator use_begin()
Definition: Value.h:310
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:188
INITIALIZE_PASS_BEGIN(AArch64AddressTypePromotion,"aarch64-type-promotion", AARCH64_TYPE_PROMO_NAME, false, false) INITIALIZE_PASS_END(AArch64AddressTypePromotion
#define I(x, y, z)
Definition: MD5.cpp:54
bool hasOneUse() const
Return true if there is exactly one user of this value.
Definition: Value.h:383
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:287
void mutateType(Type *Ty)
Mutate the type of this Value to be of the specified type.
Definition: Value.h:558
bool use_empty() const
Definition: Value.h:299
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:71
void moveBefore(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
Definition: Instruction.cpp:95
#define DEBUG(X)
Definition: Debug.h:100
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:217