LLVM  8.0.1
HexagonOptimizeSZextends.cpp
Go to the documentation of this file.
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 
16 #include "llvm/IR/Function.h"
17 #include "llvm/IR/Instructions.h"
18 #include "llvm/IR/IntrinsicInst.h"
19 #include "llvm/Pass.h"
20 #include "llvm/Transforms/Scalar.h"
21 
22 #include "Hexagon.h"
23 
24 using namespace llvm;
25 
26 namespace llvm {
29 }
30 
31 namespace {
32  struct HexagonOptimizeSZextends : public FunctionPass {
33  public:
34  static char ID;
35  HexagonOptimizeSZextends() : FunctionPass(ID) {
37  }
38  bool runOnFunction(Function &F) override;
39 
40  StringRef getPassName() const override { return "Remove sign extends"; }
41 
42  void getAnalysisUsage(AnalysisUsage &AU) const override {
45  }
46 
47  bool intrinsicAlreadySextended(Intrinsic::ID IntID);
48  };
49 }
50 
52 
53 INITIALIZE_PASS(HexagonOptimizeSZextends, "reargs",
54  "Remove Sign and Zero Extends for Args", false, false)
55 
56 bool HexagonOptimizeSZextends::intrinsicAlreadySextended(Intrinsic::ID IntID) {
57  switch(IntID) {
59  return true;
60  default:
61  break;
62  }
63  return false;
64 }
65 
67  if (skipFunction(F))
68  return false;
69 
70  unsigned Idx = 1;
71  // Try to optimize sign extends in formal parameters. It's relying on
72  // callee already sign extending the values. I'm not sure if our ABI
73  // requires callee to sign extend though.
74  for (auto &Arg : F.args()) {
76  if (!isa<PointerType>(Arg.getType())) {
77  for (auto UI = Arg.use_begin(); UI != Arg.use_end();) {
78  if (isa<SExtInst>(*UI)) {
79  Instruction* Use = cast<Instruction>(*UI);
80  SExtInst* SI = new SExtInst(&Arg, Use->getType());
81  assert (EVT::getEVT(SI->getType()) ==
82  (EVT::getEVT(Use->getType())));
83  ++UI;
84  Use->replaceAllUsesWith(SI);
85  Instruction* First = &F.getEntryBlock().front();
86  SI->insertBefore(First);
87  Use->eraseFromParent();
88  } else {
89  ++UI;
90  }
91  }
92  }
93  }
94  ++Idx;
95  }
96 
97  // Try to remove redundant sext operations on Hexagon. The hardware
98  // already sign extends many 16 bit intrinsic operations to 32 bits.
99  // For example:
100  // %34 = tail call i32 @llvm.hexagon.A2.addh.l16.sat.ll(i32 %x, i32 %y)
101  // %sext233 = shl i32 %34, 16
102  // %conv52 = ashr exact i32 %sext233, 16
103  for (auto &B : F) {
104  for (auto &I : B) {
105  // Look for arithmetic shift right by 16.
107  if (!(Ashr && Ashr->getOpcode() == Instruction::AShr))
108  continue;
109  Value *AshrOp1 = Ashr->getOperand(1);
110  ConstantInt *C = dyn_cast<ConstantInt>(AshrOp1);
111  // Right shifted by 16.
112  if (!(C && C->getSExtValue() == 16))
113  continue;
114 
115  // The first operand of Ashr comes from logical shift left.
116  Instruction *Shl = dyn_cast<Instruction>(Ashr->getOperand(0));
117  if (!(Shl && Shl->getOpcode() == Instruction::Shl))
118  continue;
119  Value *Intr = Shl->getOperand(0);
120  Value *ShlOp1 = Shl->getOperand(1);
121  C = dyn_cast<ConstantInt>(ShlOp1);
122  // Left shifted by 16.
123  if (!(C && C->getSExtValue() == 16))
124  continue;
125 
126  // The first operand of Shl comes from an intrinsic.
127  if (IntrinsicInst *I = dyn_cast<IntrinsicInst>(Intr)) {
128  if (!intrinsicAlreadySextended(I->getIntrinsicID()))
129  continue;
130  // All is well. Replace all uses of AShr with I.
131  for (auto UI = Ashr->user_begin(), UE = Ashr->user_end();
132  UI != UE; ++UI) {
133  const Use &TheUse = UI.getUse();
134  if (Instruction *J = dyn_cast<Instruction>(TheUse.getUser())) {
135  J->replaceUsesOfWith(Ashr, I);
136  }
137  }
138  }
139  }
140  }
141 
142  return true;
143 }
144 
145 
147  return new HexagonOptimizeSZextends();
148 }
uint64_t CallInst * C
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks &#39;this&#39; from the containing basic block and deletes it.
Definition: Instruction.cpp:68
use_iterator use_end()
Definition: Value.h:347
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
INITIALIZE_PASS(HexagonOptimizeSZextends, "reargs", "Remove Sign and Zero Extends for Args", false, false) bool HexagonOptimizeSZextends
This class represents lattice values for constants.
Definition: AllocatorList.h:24
BinaryOps getOpcode() const
Definition: InstrTypes.h:316
F(f)
This class represents a sign extension of integer types.
bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const
Return true if the attribute exists at the given index.
FunctionPass * createHexagonOptimizeSZextends()
A Use represents the edge between a Value definition and its users.
Definition: Use.h:56
unsigned Intr
User * getUser() const LLVM_READONLY
Returns the User that contains this Use.
Definition: Use.cpp:41
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:92
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Definition: Instruction.h:126
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition: Function.h:224
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:429
Value * getOperand(unsigned i) const
Definition: User.h:170
const BasicBlock & getEntryBlock() const
Definition: Function.h:640
static bool runOnFunction(Function &F, bool PostInlining)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction...
Definition: Instruction.cpp:74
void initializeHexagonOptimizeSZextendsPass(PassRegistry &)
const Instruction & front() const
Definition: BasicBlock.h:281
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
This is the shared class of boolean and integer constants.
Definition: Constants.h:84
amdgpu Simplify well known AMD library false Value Value * Arg
use_iterator use_begin()
Definition: Value.h:339
#define I(x, y, z)
Definition: MD5.cpp:58
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:323
static EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
Definition: ValueTypes.cpp:309
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
user_iterator user_begin()
Definition: Value.h:376
LLVM Value Representation.
Definition: Value.h:73
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:39
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Definition: Constants.h:157
iterator_range< arg_iterator > args()
Definition: Function.h:689
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:44
user_iterator user_end()
Definition: Value.h:384