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 RISCV 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/IRBuilder.h"
22 #include "llvm/InitializePasses.h"
23 #include "llvm/Pass.h"
24 
25 using namespace llvm;
26 
27 #define DEBUG_TYPE "riscv-codegenprepare"
28 #define PASS_NAME "RISCV CodeGenPrepare"
29 
30 STATISTIC(NumZExtToSExt, "Number of SExt instructions converted to ZExt");
31 
32 namespace {
33 
34 class RISCVCodeGenPrepare : public FunctionPass {
35   const DataLayout *DL;
36   const RISCVSubtarget *ST;
37 
38 public:
39   static char ID;
40 
41   RISCVCodeGenPrepare() : FunctionPass(ID) {}
42 
43   bool runOnFunction(Function &F) override;
44 
45   StringRef getPassName() const override { return PASS_NAME; }
46 
47   void getAnalysisUsage(AnalysisUsage &AU) const override {
48     AU.setPreservesCFG();
49     AU.addRequired<TargetPassConfig>();
50   }
51 
52 private:
53   bool optimizeZExt(ZExtInst *I);
54 };
55 
56 } // end anonymous namespace
57 
58 bool RISCVCodeGenPrepare::optimizeZExt(ZExtInst *ZExt) {
59   if (!ST->is64Bit())
60     return false;
61 
62   Value *Src = ZExt->getOperand(0);
63 
64   // We only care about ZExt from i32 to i64.
65   if (!ZExt->getType()->isIntegerTy(64) || !Src->getType()->isIntegerTy(32))
66     return false;
67 
68   // Look for an opportunity to replace (i64 (zext (i32 X))) with a sext if we
69   // can determine that the sign bit of X is zero via a dominating condition.
70   // This often occurs with widened induction variables.
71   if (isImpliedByDomCondition(ICmpInst::ICMP_SGE, Src,
72                               Constant::getNullValue(Src->getType()), ZExt,
73                               *DL)) {
74     IRBuilder<> Builder(ZExt);
75     Value *SExt = Builder.CreateSExt(Src, ZExt->getType());
76     SExt->takeName(ZExt);
77 
78     ZExt->replaceAllUsesWith(SExt);
79     ZExt->eraseFromParent();
80     ++NumZExtToSExt;
81     return true;
82   }
83 
84   return false;
85 }
86 
87 bool RISCVCodeGenPrepare::runOnFunction(Function &F) {
88   if (skipFunction(F))
89     return false;
90 
91   auto &TPC = getAnalysis<TargetPassConfig>();
92   auto &TM = TPC.getTM<RISCVTargetMachine>();
93   ST = &TM.getSubtarget<RISCVSubtarget>(F);
94 
95   DL = &F.getParent()->getDataLayout();
96 
97   bool MadeChange = false;
98   for (auto &BB : F) {
99     for (Instruction &I : llvm::make_early_inc_range(BB)) {
100       if (auto *ZExt = dyn_cast<ZExtInst>(&I))
101         MadeChange |= optimizeZExt(ZExt);
102     }
103   }
104 
105   return MadeChange;
106 }
107 
108 INITIALIZE_PASS_BEGIN(RISCVCodeGenPrepare, DEBUG_TYPE, PASS_NAME, false, false)
109 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
110 INITIALIZE_PASS_END(RISCVCodeGenPrepare, DEBUG_TYPE, PASS_NAME, false, false)
111 
112 char RISCVCodeGenPrepare::ID = 0;
113 
114 FunctionPass *llvm::createRISCVCodeGenPreparePass() {
115   return new RISCVCodeGenPrepare();
116 }
117