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