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/InitializePasses.h"
22 #include "llvm/Pass.h"
23 
24 using namespace llvm;
25 
26 #define DEBUG_TYPE "riscv-codegenprepare"
27 #define PASS_NAME "RISCV CodeGenPrepare"
28 
29 STATISTIC(NumZExtToSExt, "Number of SExt instructions converted to ZExt");
30 
31 namespace {
32 
33 class RISCVCodeGenPrepare : public FunctionPass {
34   const DataLayout *DL;
35   const RISCVSubtarget *ST;
36 
37 public:
38   static char ID;
39 
40   RISCVCodeGenPrepare() : FunctionPass(ID) {}
41 
42   bool runOnFunction(Function &F) override;
43 
44   StringRef getPassName() const override { return PASS_NAME; }
45 
46   void getAnalysisUsage(AnalysisUsage &AU) const override {
47     AU.setPreservesCFG();
48     AU.addRequired<TargetPassConfig>();
49   }
50 
51 private:
52   bool optimizeZExt(ZExtInst *I);
53   bool optimizeAndExt(BinaryOperator *BO);
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     auto *SExt = new SExtInst(Src, ZExt->getType(), "", ZExt);
75     SExt->takeName(ZExt);
76     SExt->setDebugLoc(ZExt->getDebugLoc());
77 
78     ZExt->replaceAllUsesWith(SExt);
79     ZExt->eraseFromParent();
80     ++NumZExtToSExt;
81     return true;
82   }
83 
84   return false;
85 }
86 
87 // Try to optimize (i64 (and (zext/sext (i32 X), C1))) if C1 has bit 31 set,
88 // but bits 63:32 are zero. If we can prove that bit 31 of X is 0, we can fill
89 // the upper 32 bits with ones. A separate transform will turn (zext X) into
90 // (sext X) for the same condition.
91 bool RISCVCodeGenPrepare::optimizeAndExt(BinaryOperator *BO) {
92   if (!ST->is64Bit())
93     return false;
94 
95   if (BO->getOpcode() != Instruction::And)
96     return false;
97 
98   if (!BO->getType()->isIntegerTy(64))
99     return false;
100 
101   // Left hand side should be sext or zext.
102   Instruction *LHS = dyn_cast<Instruction>(BO->getOperand(0));
103   if (!LHS || (!isa<SExtInst>(LHS) && !isa<ZExtInst>(LHS)))
104     return false;
105 
106   Value *LHSSrc = LHS->getOperand(0);
107   if (!LHSSrc->getType()->isIntegerTy(32))
108     return false;
109 
110   // Right hand side should be a constant.
111   Value *RHS = BO->getOperand(1);
112 
113   auto *CI = dyn_cast<ConstantInt>(RHS);
114   if (!CI)
115     return false;
116   uint64_t C = CI->getZExtValue();
117 
118   // Look for constants that fit in 32 bits but not simm12, and can be made
119   // into simm12 by sign extending bit 31. This will allow use of ANDI.
120   // TODO: Is worth making simm32?
121   if (!isUInt<32>(C) || isInt<12>(C) || !isInt<12>(SignExtend64<32>(C)))
122     return false;
123 
124   // If we can determine the sign bit of the input is 0, we can replace the
125   // And mask constant.
126   if (!isImpliedByDomCondition(ICmpInst::ICMP_SGE, LHSSrc,
127                                Constant::getNullValue(LHSSrc->getType()),
128                                LHS, *DL))
129     return false;
130 
131   // Sign extend the constant and replace the And operand.
132   C = SignExtend64<32>(C);
133   BO->setOperand(1, ConstantInt::get(LHS->getType(), C));
134 
135   return true;
136 }
137 
138 bool RISCVCodeGenPrepare::runOnFunction(Function &F) {
139   if (skipFunction(F))
140     return false;
141 
142   auto &TPC = getAnalysis<TargetPassConfig>();
143   auto &TM = TPC.getTM<RISCVTargetMachine>();
144   ST = &TM.getSubtarget<RISCVSubtarget>(F);
145 
146   DL = &F.getParent()->getDataLayout();
147 
148   bool MadeChange = false;
149   for (auto &BB : F) {
150     for (Instruction &I : llvm::make_early_inc_range(BB)) {
151       if (auto *ZExt = dyn_cast<ZExtInst>(&I))
152         MadeChange |= optimizeZExt(ZExt);
153       else if (I.getOpcode() == Instruction::And)
154         MadeChange |= optimizeAndExt(cast<BinaryOperator>(&I));
155     }
156   }
157 
158   return MadeChange;
159 }
160 
161 INITIALIZE_PASS_BEGIN(RISCVCodeGenPrepare, DEBUG_TYPE, PASS_NAME, false, false)
162 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
163 INITIALIZE_PASS_END(RISCVCodeGenPrepare, DEBUG_TYPE, PASS_NAME, false, false)
164 
165 char RISCVCodeGenPrepare::ID = 0;
166 
167 FunctionPass *llvm::createRISCVCodeGenPreparePass() {
168   return new RISCVCodeGenPrepare();
169 }
170