LLVM: lib/Transforms/Utils/IntegerDivision.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

21

22using namespace llvm;

23

24#define DEBUG_TYPE "integer-division"

25

26

27

28

29

30

31

36

37

38

39

40

41

42

43

44

45

46

47

48

49 Dividend = Builder.CreateFreeze(Dividend);

50 Divisor = Builder.CreateFreeze(Divisor);

51 Value *DividendSign = Builder.CreateAShr(Dividend, Shift);

52 Value *DivisorSign = Builder.CreateAShr(Divisor, Shift);

53 Value *DvdXor = Builder.CreateXor(Dividend, DividendSign);

54 Value *DvsXor = Builder.CreateXor(Divisor, DivisorSign);

55 Value *UDividend = Builder.CreateSub(DvdXor, DividendSign);

56 Value *UDivisor = Builder.CreateSub(DvsXor, DivisorSign);

57 Value *URem = Builder.CreateURem(UDividend, UDivisor);

58 Value *Xored = Builder.CreateXor(URem, DividendSign);

59 Value *SRem = Builder.CreateSub(Xored, DividendSign);

60

62 Builder.SetInsertPoint(URemInst);

63

64 return SRem;

65}

66

67

68

69

70

71

72

75

76

77

78

79

80

81

82 Dividend = Builder.CreateFreeze(Dividend);

83 Divisor = Builder.CreateFreeze(Divisor);

84 Value *Quotient = Builder.CreateUDiv(Dividend, Divisor);

85 Value *Product = Builder.CreateMul(Divisor, Quotient);

86 Value *Remainder = Builder.CreateSub(Dividend, Product);

87

89 Builder.SetInsertPoint(UDiv);

90

91 return Remainder;

92}

93

94

95

96

97

98

101

102

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119 Dividend = Builder.CreateFreeze(Dividend);

120 Divisor = Builder.CreateFreeze(Divisor);

121 Value *Tmp = Builder.CreateAShr(Dividend, Shift);

122 Value *Tmp1 = Builder.CreateAShr(Divisor, Shift);

123 Value *Tmp2 = Builder.CreateXor(Tmp, Dividend);

124 Value *U_Dvnd = Builder.CreateSub(Tmp2, Tmp);

125 Value *Tmp3 = Builder.CreateXor(Tmp1, Divisor);

126 Value *U_Dvsr = Builder.CreateSub(Tmp3, Tmp1);

127 Value *Q_Sgn = Builder.CreateXor(Tmp1, Tmp);

128 Value *Q_Mag = Builder.CreateUDiv(U_Dvnd, U_Dvsr);

129 Value *Tmp4 = Builder.CreateXor(Q_Mag, Q_Sgn);

130 Value *Q = Builder.CreateSub(Tmp4, Q_Sgn);

131

133 Builder.SetInsertPoint(UDiv);

134

135 return Q;

136}

137

138

139

140

143

144

145

146

147

150

151 ConstantInt *Zero = ConstantInt::get(DivTy, 0);

152 ConstantInt *One = ConstantInt::get(DivTy, 1);

155

157

158 BasicBlock *IBB = Builder.GetInsertBlock();

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195 BasicBlock *SpecialCases = Builder.GetInsertBlock();

196 SpecialCases->setName(Twine(SpecialCases->getName(), "_udiv-special-cases"));

198 "udiv-end");

200 "udiv-loop-exit", F, End);

202 "udiv-do-while", F, End);

204 "udiv-preheader", F, End);

206 "udiv-bb1", F, End);

207

208

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228 Builder.SetInsertPoint(SpecialCases);

229 Divisor = Builder.CreateFreeze(Divisor);

230 Dividend = Builder.CreateFreeze(Dividend);

231 Value *Ret0_1 = Builder.CreateICmpEQ(Divisor, Zero);

232 Value *Ret0_2 = Builder.CreateICmpEQ(Dividend, Zero);

233 Value *Ret0_3 = Builder.CreateOr(Ret0_1, Ret0_2);

234 Value *Tmp0 = Builder.CreateCall(CTLZ, {Divisor, True});

