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 //===----------------------------------------------------------------------===//
14 #include "llvm/CodeGen/StackProtector.h"
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"
26 FunctionPass
*createHexagonOptimizeSZextends();
27 void initializeHexagonOptimizeSZextendsPass(PassRegistry
&);
31 struct HexagonOptimizeSZextends
: public FunctionPass
{
34 HexagonOptimizeSZextends() : FunctionPass(ID
) {
35 initializeHexagonOptimizeSZextendsPass(*PassRegistry::getPassRegistry());
37 bool runOnFunction(Function
&F
) override
;
39 StringRef
getPassName() const override
{ return "Remove sign extends"; }
41 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
42 AU
.addPreserved
<StackProtector
>();
43 FunctionPass::getAnalysisUsage(AU
);
46 bool intrinsicAlreadySextended(Intrinsic::ID IntID
);
50 char HexagonOptimizeSZextends::ID
= 0;
52 INITIALIZE_PASS(HexagonOptimizeSZextends
, "reargs",
53 "Remove Sign and Zero Extends for Args", false, false)
55 bool HexagonOptimizeSZextends::intrinsicAlreadySextended(Intrinsic::ID IntID
) {
57 case llvm::Intrinsic::hexagon_A2_addh_l16_sat_ll
:
65 bool HexagonOptimizeSZextends::runOnFunction(Function
&F
) {
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())));
83 Use
->replaceAllUsesWith(SI
);
84 Instruction
* First
= &F
.getEntryBlock().front();
85 SI
->insertBefore(First
);
86 Use
->eraseFromParent();
96 // Try to remove redundant sext operations on Hexagon. The hardware
97 // already sign extends many 16 bit intrinsic operations to 32 bits.
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
104 // Look for arithmetic shift right by 16.
105 BinaryOperator
*Ashr
= dyn_cast
<BinaryOperator
>(&I
);
106 if (!(Ashr
&& Ashr
->getOpcode() == Instruction::AShr
))
108 Value
*AshrOp1
= Ashr
->getOperand(1);
109 ConstantInt
*C
= dyn_cast
<ConstantInt
>(AshrOp1
);
110 // Right shifted by 16.
111 if (!(C
&& C
->getSExtValue() == 16))
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
))
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))
125 // The first operand of Shl comes from an intrinsic.
126 if (IntrinsicInst
*I
= dyn_cast
<IntrinsicInst
>(Intr
)) {
127 if (!intrinsicAlreadySextended(I
->getIntrinsicID()))
129 // All is well. Replace all uses of AShr with I.
130 for (auto UI
= Ashr
->user_begin(), UE
= Ashr
->user_end();
132 const Use
&TheUse
= UI
.getUse();
133 if (Instruction
*J
= dyn_cast
<Instruction
>(TheUse
.getUser())) {
134 J
->replaceUsesOfWith(Ashr
, I
);
145 FunctionPass
*llvm::createHexagonOptimizeSZextends() {
146 return new HexagonOptimizeSZextends();