1 //===----- RISCVCodeGenPrepare.cpp ----------------------------------------===//
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 // This is a RISC-V specific version of CodeGenPrepare.
10 // It munges the code in the input function to better prepare it for
11 // SelectionDAG-based code generation. This works around limitations in it's
12 // basic-block-at-a-time approach.
14 //===----------------------------------------------------------------------===//
17 #include "RISCVTargetMachine.h"
18 #include "llvm/ADT/Statistic.h"
19 #include "llvm/Analysis/ValueTracking.h"
20 #include "llvm/CodeGen/TargetPassConfig.h"
21 #include "llvm/IR/InstVisitor.h"
22 #include "llvm/IR/PatternMatch.h"
23 #include "llvm/InitializePasses.h"
24 #include "llvm/Pass.h"
28 #define DEBUG_TYPE "riscv-codegenprepare"
29 #define PASS_NAME "RISC-V CodeGenPrepare"
31 STATISTIC(NumZExtToSExt
, "Number of SExt instructions converted to ZExt");
35 class RISCVCodeGenPrepare
: public FunctionPass
,
36 public InstVisitor
<RISCVCodeGenPrepare
, bool> {
38 const RISCVSubtarget
*ST
;
43 RISCVCodeGenPrepare() : FunctionPass(ID
) {}
45 bool runOnFunction(Function
&F
) override
;
47 StringRef
getPassName() const override
{ return PASS_NAME
; }
49 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
51 AU
.addRequired
<TargetPassConfig
>();
54 bool visitInstruction(Instruction
&I
) { return false; }
55 bool visitZExtInst(ZExtInst
&I
);
56 bool visitAnd(BinaryOperator
&BO
);
59 } // end anonymous namespace
61 bool RISCVCodeGenPrepare::visitZExtInst(ZExtInst
&ZExt
) {
68 Value
*Src
= ZExt
.getOperand(0);
70 // We only care about ZExt from i32 to i64.
71 if (!ZExt
.getType()->isIntegerTy(64) || !Src
->getType()->isIntegerTy(32))
74 // Look for an opportunity to infer nneg on a zext if we can determine that
75 // the sign bit of X is zero via a dominating condition. This often occurs
76 // with widened induction variables.
77 if (isImpliedByDomCondition(ICmpInst::ICMP_SGE
, Src
,
78 Constant::getNullValue(Src
->getType()), &ZExt
,
79 *DL
).value_or(false)) {
85 // Convert (zext (abs(i32 X, i1 1))) -> (zext nneg (abs(i32 X, i1 1))). If abs of
86 // INT_MIN is poison, the sign bit is zero.
87 // TODO: Move this to instcombine now that we have zext nneg in IR.
88 using namespace PatternMatch
;
89 if (match(Src
, m_Intrinsic
<Intrinsic::abs
>(m_Value(), m_One()))) {
98 // Try to optimize (i64 (and (zext/sext (i32 X), C1))) if C1 has bit 31 set,
99 // but bits 63:32 are zero. If we know that bit 31 of X is 0, we can fill
100 // the upper 32 bits with ones.
101 bool RISCVCodeGenPrepare::visitAnd(BinaryOperator
&BO
) {
105 if (!BO
.getType()->isIntegerTy(64))
108 auto canBeSignExtend
= [](Instruction
*I
) {
109 if (isa
<SExtInst
>(I
))
111 if (isa
<ZExtInst
>(I
))
112 return I
->hasNonNeg();
116 // Left hand side should be a sext or zext nneg.
117 Instruction
*LHS
= dyn_cast
<Instruction
>(BO
.getOperand(0));
118 if (!LHS
|| !canBeSignExtend(LHS
))
121 Value
*LHSSrc
= LHS
->getOperand(0);
122 if (!LHSSrc
->getType()->isIntegerTy(32))
125 // Right hand side should be a constant.
126 Value
*RHS
= BO
.getOperand(1);
128 auto *CI
= dyn_cast
<ConstantInt
>(RHS
);
131 uint64_t C
= CI
->getZExtValue();
133 // Look for constants that fit in 32 bits but not simm12, and can be made
134 // into simm12 by sign extending bit 31. This will allow use of ANDI.
135 // TODO: Is worth making simm32?
136 if (!isUInt
<32>(C
) || isInt
<12>(C
) || !isInt
<12>(SignExtend64
<32>(C
)))
139 // Sign extend the constant and replace the And operand.
140 C
= SignExtend64
<32>(C
);
141 BO
.setOperand(1, ConstantInt::get(LHS
->getType(), C
));
146 bool RISCVCodeGenPrepare::runOnFunction(Function
&F
) {
150 auto &TPC
= getAnalysis
<TargetPassConfig
>();
151 auto &TM
= TPC
.getTM
<RISCVTargetMachine
>();
152 ST
= &TM
.getSubtarget
<RISCVSubtarget
>(F
);
154 DL
= &F
.getParent()->getDataLayout();
156 bool MadeChange
= false;
158 for (Instruction
&I
: llvm::make_early_inc_range(BB
))
159 MadeChange
|= visit(I
);
164 INITIALIZE_PASS_BEGIN(RISCVCodeGenPrepare
, DEBUG_TYPE
, PASS_NAME
, false, false)
165 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig
)
166 INITIALIZE_PASS_END(RISCVCodeGenPrepare
, DEBUG_TYPE
, PASS_NAME
, false, false)
168 char RISCVCodeGenPrepare::ID
= 0;
170 FunctionPass
*llvm::createRISCVCodeGenPreparePass() {
171 return new RISCVCodeGenPrepare();