235 Value *Tmp1 = Builder.CreateCall(CTLZ, {Dividend, True});

236 Value *SR = Builder.CreateSub(Tmp0, Tmp1);

237 Value *Ret0_4 = Builder.CreateICmpUGT(SR, MSB);

238 Value *Ret0 = Builder.CreateLogicalOr(Ret0_3, Ret0_4);

239 Value *RetDividend = Builder.CreateICmpEQ(SR, MSB);

240 Value *RetVal = Builder.CreateSelect(Ret0, Zero, Dividend);

241 Value *EarlyRet = Builder.CreateLogicalOr(Ret0, RetDividend);

242 Builder.CreateCondBr(EarlyRet, End, BB1);

243

244

245

246

247

248

249

250 Builder.SetInsertPoint(BB1);

251 Value *SR_1 = Builder.CreateAdd(SR, One);

252 Value *Tmp2 = Builder.CreateSub(MSB, SR);

253 Value *Q = Builder.CreateShl(Dividend, Tmp2);

254 Value *SkipLoop = Builder.CreateICmpEQ(SR_1, Zero);

255 Builder.CreateCondBr(SkipLoop, LoopExit, Preheader);

256

257

258

259

260

261 Builder.SetInsertPoint(Preheader);

262 Value *Tmp3 = Builder.CreateLShr(Dividend, SR_1);

263 Value *Tmp4 = Builder.CreateAdd(Divisor, NegOne);

264 Builder.CreateBr(DoWhile);

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284 Builder.SetInsertPoint(DoWhile);

285 PHINode *Carry_1 = Builder.CreatePHI(DivTy, 2);

286 PHINode *SR_3 = Builder.CreatePHI(DivTy, 2);

287 PHINode *R_1 = Builder.CreatePHI(DivTy, 2);

288 PHINode *Q_2 = Builder.CreatePHI(DivTy, 2);

289 Value *Tmp5 = Builder.CreateShl(R_1, One);

290 Value *Tmp6 = Builder.CreateLShr(Q_2, MSB);

291 Value *Tmp7 = Builder.CreateOr(Tmp5, Tmp6);

292 Value *Tmp8 = Builder.CreateShl(Q_2, One);

293 Value *Q_1 = Builder.CreateOr(Carry_1, Tmp8);

294 Value *Tmp9 = Builder.CreateSub(Tmp4, Tmp7);

295 Value *Tmp10 = Builder.CreateAShr(Tmp9, MSB);

296 Value *Carry = Builder.CreateAnd(Tmp10, One);

297 Value *Tmp11 = Builder.CreateAnd(Tmp10, Divisor);

298 Value *R = Builder.CreateSub(Tmp7, Tmp11);

299 Value *SR_2 = Builder.CreateAdd(SR_3, NegOne);

300 Value *Tmp12 = Builder.CreateICmpEQ(SR_2, Zero);

301 Builder.CreateCondBr(Tmp12, LoopExit, DoWhile);

302

303

304

305

306

307

308

309 Builder.SetInsertPoint(LoopExit);

310 PHINode *Carry_2 = Builder.CreatePHI(DivTy, 2);

311 PHINode *Q_3 = Builder.CreatePHI(DivTy, 2);

312 Value *Tmp13 = Builder.CreateShl(Q_3, One);

313 Value *Q_4 = Builder.CreateOr(Carry_2, Tmp13);

314 Builder.CreateBr(End);

315

316

317

318

319 Builder.SetInsertPoint(End, End->begin());

320 PHINode *Q_5 = Builder.CreatePHI(DivTy, 2);

321

322

323

326

329

332

335

338

341

344

345 return Q_5;

346}

347

348

349

350

351

352

353

356 Rem->getOpcode() == Instruction::URem) &&

357 "Trying to expand remainder from a non-remainder function");

358

360

362

363

364 if (Rem->getOpcode() == Instruction::SRem) {

367

368

369 bool IsInsertPoint = Rem->getIterator() == Builder.GetInsertPoint();

373

374

375

376

377 if (IsInsertPoint)

378 return true;

379

381 Rem = BO;

382 }

