LLVM: lib/Target/RISCV/RISCVCodeGenPrepare.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

29

30using namespace llvm;

31

32#define DEBUG_TYPE "riscv-codegenprepare"

33#define PASS_NAME "RISC-V CodeGenPrepare"

34

35namespace {

36class RISCVCodeGenPrepare : public InstVisitor<RISCVCodeGenPrepare, bool> {

41

42public:

45 : F(F), DL(&F.getDataLayout()), DT(DT), ST(ST) {}

46 bool run();

47 bool visitInstruction(Instruction &I) { return false; }

52};

53}

54

55namespace {

56class RISCVCodeGenPrepareLegacyPass : public FunctionPass {

57public:

58 static char ID;

59

60 RISCVCodeGenPrepareLegacyPass() : FunctionPass(ID) {}

61

63 StringRef getPassName() const override { return PASS_NAME; }

64

65 void getAnalysisUsage(AnalysisUsage &AU) const override {

67 AU.addRequired();

69 }

70};

71}

72

73

74

75

76bool RISCVCodeGenPrepare::visitAnd(BinaryOperator &BO) {

78 return false;

79

81 return false;

82

83 using namespace PatternMatch;

84

85

88 return false;

89

91 return false;

92

93

95

97 if (!CI)

98 return false;

99 uint64_t C = CI->getZExtValue();

100

101

102

103

105 return false;

106

107

110

111 return true;

112}

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143bool RISCVCodeGenPrepare::widenVPMerge(IntrinsicInst &II) {

144 if (II.getType()->getScalarType()->isIntegerTy(1))

145 return false;

146

148 using namespace PatternMatch;

152 return false;

153

155 if (!Phi || Phi->hasOneUse() || Phi->getNumIncomingValues() != 2 ||

157 Phi->getIncomingValue(1) != &II)

158 return false;

159

160 Type *WideTy =

161 VectorType::get(IntegerType::getInt8Ty(II.getContext()),

163

165 PHINode *WidePhi = Builder.CreatePHI(WideTy, 2);

167 Phi->getIncomingBlock(0));

168 Builder.SetInsertPoint(&II);

169 Value *WideTrue = Builder.CreateZExt(True, WideTy);

170 Value *WideMerge = Builder.CreateIntrinsic(Intrinsic::vp_merge, {WideTy},

171 {Mask, WideTrue, WidePhi, EVL});

172 WidePhi->addIncoming(WideMerge, Phi->getIncomingBlock(1));

173 Value *Trunc = Builder.CreateTrunc(WideMerge, II.getType());

174

175 II.replaceAllUsesWith(Trunc);

176

177

178 Phi->setIncomingValue(1, Phi->getIncomingValue(0));

180

181 return true;

182}

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215bool RISCVCodeGenPrepare::visitIntrinsicInst(IntrinsicInst &I) {

216 if (expandVPStrideLoad(I))

217 return true;

218

219 if (widenVPMerge(I))

220 return true;

221

222 if (I.getIntrinsicID() != Intrinsic::vector_reduce_fadd &&

224 return false;

225

227 if (PHI || PHI->hasOneUse() ||

229 return false;

230

231 Type *VecTy = I.getOperand(1)->getType();

233 auto *VecPHI = Builder.CreatePHI(VecTy, PHI->getNumIncomingValues());

234

235 for (auto *BB : PHI->blocks()) {

236 Builder.SetInsertPoint(BB->getTerminator());

237 Value *InsertElt = Builder.CreateInsertElement(

238 VecTy, PHI->getIncomingValueForBlock(BB), (uint64_t)0);

239 VecPHI->addIncoming(InsertElt, BB);

240 }

241

242 Builder.SetInsertPoint(&I);

243 I.setOperand(0, Builder.CreateExtractElement(VecPHI, (uint64_t)0));

244

245 PHI->eraseFromParent();

246

247 return true;

248}

249

250

251

252

253bool RISCVCodeGenPrepare::expandVPStrideLoad(IntrinsicInst &II) {

255

256 using namespace PatternMatch;

259 return false;

260

261

262

263 if (II.getType()->getScalarSizeInBits() > ST->getXLen())

264 return false;

265

267 return false;

268

270

272 Type *STy = VTy->getElementType();

273 Value *Val = Builder.CreateLoad(STy, BasePtr);

274 Value *Res = Builder.CreateIntrinsic(

275 Intrinsic::vp_merge, VTy,

276 {II.getOperand(2), Builder.CreateVectorSplat(VTy->getElementCount(), Val),

278

279 II.replaceAllUsesWith(Res);

280 II.eraseFromParent();

281 return true;

282}

283

284bool RISCVCodeGenPrepare::run() {

285 bool MadeChange = false;

286 for (auto &BB : F)

288 MadeChange |= visit(I);

289

290 return MadeChange;

291}

292

293bool RISCVCodeGenPrepareLegacyPass::runOnFunction(Function &F) {

294 if (skipFunction(F))

295 return false;

296

297 auto &TPC = getAnalysis();

298 auto &TM = TPC.getTM();

299 auto ST = &TM.getSubtarget(F);

300 auto DT = &getAnalysis().getDomTree();

301

302 RISCVCodeGenPrepare RVCGP(F, DT, ST);

303 return RVCGP.run();

304}

305

307 false, false)

311

312char RISCVCodeGenPrepareLegacyPass::ID = 0;

313

315 return new RISCVCodeGenPrepareLegacyPass();

316}

317

322 bool Changed = RISCVCodeGenPrepare(F, DT, ST).run();

325

328 return PA;

329}

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static bool runOnFunction(Function &F, bool PostInlining)

uint64_t IntrinsicInst * II

FunctionAnalysisManager FAM

#define INITIALIZE_PASS_DEPENDENCY(depName)

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

#define PASS_NAME

Definition RISCVCodeGenPrepare.cpp:33

void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

Target-Independent Code Generator Pass Configuration Options pass.

AnalysisUsage & addRequired()

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

Represents analyses that only rely on functions' control flow.

static LLVM_ABI ConstantAggregateZero * get(Type *Ty)

A parsed version of the target data layout string in and methods for querying it.

Analysis pass which computes a DominatorTree.

Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.

FunctionPass class - This class is used to implement most global optimizations.

Base class for instruction visitors.

A wrapper class for inspecting calls to intrinsic functions.

void addIncoming(Value *V, BasicBlock *BB)

Add an incoming value to the end of the PHI list.

static LLVM_ABI PoisonValue * get(Type *T)

Static factory methods - Return an 'poison' object of the specified type.

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses none()

Convenience factory function for the empty preserved set.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

PreservedAnalyses & preserveSet()

Mark an analysis set as preserved.

PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)

