xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
1 //===----- RISCVCodeGenPrepare.cpp ----------------------------------------===//
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 // 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.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "RISCV.h"
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"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "riscv-codegenprepare"
29 #define PASS_NAME "RISC-V CodeGenPrepare"
30 
31 STATISTIC(NumZExtToSExt, "Number of SExt instructions converted to ZExt");
32 
33 namespace {
34 
35 class RISCVCodeGenPrepare : public FunctionPass,
36                             public InstVisitor<RISCVCodeGenPrepare, bool> {
37   const DataLayout *DL;
38   const RISCVSubtarget *ST;
39 
40 public:
41   static char ID;
42 
43   RISCVCodeGenPrepare() : FunctionPass(ID) {}
44 
45   bool runOnFunction(Function &F) override;
46 
47   StringRef getPassName() const override { return PASS_NAME; }
48 
49   void getAnalysisUsage(AnalysisUsage &AU) const override {
50     AU.setPreservesCFG();
51     AU.addRequired<TargetPassConfig>();
52   }
53 
54   bool visitInstruction(Instruction &I) { return false; }
55   bool visitZExtInst(ZExtInst &I);
56   bool visitAnd(BinaryOperator &BO);
57 };
58 
59 } // end anonymous namespace
60 
61 bool RISCVCodeGenPrepare::visitZExtInst(ZExtInst &ZExt) {
62   if (!ST->is64Bit())
63     return false;
64 
65   Value *Src = ZExt.getOperand(0);
66 
67   // We only care about ZExt from i32 to i64.
68   if (!ZExt.getType()->isIntegerTy(64) || !Src->getType()->isIntegerTy(32))
69     return false;
70 
71   // Look for an opportunity to replace (i64 (zext (i32 X))) with a sext if we
72   // can determine that the sign bit of X is zero via a dominating condition.
73   // This often occurs with widened induction variables.
74   if (isImpliedByDomCondition(ICmpInst::ICMP_SGE, Src,
75                               Constant::getNullValue(Src->getType()), &ZExt,
76                               *DL).value_or(false)) {
77     auto *SExt = new SExtInst(Src, ZExt.getType(), "", &ZExt);
78     SExt->takeName(&ZExt);
79     SExt->setDebugLoc(ZExt.getDebugLoc());
80 
81     ZExt.replaceAllUsesWith(SExt);
82     ZExt.eraseFromParent();
83     ++NumZExtToSExt;
84     return true;
85   }
86 
87   // Convert (zext (abs(i32 X, i1 1))) -> (sext (abs(i32 X, i1 1))). If abs of
88   // INT_MIN is poison, the sign bit is zero.
89   using namespace PatternMatch;
90   if (match(Src, m_Intrinsic<Intrinsic::abs>(m_Value(), m_One()))) {
91     auto *SExt = new SExtInst(Src, ZExt.getType(), "", &ZExt);
92     SExt->takeName(&ZExt);
93     SExt->setDebugLoc(ZExt.getDebugLoc());
94 
95     ZExt.replaceAllUsesWith(SExt);
96     ZExt.eraseFromParent();
97     ++NumZExtToSExt;
98     return true;
99   }
100 
101   return false;
102 }
103 
104 // Try to optimize (i64 (and (zext/sext (i32 X), C1))) if C1 has bit 31 set,
105 // but bits 63:32 are zero. If we can prove that bit 31 of X is 0, we can fill
106 // the upper 32 bits with ones. A separate transform will turn (zext X) into
107 // (sext X) for the same condition.
108 bool RISCVCodeGenPrepare::visitAnd(BinaryOperator &BO) {
109   if (!ST->is64Bit())
110     return false;
111 
112   if (!BO.getType()->isIntegerTy(64))
113     return false;
114 
115   // Left hand side should be sext or zext.
116   Instruction *LHS = dyn_cast<Instruction>(BO.getOperand(0));
117   if (!LHS || (!isa<SExtInst>(LHS) && !isa<ZExtInst>(LHS)))
118     return false;
119 
120   Value *LHSSrc = LHS->getOperand(0);
121   if (!LHSSrc->getType()->isIntegerTy(32))
122     return false;
123 
124   // Right hand side should be a constant.
125   Value *RHS = BO.getOperand(1);
126 
127   auto *CI = dyn_cast<ConstantInt>(RHS);
128   if (!CI)
129     return false;
130   uint64_t C = CI->getZExtValue();
131 
132   // Look for constants that fit in 32 bits but not simm12, and can be made
133   // into simm12 by sign extending bit 31. This will allow use of ANDI.
134   // TODO: Is worth making simm32?
135   if (!isUInt<32>(C) || isInt<12>(C) || !isInt<12>(SignExtend64<32>(C)))
136     return false;
137 
138   // If we can determine the sign bit of the input is 0, we can replace the
139   // And mask constant.
140   if (!isImpliedByDomCondition(ICmpInst::ICMP_SGE, LHSSrc,
141                                Constant::getNullValue(LHSSrc->getType()),
142                                LHS, *DL).value_or(false))
143     return false;
144 
145   // Sign extend the constant and replace the And operand.
146   C = SignExtend64<32>(C);
147   BO.setOperand(1, ConstantInt::get(LHS->getType(), C));
148 
149   return true;
150 }
151 
152 bool RISCVCodeGenPrepare::runOnFunction(Function &F) {
153   if (skipFunction(F))
154     return false;
155 
156   auto &TPC = getAnalysis<TargetPassConfig>();
157   auto &TM = TPC.getTM<RISCVTargetMachine>();
158   ST = &TM.getSubtarget<RISCVSubtarget>(F);
159 
160   DL = &F.getParent()->getDataLayout();
161 
162   bool MadeChange = false;
163   for (auto &BB : F)
164     for (Instruction &I : llvm::make_early_inc_range(BB))
165       MadeChange |= visit(I);
166 
167   return MadeChange;
168 }
169 
170 INITIALIZE_PASS_BEGIN(RISCVCodeGenPrepare, DEBUG_TYPE, PASS_NAME, false, false)
171 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
172 INITIALIZE_PASS_END(RISCVCodeGenPrepare, DEBUG_TYPE, PASS_NAME, false, false)
173 
174 char RISCVCodeGenPrepare::ID = 0;
175 
176 FunctionPass *llvm::createRISCVCodeGenPreparePass() {
177   return new RISCVCodeGenPrepare();
178 }
179