383

386

390

391

393 assert(UDiv->getOpcode() == Instruction::UDiv && "Non-udiv in expansion?");

395 }

396

397 return true;

398}

399

400

401

402

403

404

405

408 Div->getOpcode() == Instruction::UDiv) &&

409 "Trying to expand division from a non-division function");

410

412

414

415

416 if (Div->getOpcode() == Instruction::SDiv) {

417

420

421

422 bool IsInsertPoint = Div->getIterator() == Builder.GetInsertPoint();

426

427

428

429

430 if (IsInsertPoint)

431 return true;

432

434 Div = BO;

435 }

436

437

440 Builder);

444

445 return true;

446}

447

448

449

450

451

452

453

454

457 Rem->getOpcode() == Instruction::URem) &&

458 "Trying to expand remainder from a non-remainder function");

459

461 assert(!RemTy->isVectorTy() && "Div over vectors not supported");

462

464

465 assert(RemTyBitWidth <= 32 &&

466 "Div of bitwidth greater than 32 not supported");

467

468 if (RemTyBitWidth == 32)

470

471

472

474

475 Value *ExtDividend;

476 Value *ExtDivisor;

480

481 if (Rem->getOpcode() == Instruction::SRem) {

484 ExtRem = Builder.CreateSRem(ExtDividend, ExtDivisor);

485 } else {

488 ExtRem = Builder.CreateURem(ExtDividend, ExtDivisor);

489 }

490 Trunc = Builder.CreateTrunc(ExtRem, RemTy);

491

495

497}

498

499

500

501

502

503

506 Rem->getOpcode() == Instruction::URem) &&

507 "Trying to expand remainder from a non-remainder function");

508

510 assert(!RemTy->isVectorTy() && "Div over vectors not supported");

511

513

514 if (RemTyBitWidth >= 64)

516

517

518

520

521 Value *ExtDividend;

522 Value *ExtDivisor;

526

527 if (Rem->getOpcode() == Instruction::SRem) {

528 ExtDividend = Builder.CreateSExt(Rem->getOperand(0), Int64Ty);

529 ExtDivisor = Builder.CreateSExt(Rem->getOperand(1), Int64Ty);

530 ExtRem = Builder.CreateSRem(ExtDividend, ExtDivisor);

531 } else {

532 ExtDividend = Builder.CreateZExt(Rem->getOperand(0), Int64Ty);

533 ExtDivisor = Builder.CreateZExt(Rem->getOperand(1), Int64Ty);

534 ExtRem = Builder.CreateURem(ExtDividend, ExtDivisor);

535 }

536 Trunc = Builder.CreateTrunc(ExtRem, RemTy);

537

541

543}

544

545

546

547

548

549

550

553 Div->getOpcode() == Instruction::UDiv) &&

554 "Trying to expand division from a non-division function");

555

557 assert(!DivTy->isVectorTy() && "Div over vectors not supported");

558

560

561 assert(DivTyBitWidth <= 32 && "Div of bitwidth greater than 32 not supported");

562

563 if (DivTyBitWidth == 32)

565

566

567

569

570 Value *ExtDividend;

571 Value *ExtDivisor;

575

576 if (Div->getOpcode() == Instruction::SDiv) {

579 ExtDiv = Builder.CreateSDiv(ExtDividend, ExtDivisor);

580 } else {

583 ExtDiv = Builder.CreateUDiv(ExtDividend, ExtDivisor);

584 }

585 Trunc = Builder.CreateTrunc(ExtDiv, DivTy);

586

590

592}

593

594

595

596

597

598

601 Div->getOpcode() == Instruction::UDiv) &&

602 "Trying to expand division from a non-division function");

603

605 assert(!DivTy->isVectorTy() && "Div over vectors not supported");

606

608

609 if (DivTyBitWidth >= 64)

611

612

613

615

616 Value *ExtDividend;

617 Value *ExtDivisor;

621

