1fcaf7f86SDimitry Andric //===----- RISCVCodeGenPrepare.cpp ----------------------------------------===// 2fcaf7f86SDimitry Andric // 3fcaf7f86SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fcaf7f86SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fcaf7f86SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fcaf7f86SDimitry Andric // 7fcaf7f86SDimitry Andric //===----------------------------------------------------------------------===// 8fcaf7f86SDimitry Andric // 9fcaf7f86SDimitry Andric // This is a RISCV specific version of CodeGenPrepare. 10fcaf7f86SDimitry Andric // It munges the code in the input function to better prepare it for 11fcaf7f86SDimitry Andric // SelectionDAG-based code generation. This works around limitations in it's 12fcaf7f86SDimitry Andric // basic-block-at-a-time approach. 13fcaf7f86SDimitry Andric // 14fcaf7f86SDimitry Andric //===----------------------------------------------------------------------===// 15fcaf7f86SDimitry Andric 16fcaf7f86SDimitry Andric #include "RISCV.h" 17fcaf7f86SDimitry Andric #include "RISCVTargetMachine.h" 18fcaf7f86SDimitry Andric #include "llvm/ADT/Statistic.h" 19fcaf7f86SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 20fcaf7f86SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 21972a253aSDimitry Andric #include "llvm/IR/PatternMatch.h" 22fcaf7f86SDimitry Andric #include "llvm/InitializePasses.h" 23fcaf7f86SDimitry Andric #include "llvm/Pass.h" 24fcaf7f86SDimitry Andric 25fcaf7f86SDimitry Andric using namespace llvm; 26fcaf7f86SDimitry Andric 27fcaf7f86SDimitry Andric #define DEBUG_TYPE "riscv-codegenprepare" 28fcaf7f86SDimitry Andric #define PASS_NAME "RISCV CodeGenPrepare" 29fcaf7f86SDimitry Andric 30fcaf7f86SDimitry Andric STATISTIC(NumZExtToSExt, "Number of SExt instructions converted to ZExt"); 31fcaf7f86SDimitry Andric 32fcaf7f86SDimitry Andric namespace { 33fcaf7f86SDimitry Andric 34fcaf7f86SDimitry Andric class RISCVCodeGenPrepare : public FunctionPass { 35fcaf7f86SDimitry Andric const DataLayout *DL; 36fcaf7f86SDimitry Andric const RISCVSubtarget *ST; 37fcaf7f86SDimitry Andric 38fcaf7f86SDimitry Andric public: 39fcaf7f86SDimitry Andric static char ID; 40fcaf7f86SDimitry Andric 41fcaf7f86SDimitry Andric RISCVCodeGenPrepare() : FunctionPass(ID) {} 42fcaf7f86SDimitry Andric 43fcaf7f86SDimitry Andric bool runOnFunction(Function &F) override; 44fcaf7f86SDimitry Andric 45fcaf7f86SDimitry Andric StringRef getPassName() const override { return PASS_NAME; } 46fcaf7f86SDimitry Andric 47fcaf7f86SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 48fcaf7f86SDimitry Andric AU.setPreservesCFG(); 49fcaf7f86SDimitry Andric AU.addRequired<TargetPassConfig>(); 50fcaf7f86SDimitry Andric } 51fcaf7f86SDimitry Andric 52fcaf7f86SDimitry Andric private: 53fcaf7f86SDimitry Andric bool optimizeZExt(ZExtInst *I); 54fcaf7f86SDimitry Andric bool optimizeAndExt(BinaryOperator *BO); 55fcaf7f86SDimitry Andric }; 56fcaf7f86SDimitry Andric 57fcaf7f86SDimitry Andric } // end anonymous namespace 58fcaf7f86SDimitry Andric 59fcaf7f86SDimitry Andric bool RISCVCodeGenPrepare::optimizeZExt(ZExtInst *ZExt) { 60fcaf7f86SDimitry Andric if (!ST->is64Bit()) 61fcaf7f86SDimitry Andric return false; 62fcaf7f86SDimitry Andric 63fcaf7f86SDimitry Andric Value *Src = ZExt->getOperand(0); 64fcaf7f86SDimitry Andric 65fcaf7f86SDimitry Andric // We only care about ZExt from i32 to i64. 66fcaf7f86SDimitry Andric if (!ZExt->getType()->isIntegerTy(64) || !Src->getType()->isIntegerTy(32)) 67fcaf7f86SDimitry Andric return false; 68fcaf7f86SDimitry Andric 69fcaf7f86SDimitry Andric // Look for an opportunity to replace (i64 (zext (i32 X))) with a sext if we 70fcaf7f86SDimitry Andric // can determine that the sign bit of X is zero via a dominating condition. 71fcaf7f86SDimitry Andric // This often occurs with widened induction variables. 72fcaf7f86SDimitry Andric if (isImpliedByDomCondition(ICmpInst::ICMP_SGE, Src, 73fcaf7f86SDimitry Andric Constant::getNullValue(Src->getType()), ZExt, 74*a4a491e2SDimitry Andric *DL).value_or(false)) { 75fcaf7f86SDimitry Andric auto *SExt = new SExtInst(Src, ZExt->getType(), "", ZExt); 76fcaf7f86SDimitry Andric SExt->takeName(ZExt); 77fcaf7f86SDimitry Andric SExt->setDebugLoc(ZExt->getDebugLoc()); 78fcaf7f86SDimitry Andric 79fcaf7f86SDimitry Andric ZExt->replaceAllUsesWith(SExt); 80fcaf7f86SDimitry Andric ZExt->eraseFromParent(); 81fcaf7f86SDimitry Andric ++NumZExtToSExt; 82fcaf7f86SDimitry Andric return true; 83fcaf7f86SDimitry Andric } 84fcaf7f86SDimitry Andric 85972a253aSDimitry Andric // Convert (zext (abs(i32 X, i1 1))) -> (sext (abs(i32 X, i1 1))). If abs of 86972a253aSDimitry Andric // INT_MIN is poison, the sign bit is zero. 87972a253aSDimitry Andric using namespace PatternMatch; 88972a253aSDimitry Andric if (match(Src, m_Intrinsic<Intrinsic::abs>(m_Value(), m_One()))) { 89972a253aSDimitry Andric auto *SExt = new SExtInst(Src, ZExt->getType(), "", ZExt); 90972a253aSDimitry Andric SExt->takeName(ZExt); 91972a253aSDimitry Andric SExt->setDebugLoc(ZExt->getDebugLoc()); 92972a253aSDimitry Andric 93972a253aSDimitry Andric ZExt->replaceAllUsesWith(SExt); 94972a253aSDimitry Andric ZExt->eraseFromParent(); 95972a253aSDimitry Andric ++NumZExtToSExt; 96972a253aSDimitry Andric return true; 97972a253aSDimitry Andric } 98972a253aSDimitry Andric 99fcaf7f86SDimitry Andric return false; 100fcaf7f86SDimitry Andric } 101fcaf7f86SDimitry Andric 102fcaf7f86SDimitry Andric // Try to optimize (i64 (and (zext/sext (i32 X), C1))) if C1 has bit 31 set, 103fcaf7f86SDimitry Andric // but bits 63:32 are zero. If we can prove that bit 31 of X is 0, we can fill 104fcaf7f86SDimitry Andric // the upper 32 bits with ones. A separate transform will turn (zext X) into 105fcaf7f86SDimitry Andric // (sext X) for the same condition. 106fcaf7f86SDimitry Andric bool RISCVCodeGenPrepare::optimizeAndExt(BinaryOperator *BO) { 107fcaf7f86SDimitry Andric if (!ST->is64Bit()) 108fcaf7f86SDimitry Andric return false; 109fcaf7f86SDimitry Andric 110fcaf7f86SDimitry Andric if (BO->getOpcode() != Instruction::And) 111fcaf7f86SDimitry Andric return false; 112fcaf7f86SDimitry Andric 113fcaf7f86SDimitry Andric if (!BO->getType()->isIntegerTy(64)) 114fcaf7f86SDimitry Andric return false; 115fcaf7f86SDimitry Andric 116fcaf7f86SDimitry Andric // Left hand side should be sext or zext. 117fcaf7f86SDimitry Andric Instruction *LHS = dyn_cast<Instruction>(BO->getOperand(0)); 118fcaf7f86SDimitry Andric if (!LHS || (!isa<SExtInst>(LHS) && !isa<ZExtInst>(LHS))) 119fcaf7f86SDimitry Andric return false; 120fcaf7f86SDimitry Andric 121fcaf7f86SDimitry Andric Value *LHSSrc = LHS->getOperand(0); 122fcaf7f86SDimitry Andric if (!LHSSrc->getType()->isIntegerTy(32)) 123fcaf7f86SDimitry Andric return false; 124fcaf7f86SDimitry Andric 125fcaf7f86SDimitry Andric // Right hand side should be a constant. 126fcaf7f86SDimitry Andric Value *RHS = BO->getOperand(1); 127fcaf7f86SDimitry Andric 128fcaf7f86SDimitry Andric auto *CI = dyn_cast<ConstantInt>(RHS); 129fcaf7f86SDimitry Andric if (!CI) 130fcaf7f86SDimitry Andric return false; 131fcaf7f86SDimitry Andric uint64_t C = CI->getZExtValue(); 132fcaf7f86SDimitry Andric 133fcaf7f86SDimitry Andric // Look for constants that fit in 32 bits but not simm12, and can be made 134fcaf7f86SDimitry Andric // into simm12 by sign extending bit 31. This will allow use of ANDI. 135fcaf7f86SDimitry Andric // TODO: Is worth making simm32? 136fcaf7f86SDimitry Andric if (!isUInt<32>(C) || isInt<12>(C) || !isInt<12>(SignExtend64<32>(C))) 137fcaf7f86SDimitry Andric return false; 138fcaf7f86SDimitry Andric 139fcaf7f86SDimitry Andric // If we can determine the sign bit of the input is 0, we can replace the 140fcaf7f86SDimitry Andric // And mask constant. 141fcaf7f86SDimitry Andric if (!isImpliedByDomCondition(ICmpInst::ICMP_SGE, LHSSrc, 142fcaf7f86SDimitry Andric Constant::getNullValue(LHSSrc->getType()), 143*a4a491e2SDimitry Andric LHS, *DL).value_or(false)) 144fcaf7f86SDimitry Andric return false; 145fcaf7f86SDimitry Andric 146fcaf7f86SDimitry Andric // Sign extend the constant and replace the And operand. 147fcaf7f86SDimitry Andric C = SignExtend64<32>(C); 148fcaf7f86SDimitry Andric BO->setOperand(1, ConstantInt::get(LHS->getType(), C)); 149fcaf7f86SDimitry Andric 150fcaf7f86SDimitry Andric return true; 151fcaf7f86SDimitry Andric } 152fcaf7f86SDimitry Andric 153fcaf7f86SDimitry Andric bool RISCVCodeGenPrepare::runOnFunction(Function &F) { 154fcaf7f86SDimitry Andric if (skipFunction(F)) 155fcaf7f86SDimitry Andric return false; 156fcaf7f86SDimitry Andric 157fcaf7f86SDimitry Andric auto &TPC = getAnalysis<TargetPassConfig>(); 158fcaf7f86SDimitry Andric auto &TM = TPC.getTM<RISCVTargetMachine>(); 159fcaf7f86SDimitry Andric ST = &TM.getSubtarget<RISCVSubtarget>(F); 160fcaf7f86SDimitry Andric 161fcaf7f86SDimitry Andric DL = &F.getParent()->getDataLayout(); 162fcaf7f86SDimitry Andric 163fcaf7f86SDimitry Andric bool MadeChange = false; 164fcaf7f86SDimitry Andric for (auto &BB : F) { 165fcaf7f86SDimitry Andric for (Instruction &I : llvm::make_early_inc_range(BB)) { 166fcaf7f86SDimitry Andric if (auto *ZExt = dyn_cast<ZExtInst>(&I)) 167fcaf7f86SDimitry Andric MadeChange |= optimizeZExt(ZExt); 168fcaf7f86SDimitry Andric else if (I.getOpcode() == Instruction::And) 169fcaf7f86SDimitry Andric MadeChange |= optimizeAndExt(cast<BinaryOperator>(&I)); 170fcaf7f86SDimitry Andric } 171fcaf7f86SDimitry Andric } 172fcaf7f86SDimitry Andric 173fcaf7f86SDimitry Andric return MadeChange; 174fcaf7f86SDimitry Andric } 175fcaf7f86SDimitry Andric 176fcaf7f86SDimitry Andric INITIALIZE_PASS_BEGIN(RISCVCodeGenPrepare, DEBUG_TYPE, PASS_NAME, false, false) 177fcaf7f86SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) 178fcaf7f86SDimitry Andric INITIALIZE_PASS_END(RISCVCodeGenPrepare, DEBUG_TYPE, PASS_NAME, false, false) 179fcaf7f86SDimitry Andric 180fcaf7f86SDimitry Andric char RISCVCodeGenPrepare::ID = 0; 181fcaf7f86SDimitry Andric 182fcaf7f86SDimitry Andric FunctionPass *llvm::createRISCVCodeGenPreparePass() { 183fcaf7f86SDimitry Andric return new RISCVCodeGenPrepare(); 184fcaf7f86SDimitry Andric } 185