HexagonOptimizeSZextends.cpp revision 292941
1//===- HexagonOptimizeSZextends.cpp - Remove unnecessary argument extends -===// 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// Pass that removes sign extends for function parameters. These parameters 11// are already sign extended by the caller per Hexagon's ABI 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/CodeGen/MachineFunctionAnalysis.h" 16#include "llvm/CodeGen/StackProtector.h" 17#include "llvm/IR/Function.h" 18#include "llvm/IR/Instructions.h" 19#include "llvm/IR/IntrinsicInst.h" 20#include "llvm/Pass.h" 21#include "llvm/Transforms/Scalar.h" 22 23#include "Hexagon.h" 24 25using namespace llvm; 26 27namespace llvm { 28 FunctionPass *createHexagonOptimizeSZextends(); 29 void initializeHexagonOptimizeSZextendsPass(PassRegistry&); 30} 31 32namespace { 33 struct HexagonOptimizeSZextends : public FunctionPass { 34 public: 35 static char ID; 36 HexagonOptimizeSZextends() : FunctionPass(ID) { 37 initializeHexagonOptimizeSZextendsPass(*PassRegistry::getPassRegistry()); 38 } 39 bool runOnFunction(Function &F) override; 40 41 const char *getPassName() const override { 42 return "Remove sign extends"; 43 } 44 45 void getAnalysisUsage(AnalysisUsage &AU) const override { 46 AU.addRequired<MachineFunctionAnalysis>(); 47 AU.addPreserved<MachineFunctionAnalysis>(); 48 AU.addPreserved<StackProtector>(); 49 FunctionPass::getAnalysisUsage(AU); 50 } 51 52 bool intrinsicAlreadySextended(Intrinsic::ID IntID); 53 }; 54} 55 56char HexagonOptimizeSZextends::ID = 0; 57 58INITIALIZE_PASS(HexagonOptimizeSZextends, "reargs", 59 "Remove Sign and Zero Extends for Args", false, false) 60 61bool HexagonOptimizeSZextends::intrinsicAlreadySextended(Intrinsic::ID IntID) { 62 switch(IntID) { 63 case llvm::Intrinsic::hexagon_A2_addh_l16_sat_ll: 64 return true; 65 default: 66 break; 67 } 68 return false; 69} 70 71bool HexagonOptimizeSZextends::runOnFunction(Function &F) { 72 unsigned Idx = 1; 73 // Try to optimize sign extends in formal parameters. It's relying on 74 // callee already sign extending the values. I'm not sure if our ABI 75 // requires callee to sign extend though. 76 for (auto &Arg : F.args()) { 77 if (F.getAttributes().hasAttribute(Idx, Attribute::SExt)) { 78 if (!isa<PointerType>(Arg.getType())) { 79 for (auto UI = Arg.use_begin(); UI != Arg.use_end();) { 80 if (isa<SExtInst>(*UI)) { 81 Instruction* Use = cast<Instruction>(*UI); 82 SExtInst* SI = new SExtInst(&Arg, Use->getType()); 83 assert (EVT::getEVT(SI->getType()) == 84 (EVT::getEVT(Use->getType()))); 85 ++UI; 86 Use->replaceAllUsesWith(SI); 87 Instruction* First = &F.getEntryBlock().front(); 88 SI->insertBefore(First); 89 Use->eraseFromParent(); 90 } else { 91 ++UI; 92 } 93 } 94 } 95 } 96 ++Idx; 97 } 98 99 // Try to remove redundant sext operations on Hexagon. The hardware 100 // already sign extends many 16 bit intrinsic operations to 32 bits. 101 // For example: 102 // %34 = tail call i32 @llvm.hexagon.A2.addh.l16.sat.ll(i32 %x, i32 %y) 103 // %sext233 = shl i32 %34, 16 104 // %conv52 = ashr exact i32 %sext233, 16 105 for (auto &B : F) { 106 for (auto &I : B) { 107 // Look for arithmetic shift right by 16. 108 BinaryOperator *Ashr = dyn_cast<BinaryOperator>(&I); 109 if (!(Ashr && Ashr->getOpcode() == Instruction::AShr)) 110 continue; 111 Value *AshrOp1 = Ashr->getOperand(1); 112 ConstantInt *C = dyn_cast<ConstantInt>(AshrOp1); 113 // Right shifted by 16. 114 if (!(C && C->getSExtValue() == 16)) 115 continue; 116 117 // The first operand of Ashr comes from logical shift left. 118 Instruction *Shl = dyn_cast<Instruction>(Ashr->getOperand(0)); 119 if (!(Shl && Shl->getOpcode() == Instruction::Shl)) 120 continue; 121 Value *Intr = Shl->getOperand(0); 122 Value *ShlOp1 = Shl->getOperand(1); 123 C = dyn_cast<ConstantInt>(ShlOp1); 124 // Left shifted by 16. 125 if (!(C && C->getSExtValue() == 16)) 126 continue; 127 128 // The first operand of Shl comes from an intrinsic. 129 if (IntrinsicInst *I = dyn_cast<IntrinsicInst>(Intr)) { 130 if (!intrinsicAlreadySextended(I->getIntrinsicID())) 131 continue; 132 // All is well. Replace all uses of AShr with I. 133 for (auto UI = Ashr->user_begin(), UE = Ashr->user_end(); 134 UI != UE; ++UI) { 135 const Use &TheUse = UI.getUse(); 136 if (Instruction *J = dyn_cast<Instruction>(TheUse.getUser())) { 137 J->replaceUsesOfWith(Ashr, I); 138 } 139 } 140 } 141 } 142 } 143 144 return true; 145} 146 147 148FunctionPass *llvm::createHexagonOptimizeSZextends() { 149 return new HexagonOptimizeSZextends(); 150} 151