1 //===- HexagonOptimizeSZextends.cpp - Remove unnecessary argument extends -===//
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
7 //===----------------------------------------------------------------------===//
9 // Pass that removes sign extends for function parameters. These parameters
10 // are already sign extended by the caller per Hexagon's ABI
12 //===----------------------------------------------------------------------===//
15 #include "llvm/CodeGen/StackProtector.h"
16 #include "llvm/CodeGen/ValueTypes.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"
27 FunctionPass
*createHexagonOptimizeSZextends();
28 void initializeHexagonOptimizeSZextendsPass(PassRegistry
&);
32 struct HexagonOptimizeSZextends
: public FunctionPass
{
35 HexagonOptimizeSZextends() : FunctionPass(ID
) {
36 initializeHexagonOptimizeSZextendsPass(*PassRegistry::getPassRegistry());
38 bool runOnFunction(Function
&F
) override
;
40 StringRef
getPassName() const override
{ return "Remove sign extends"; }
42 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
43 AU
.addPreserved
<StackProtector
>();
44 FunctionPass::getAnalysisUsage(AU
);
47 bool intrinsicAlreadySextended(Intrinsic::ID IntID
);
51 char HexagonOptimizeSZextends::ID
= 0;
53 INITIALIZE_PASS(HexagonOptimizeSZextends
, "reargs",
54 "Remove Sign and Zero Extends for Args", false, false)
56 bool HexagonOptimizeSZextends::intrinsicAlreadySextended(Intrinsic::ID IntID
) {
58 case llvm::Intrinsic::hexagon_A2_addh_l16_sat_ll
:
66 bool HexagonOptimizeSZextends::runOnFunction(Function
&F
) {
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())));
83 Use
->replaceAllUsesWith(SI
);
84 Instruction
* First
= &F
.getEntryBlock().front();
85 SI
->insertBefore(First
);
86 Use
->eraseFromParent();
94 // Try to remove redundant sext operations on Hexagon. The hardware
95 // already sign extends many 16 bit intrinsic operations to 32 bits.
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
102 // Look for arithmetic shift right by 16.
103 BinaryOperator
*Ashr
= dyn_cast
<BinaryOperator
>(&I
);
104 if (!(Ashr
&& Ashr
->getOpcode() == Instruction::AShr
))
106 Value
*AshrOp1
= Ashr
->getOperand(1);
107 ConstantInt
*C
= dyn_cast
<ConstantInt
>(AshrOp1
);
108 // Right shifted by 16.
109 if (!(C
&& C
->getSExtValue() == 16))
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
))
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))
123 // The first operand of Shl comes from an intrinsic.
124 if (IntrinsicInst
*I
= dyn_cast
<IntrinsicInst
>(Intr
)) {
125 if (!intrinsicAlreadySextended(I
->getIntrinsicID()))
127 // All is well. Replace all uses of AShr with I.
128 for (auto UI
= Ashr
->user_begin(), UE
= Ashr
->user_end();
130 const Use
&TheUse
= UI
.getUse();
131 if (Instruction
*J
= dyn_cast
<Instruction
>(TheUse
.getUser())) {
132 J
->replaceUsesOfWith(Ashr
, I
);
143 FunctionPass
*llvm::createHexagonOptimizeSZextends() {
144 return new HexagonOptimizeSZextends();