LLVM  10.0.0svn
HexagonOptimizeSZextends.cpp
Go to the documentation of this file.
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 
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 
23 using namespace llvm;
24 
25 namespace llvm {
28 }
29 
30 namespace {
31  struct HexagonOptimizeSZextends : public FunctionPass {
32  public:
33  static char ID;
34  HexagonOptimizeSZextends() : FunctionPass(ID) {
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 {
44  }
45 
46  bool intrinsicAlreadySextended(Intrinsic::ID IntID);
47  };
48 }
49 
51 
52 INITIALIZE_PASS(HexagonOptimizeSZextends, "reargs",
53  "Remove Sign and Zero Extends for Args", false, false)
54 
55 bool 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 
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.
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 
146  return new HexagonOptimizeSZextends();
147 }
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:67
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:23
BinaryOps getOpcode() const
Definition: InstrTypes.h:402
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:55
unsigned Intr
User * getUser() const LLVM_READONLY
Returns the User that contains this Use.
Definition: Use.cpp:40
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:96
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:125
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition: Function.h:223
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:169
const BasicBlock & getEntryBlock() const
Definition: Function.h:664
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:73
void initializeHexagonOptimizeSZextendsPass(PassRegistry &)
const Instruction & front() const
Definition: BasicBlock.h:280
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
#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:332
static EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
Definition: ValueTypes.cpp:475
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
user_iterator user_begin()
Definition: Value.h:395
LLVM Value Representation.
Definition: Value.h:73
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:38
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:156
iterator_range< arg_iterator > args()
Definition: Function.h:719
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:43
user_iterator user_end()
Definition: Value.h:403