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