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