LLVM  16.0.0git
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 
14 #include "Hexagon.h"
17 #include "llvm/IR/Function.h"
18 #include "llvm/IR/Instructions.h"
19 #include "llvm/IR/IntrinsicInst.h"
20 #include "llvm/IR/IntrinsicsHexagon.h"
21 #include "llvm/Pass.h"
22 #include "llvm/Transforms/Scalar.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) {
58  case llvm::Intrinsic::hexagon_A2_addh_l16_sat_ll:
59  return true;
60  default:
61  break;
62  }
63  return false;
64 }
65 
67  if (skipFunction(F))
68  return false;
69 
70  unsigned Idx = 0;
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()) {
75  if (F.getAttributes().hasParamAttr(Idx, Attribute::SExt)) {
76  if (!isa<PointerType>(Arg.getType())) {
77  for (Use &U : llvm::make_early_inc_range(Arg.uses())) {
78  if (isa<SExtInst>(U)) {
79  Instruction* Use = cast<Instruction>(U);
80  SExtInst* SI = new SExtInst(&Arg, Use->getType());
81  assert (EVT::getEVT(SI->getType()) ==
82  (EVT::getEVT(Use->getType())));
84  Instruction* First = &F.getEntryBlock().front();
85  SI->insertBefore(First);
86  Use->eraseFromParent();
87  }
88  }
89  }
90  }
91  ++Idx;
92  }
93 
94  // Try to remove redundant sext operations on Hexagon. The hardware
95  // already sign extends many 16 bit intrinsic operations to 32 bits.
96  // For example:
97  // %34 = tail call i32 @llvm.hexagon.A2.addh.l16.sat.ll(i32 %x, i32 %y)
98  // %sext233 = shl i32 %34, 16
99  // %conv52 = ashr exact i32 %sext233, 16
100  for (auto &B : F) {
101  for (auto &I : B) {
102  // Look for arithmetic shift right by 16.
103  BinaryOperator *Ashr = dyn_cast<BinaryOperator>(&I);
104  if (!(Ashr && Ashr->getOpcode() == Instruction::AShr))
105  continue;
106  Value *AshrOp1 = Ashr->getOperand(1);
107  ConstantInt *C = dyn_cast<ConstantInt>(AshrOp1);
108  // Right shifted by 16.
109  if (!(C && C->getSExtValue() == 16))
110  continue;
111 
112  // The first operand of Ashr comes from logical shift left.
113  Instruction *Shl = dyn_cast<Instruction>(Ashr->getOperand(0));
114  if (!(Shl && Shl->getOpcode() == Instruction::Shl))
115  continue;
116  Value *Intr = Shl->getOperand(0);
117  Value *ShlOp1 = Shl->getOperand(1);
118  C = dyn_cast<ConstantInt>(ShlOp1);
119  // Left shifted by 16.
120  if (!(C && C->getSExtValue() == 16))
121  continue;
122 
123  // The first operand of Shl comes from an intrinsic.
124  if (IntrinsicInst *I = dyn_cast<IntrinsicInst>(Intr)) {
125  if (!intrinsicAlreadySextended(I->getIntrinsicID()))
126  continue;
127  // All is well. Replace all uses of AShr with I.
128  for (auto UI = Ashr->user_begin(), UE = Ashr->user_end();
129  UI != UE; ++UI) {
130  const Use &TheUse = UI.getUse();
131  if (Instruction *J = dyn_cast<Instruction>(TheUse.getUser())) {
132  J->replaceUsesOfWith(Ashr, I);
133  }
134  }
135  }
136  }
137  }
138 
139  return true;
140 }
141 
142 
144  return new HexagonOptimizeSZextends();
145 }
ValueTypes.h
StackProtector.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
IntrinsicInst.h
Scalar.h
llvm::Function
Definition: Function.h:60
Pass.h
llvm::Value::user_begin
user_iterator user_begin()
Definition: Value.h:397
F
#define F(x, y, z)
Definition: MD5.cpp:55
Arg
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Definition: AMDGPULibCalls.cpp:187
llvm::ConstantInt
This is the shared class of boolean and integer constants.
Definition: Constants.h:79
llvm::Instruction::getOpcode
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Definition: Instruction.h:164
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:24
Intr
unsigned Intr
Definition: AMDGPUBaseInfo.cpp:2383
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::StackProtector
Definition: StackProtector.h:36
llvm::initializeHexagonOptimizeSZextendsPass
void initializeHexagonOptimizeSZextendsPass(PassRegistry &)
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
First
into llvm powi allowing the code generator to produce balanced multiplication trees First
Definition: README.txt:54
llvm::BinaryOperator::getOpcode
BinaryOps getOpcode() const
Definition: InstrTypes.h:392
llvm::Instruction
Definition: Instruction.h:42
llvm::PassRegistry
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:38
llvm::Use::getUser
User * getUser() const
Returns the User that contains this Use.
Definition: Use.h:72
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
Hexagon.h
llvm::Value::user_end
user_iterator user_end()
Definition: Value.h:405
llvm::createHexagonOptimizeSZextends
FunctionPass * createHexagonOptimizeSZextends()
Definition: HexagonOptimizeSZextends.cpp:143
INITIALIZE_PASS
INITIALIZE_PASS(HexagonOptimizeSZextends, "reargs", "Remove Sign and Zero Extends for Args", false, false) bool HexagonOptimizeSZextends
Definition: HexagonOptimizeSZextends.cpp:53
llvm::EVT::getEVT
static EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
Definition: ValueTypes.cpp:577
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::make_early_inc_range
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:596
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SI
StandardInstrumentations SI(Debug, VerifyEach)
llvm::BinaryOperator
Definition: InstrTypes.h:188
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::Value::getType
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
llvm::AnalysisUsage::addPreserved
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Definition: PassAnalysisSupport.h:98
llvm::Value::replaceAllUsesWith
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:532
llvm::SExtInst
This class represents a sign extension of integer types.
Definition: Instructions.h:4889
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
Function.h
llvm::IntrinsicInst
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:46
Instructions.h
llvm::Pass::getAnalysisUsage
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:97
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
llvm::User::getOperand
Value * getOperand(unsigned i) const
Definition: User.h:169
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::Use
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38