Definition RISCVCodeGenPrepare.cpp:318

Target-Independent Code Generator Pass Configuration Options.

bool isIntegerTy() const

True if this is an instance of IntegerType.

void setOperand(unsigned i, Value *Val)

Value * getOperand(unsigned i) const

Type * getType() const

All values are typed, get the type of this value.

constexpr std::underlying_type_t< E > Mask()

Get a bitmask with 1s in all places up to the high-order bit of E's largest value.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

cst_pred_ty< is_all_ones > m_AllOnes()

Match an integer or vector with all bits set.

bool match(Val *V, const Pattern &P)

IntrinsicID_match m_Intrinsic()

Match intrinsic calls like this: m_IntrinsicIntrinsic::fabs(m_Value(X))

NNegZExt_match< OpTy > m_NNegZExt(const OpTy &Op)

class_match< Value > m_Value()

Match an arbitrary value and ignore it.

is_zero m_Zero()

Match any null constant or a vector with all elements equal to 0.

NodeAddr< PhiNode * > Phi

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())

If the specified value is a trivially dead instruction, delete it.

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

FunctionPass * createRISCVCodeGenPrepareLegacyPass()

Definition RISCVCodeGenPrepare.cpp:314

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

constexpr bool isUInt(uint64_t x)

Checks if an unsigned integer fits into the given bit width.

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)

Return true if the given value is known to be non-zero when defined.

IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

constexpr int64_t SignExtend64(uint64_t x)

Sign-extend the number in the bottom B bits of X to a 64-bit integer.

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.