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