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 (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())));
84 Use
->replaceAllUsesWith(SI
);
85 Instruction
* First
= &F
.getEntryBlock().front();
86 SI
->insertBefore(First
);
87 Use
->eraseFromParent();
97 // Try to remove redundant sext operations on Hexagon. The hardware
98 // already sign extends many 16 bit intrinsic operations to 32 bits.
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
105 // Look for arithmetic shift right by 16.
106 BinaryOperator
*Ashr
= dyn_cast
<BinaryOperator
>(&I
);
107 if (!(Ashr
&& Ashr
->getOpcode() == Instruction::AShr
))
109 Value
*AshrOp1
= Ashr
->getOperand(1);
110 ConstantInt
*C
= dyn_cast
<ConstantInt
>(AshrOp1
);
111 // Right shifted by 16.
112 if (!(C
&& C
->getSExtValue() == 16))
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
))
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))
126 // The first operand of Shl comes from an intrinsic.
127 if (IntrinsicInst
*I
= dyn_cast
<IntrinsicInst
>(Intr
)) {
128 if (!intrinsicAlreadySextended(I
->getIntrinsicID()))
130 // All is well. Replace all uses of AShr with I.
131 for (auto UI
= Ashr
->user_begin(), UE
= Ashr
->user_end();
133 const Use
&TheUse
= UI
.getUse();
134 if (Instruction
*J
= dyn_cast
<Instruction
>(TheUse
.getUser())) {
135 J
->replaceUsesOfWith(Ashr
, I
);
146 FunctionPass
*llvm::createHexagonOptimizeSZextends() {
147 return new HexagonOptimizeSZextends();