1 //===-- AArch64AddressTypePromotion.cpp --- Promote type for addr accesses -==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This pass tries to promote the computations use to obtained a sign extended
11 // value used into memory accesses.
13 // a = add nsw i32 b, 3
14 // d = sext i32 a to i64
15 // e = getelementptr ..., i64 d
18 // f = sext i32 b to i64
19 // a = add nsw i64 f, 3
20 // e = getelementptr ..., i64 a
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).
27 // FIXME: This pass may be useful for other targets too.
28 // ===---------------------------------------------------------------------===//
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"
41 #include "llvm/Support/CommandLine.h"
42 #include "llvm/Support/Debug.h"
43 #include "llvm/Support/raw_ostream.h"
47 #define DEBUG_TYPE "aarch64-type-promotion"
50 EnableMerge("aarch64-type-promotion-merge", cl::Hidden,
51 cl::desc("Enable merging of redundant sexts when one is dominating"
55 #define AARCH64_TYPE_PROMO_NAME "AArch64 Address Type Promotion"
57 //===----------------------------------------------------------------------===//
58 // AArch64AddressTypePromotion
59 //===----------------------------------------------------------------------===//
62 class AArch64AddressTypePromotion : public FunctionPass {
66 AArch64AddressTypePromotion()
67 : FunctionPass(ID), Func(nullptr), ConsideredSExtType(nullptr) {
68 initializeAArch64AddressTypePromotionPass(*PassRegistry::getPassRegistry());
71 StringRef getPassName() const override { return AARCH64_TYPE_PROMO_NAME; }
73 /// Iterate over the functions and promote the computation of interesting
75 bool runOnFunction(Function &F) override;
78 /// The current function.
80 /// Filter out all sexts that does not have this type.
81 /// Currently initialized with Int64Ty.
82 Type *ConsideredSExtType;
84 // This transformation requires dominator info.
85 void getAnalysisUsage(AnalysisUsage &AU) const override {
87 AU.addRequired<DominatorTreeWrapperPass>();
88 AU.addPreserved<DominatorTreeWrapperPass>();
89 FunctionPass::getAnalysisUsage(AU);
92 typedef SmallPtrSet<Instruction *, 32> SetOfInstructions;
93 typedef SmallVector<Instruction *, 16> Instructions;
94 typedef DenseMap<Value *, Instructions> ValueToInsts;
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);
103 /// Check if it is possible and legal to move a sext through this
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);
111 /// Move sext operations through safe to sext instructions.
112 bool propagateSignExtension(Instructions &SExtInsts);
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;
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
126 void analyzeSExtension(Instructions &SExtInsts);
128 /// Merge redundant sign extension operations in common dominator.
129 void mergeSExts(ValueToInsts &ValToSExtendedUses,
130 SetOfInstructions &ToRemove);
132 } // end anonymous namespace.
134 char AArch64AddressTypePromotion::ID = 0;
136 INITIALIZE_PASS_BEGIN(AArch64AddressTypePromotion, "aarch64-type-promotion",
137 AARCH64_TYPE_PROMO_NAME, false, false)
138 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
139 INITIALIZE_PASS_END(AArch64AddressTypePromotion, "aarch64-type-promotion",
140 AARCH64_TYPE_PROMO_NAME, false, false)
142 FunctionPass *llvm::createAArch64AddressTypePromotionPass() {
143 return new AArch64AddressTypePromotion();
146 bool AArch64AddressTypePromotion::canGetThrough(const Instruction *Inst) {
147 if (isa<SExtInst>(Inst))
150 const BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Inst);
151 if (BinOp && isa<OverflowingBinaryOperator>(BinOp) &&
152 (BinOp->hasNoUnsignedWrap() || BinOp->hasNoSignedWrap()))
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())
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()))
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())
183 // This truncate is used only once, thus if we can get thourgh, it will become
185 if (isa<TruncInst>(Inst))
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)))
198 static bool shouldSExtOperand(const Instruction *Inst, int OpIdx) {
199 return !(isa<SelectInst>(Inst) && OpIdx == 0);
203 AArch64AddressTypePromotion::shouldConsiderSExt(const Instruction *SExt) const {
204 if (SExt->getType() != ConsideredSExtType)
207 for (const User *U : SExt->users()) {
208 if (isa<GetElementPtrInst>(U))
216 // - SExtInsts contains all the sext instructions that are used directly in
217 // GetElementPtrInst, i.e., access to memory.
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).
231 // b = sext i32 a to i64 <- is it legal/safe/profitable to get through 'a'
234 // => Yes, update the code
235 // b = sext i32 c to i64
241 AArch64AddressTypePromotion::propagateSignExtension(Instructions &SExtInsts) {
242 DEBUG(dbgs() << "*** Propagate Sign Extension ***\n");
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();
251 DEBUG(dbgs() << "Consider:\n" << *SExt << '\n');
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");
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");
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
276 while (!Inst->use_empty()) {
277 Use &U = *Inst->use_begin();
278 Instruction *User = dyn_cast<Instruction>(U.getUser());
279 assert(User && "User of sext is not an Instruction!");
280 User->setOperand(U.getOperandNo(), SExt);
282 ToRemove.insert(Inst);
283 SExt->setOperand(0, Inst->getOperand(0));
284 SExt->moveBefore(Inst);
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.
294 Inst->mutateType(SExt->getType());
296 SExt->replaceAllUsesWith(Inst);
298 Instruction *SExtForOpnd = SExt;
300 DEBUG(dbgs() << "Propagate SExt to operands\n");
301 for (int OpIdx = 0, EndOpIdx = Inst->getNumOperands(); OpIdx != EndOpIdx;
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");
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()));
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()));
324 // Otherwise we have to explicity sign extend it.
325 assert(SExtForOpnd &&
326 "Only one operand should have been sign extended");
328 SExtForOpnd->setOperand(0, Opnd);
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;
337 if (SExtForOpnd == SExt) {
338 DEBUG(dbgs() << "Sign extension is useless now\n");
339 ToRemove.insert(SExt);
344 // If the use is already of the right type, connect its uses to its argument
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 "
351 SExt->replaceAllUsesWith(SExt->getOperand(0));
352 ToRemove.insert(SExt);
354 ValToSExtendedUses[SExt->getOperand(0)].push_back(SExt);
358 mergeSExts(ValToSExtendedUses, ToRemove);
360 // Remove all instructions marked as ToRemove.
361 for (Instruction *I: ToRemove)
362 I->eraseFromParent();
366 void AArch64AddressTypePromotion::mergeSExts(ValueToInsts &ValToSExtendedUses,
367 SetOfInstructions &ToRemove) {
368 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
370 for (auto &Entry : ValToSExtendedUses) {
371 Instructions &Insts = Entry.second;
373 for (Instruction *Inst : Insts) {
374 if (ToRemove.count(Inst))
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"
381 Pt->replaceAllUsesWith(Inst);
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.
392 DEBUG(dbgs() << "Replace all uses of:\n" << *Inst << "\nwith:\n"
394 Inst->replaceAllUsesWith(Pt);
395 ToRemove.insert(Inst);
400 CurPts.push_back(Inst);
405 void AArch64AddressTypePromotion::analyzeSExtension(Instructions &SExtInsts) {
406 DEBUG(dbgs() << "*** Analyze Sign Extensions ***\n");
408 DenseMap<Value *, Instruction *> SeenChains;
410 for (auto &BB : *Func) {
411 for (auto &II : BB) {
412 Instruction *SExt = &II;
414 // Collect all sext operation per type.
415 if (!isa<SExtInst>(SExt) || !shouldConsiderSExt(SExt))
418 DEBUG(dbgs() << "Found:\n" << (*SExt) << '\n');
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.
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
439 // Check the head of the chain.
440 Instruction *Inst = SExt;
444 const BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Inst);
445 if (BinOp && isa<ConstantInt>(BinOp->getOperand(0)))
447 Last = Inst->getOperand(OpdIdx);
448 Inst = dyn_cast<Instruction>(Last);
449 } while (Inst && canGetThrough(Inst) && shouldGetThrough(Inst));
451 DEBUG(dbgs() << "Head of the chain:\n" << *Last << '\n');
452 DenseMap<Value *, Instruction *>::iterator AlreadySeen =
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;
463 DEBUG(dbgs() << "Record its chain membership\n");
464 SeenChains[Last] = SExt;
470 bool AArch64AddressTypePromotion::runOnFunction(Function &F) {
474 if (F.isDeclaration())
477 ConsideredSExtType = Type::getInt64Ty(Func->getContext());
479 DEBUG(dbgs() << "*** " << getPassName() << ": " << Func->getName() << '\n');
481 Instructions SExtInsts;
482 analyzeSExtension(SExtInsts);
483 return propagateSignExtension(SExtInsts);