622 if (Div->getOpcode() == Instruction::SDiv) {

623 ExtDividend = Builder.CreateSExt(Div->getOperand(0), Int64Ty);

624 ExtDivisor = Builder.CreateSExt(Div->getOperand(1), Int64Ty);

625 ExtDiv = Builder.CreateSDiv(ExtDividend, ExtDivisor);

626 } else {

627 ExtDividend = Builder.CreateZExt(Div->getOperand(0), Int64Ty);

628 ExtDivisor = Builder.CreateZExt(Div->getOperand(1), Int64Ty);

629 ExtDiv = Builder.CreateUDiv(ExtDividend, ExtDivisor);

630 }

631 Trunc = Builder.CreateTrunc(ExtDiv, DivTy);

632

636

638}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static Value * generateSignedDivisionCode(Value *Dividend, Value *Divisor, IRBuilder<> &Builder)

Generate code to divide two signed integers.

Definition IntegerDivision.cpp:99

static Value * generateUnsignedRemainderCode(Value *Dividend, Value *Divisor, IRBuilder<> &Builder)

Generate code to compute the remainder of two unsigned integers.

Definition IntegerDivision.cpp:73

static Value * generateSignedRemainderCode(Value *Dividend, Value *Divisor, IRBuilder<> &Builder)

Generate code to compute the remainder of two signed integers.

Definition IntegerDivision.cpp:32

static Value * generateUnsignedDivisionCode(Value *Dividend, Value *Divisor, IRBuilder<> &Builder)

Generates code to divide two unsigned scalar 32-bit or 64-bit integers.

Definition IntegerDivision.cpp:141

LLVM Basic Block Representation.

iterator begin()

Instruction iterator methods.

const Function * getParent() const

Return the enclosing method, or null if none.

static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)

Creates a new BasicBlock.

LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)

Split the basic block into two basic blocks at the specified instruction.

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

BinaryOps getOpcode() const

This is the shared class of boolean and integer constants.

static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)

static ConstantInt * getSigned(IntegerType *Ty, int64_t V)

Return a ConstantInt with the specified value for the specified type.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

LLVM_ABI InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

Class to represent integer types.

unsigned getBitWidth() const

Get the number of bits in this IntegerType.

void addIncoming(Value *V, BasicBlock *BB)

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

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

The instances of the Type class are immutable: once they are created, they are never changed.

static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)

LLVM_ABI unsigned getIntegerBitWidth() const

bool isVectorTy() const

True if this is an instance of VectorType.

void dropAllReferences()

Drop all references to operands.

Value * getOperand(unsigned i) const

LLVM Value Representation.

Type * getType() const

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

LLVM_ABI void setName(const Twine &Name)

Change the name of the value.

LLVM_ABI void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

self_iterator getIterator()

LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})

Look up the Function declaration of the intrinsic id in the Module M.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI bool expandDivision(BinaryOperator *Div)

Generate code to divide two integers, replacing Div with the generated code.

Definition IntegerDivision.cpp:406

LLVM_ABI bool expandRemainderUpTo32Bits(BinaryOperator *Rem)

Generate code to calculate the remainder of two integers, replacing Rem with the generated code.

Definition IntegerDivision.cpp:455

decltype(auto) dyn_cast(const From &Val)

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

FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty

LLVM_ABI bool expandRemainderUpTo64Bits(BinaryOperator *Rem)

Generate code to calculate the remainder of two integers, replacing Rem with the generated code.

Definition IntegerDivision.cpp:504

LLVM_ABI bool expandDivisionUpTo64Bits(BinaryOperator *Div)

Generate code to divide two integers, replacing Div with the generated code.

Definition IntegerDivision.cpp:599

LLVM_ABI bool expandDivisionUpTo32Bits(BinaryOperator *Div)

Generate code to divide two integers, replacing Div with the generated code.

Definition IntegerDivision.cpp:551

constexpr unsigned BitWidth

decltype(auto) cast(const From &Val)

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

LLVM_ABI bool expandRemainder(BinaryOperator *Rem)

Generate code to calculate the remainder of two integers, replacing Rem with the generated code.

Definition IntegerDivision.cpp:354