1239462Sdim//===- HexagonRemoveExtendArgs.cpp - Remove unnecessary argument sign extends //
2234285Sdim//
3234285Sdim//                     The LLVM Compiler Infrastructure
4234285Sdim//
5234285Sdim// This file is distributed under the University of Illinois Open Source
6234285Sdim// License. See LICENSE.TXT for details.
7234285Sdim//
8234285Sdim//===----------------------------------------------------------------------===//
9234285Sdim//
10234285Sdim// Pass that removes sign extends for function parameters. These parameters
11234285Sdim// are already sign extended by the caller per Hexagon's ABI
12234285Sdim//
13234285Sdim//===----------------------------------------------------------------------===//
14234285Sdim
15249423Sdim#include "Hexagon.h"
16234285Sdim#include "HexagonTargetMachine.h"
17249423Sdim#include "llvm/CodeGen/MachineFunctionAnalysis.h"
18249423Sdim#include "llvm/IR/Function.h"
19249423Sdim#include "llvm/IR/Instructions.h"
20234285Sdim#include "llvm/Pass.h"
21234285Sdim#include "llvm/Transforms/Scalar.h"
22234285Sdim
23234285Sdimusing namespace llvm;
24251662Sdim
25251662Sdimnamespace llvm {
26251662Sdim  void initializeHexagonRemoveExtendArgsPass(PassRegistry&);
27251662Sdim}
28251662Sdim
29234285Sdimnamespace {
30234285Sdim  struct HexagonRemoveExtendArgs : public FunctionPass {
31234285Sdim  public:
32234285Sdim    static char ID;
33251662Sdim    HexagonRemoveExtendArgs() : FunctionPass(ID) {
34251662Sdim      initializeHexagonRemoveExtendArgsPass(*PassRegistry::getPassRegistry());
35251662Sdim    }
36234285Sdim    virtual bool runOnFunction(Function &F);
37234285Sdim
38234285Sdim    const char *getPassName() const {
39234285Sdim      return "Remove sign extends";
40234285Sdim    }
41234285Sdim
42234285Sdim    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
43234285Sdim      AU.addRequired<MachineFunctionAnalysis>();
44234285Sdim      AU.addPreserved<MachineFunctionAnalysis>();
45234285Sdim      FunctionPass::getAnalysisUsage(AU);
46234285Sdim    }
47234285Sdim  };
48234285Sdim}
49234285Sdim
50234285Sdimchar HexagonRemoveExtendArgs::ID = 0;
51234285Sdim
52251662SdimINITIALIZE_PASS(HexagonRemoveExtendArgs, "reargs",
53251662Sdim                "Remove Sign and Zero Extends for Args", false, false)
54234285Sdim
55234285Sdimbool HexagonRemoveExtendArgs::runOnFunction(Function &F) {
56234285Sdim  unsigned Idx = 1;
57234285Sdim  for (Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end(); AI != AE;
58234285Sdim       ++AI, ++Idx) {
59249423Sdim    if (F.getAttributes().hasAttribute(Idx, Attribute::SExt)) {
60234285Sdim      Argument* Arg = AI;
61234285Sdim      if (!isa<PointerType>(Arg->getType())) {
62234285Sdim        for (Instruction::use_iterator UI = Arg->use_begin();
63234285Sdim             UI != Arg->use_end();) {
64234285Sdim          if (isa<SExtInst>(*UI)) {
65234285Sdim            Instruction* Use = cast<Instruction>(*UI);
66234285Sdim            SExtInst* SI = new SExtInst(Arg, Use->getType());
67234285Sdim            assert (EVT::getEVT(SI->getType()) ==
68234285Sdim                    (EVT::getEVT(Use->getType())));
69234285Sdim            ++UI;
70234285Sdim            Use->replaceAllUsesWith(SI);
71234285Sdim            Instruction* First = F.getEntryBlock().begin();
72234285Sdim            SI->insertBefore(First);
73234285Sdim            Use->eraseFromParent();
74234285Sdim          } else {
75234285Sdim            ++UI;
76234285Sdim          }
77234285Sdim        }
78234285Sdim      }
79234285Sdim    }
80234285Sdim  }
81234285Sdim  return true;
82234285Sdim}
83234285Sdim
84234285Sdim
85234285Sdim
86251662SdimFunctionPass*
87251662Sdimllvm::createHexagonRemoveExtendArgs(const HexagonTargetMachine &TM) {
88234285Sdim  return new HexagonRemoveExtendArgs();
89234285Sdim}
90