LLVM: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

25

26using namespace llvm;

28

29#define DEBUG_TYPE "instcombine"

30

31namespace llvm {

33}

34

35

36

37

38

43 return TorF;

44 return Builder.CreateICmp(NewPred, LHS, RHS);

45}

46

47

48

53 return TorF;

54 return Builder.CreateFCmpFMF(NewPred, LHS, RHS, FMF);

55}

56

57

58

59

62 bool Inside) {

64 "Lo is not < Hi in range emission code!");

65

66 Type *Ty = V->getType();

67

68

69

71 if (isSigned ? Lo.isMinSignedValue() : Lo.isMinValue()) {

73 return Builder.CreateICmp(Pred, V, ConstantInt::get(Ty, Hi));

74 }

75

76

77

79 Builder.CreateSub(V, ConstantInt::get(Ty, Lo), V->getName() + ".off");

80 Constant *HiMinusLo = ConstantInt::get(Ty, Hi - Lo);

81 return Builder.CreateICmp(Pred, VMinusLo, HiMinusLo);

82}

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

123

124

125

128 const APInt *ConstA = nullptr, *ConstB = nullptr, *ConstC = nullptr;

133 bool IsAPow2 = ConstA && ConstA->isPowerOf2();

134 bool IsBPow2 = ConstB && ConstB->isPowerOf2();

135 unsigned MaskVal = 0;

136 if (ConstC && ConstC->isZero()) {

137

140 if (IsAPow2)

143 if (IsBPow2)

146 return MaskVal;

147 }

148

149 if (A == C) {

152 if (IsAPow2)

155 } else if (ConstA && ConstC && ConstC->isSubsetOf(*ConstA)) {

157 }

158

159 if (B == C) {

162 if (IsBPow2)

165 } else if (ConstB && ConstC && ConstC->isSubsetOf(*ConstB)) {

167 }

168

169 return MaskVal;

170}

171

172

173

174

175

177 unsigned NewMask;

180 << 1;

181

184 >> 1;

185

186 return NewMask;

187}

188

189

193 true);

194 if (!Res)

195 return false;

196

197 Pred = Res->Pred;

198 X = Res->X;

199 Y = ConstantInt::get(X->getType(), Res->Mask);

200 Z = ConstantInt::get(X->getType(), Res->C);

201 return true;

202}

203

204

205

206

207

208

209static std::optional<std::pair<unsigned, unsigned>>

213

214

215

216

217

218

219

220

221

222 Value *L1, *L11, *L12, *L2, *L21, *L22;

224 L21 = L22 = L1 = nullptr;

225 } else {

227 if (!LHSCMP)

228 return std::nullopt;

229

230

231 if (!LHSCMP->getOperand(0)->getType()->isIntOrIntVectorTy())

232 return std::nullopt;

233

234 PredL = LHSCMP->getPredicate();

235 L1 = LHSCMP->getOperand(0);

236 L2 = LHSCMP->getOperand(1);

237

239

240

241 L11 = L1;

243 }

244

246 L21 = L2;

248 }

249 }

250

251

253 return std::nullopt;

254

257 if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {

258 A = R11;

259 D = R12;

260 } else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {

261 A = R12;

262 D = R11;

263 } else {

264 return std::nullopt;

265 }

267 } else {

269 if (!RHSCMP)

270 return std::nullopt;

271

272 if (!RHSCMP->getOperand(0)->getType()->isIntOrIntVectorTy())

273 return std::nullopt;

274

275 PredR = RHSCMP->getPredicate();

276

277 Value *R1 = RHSCMP->getOperand(0);

278 R2 = RHSCMP->getOperand(1);

279 bool Ok = false;

281

282

283 R11 = R1;

285 }

286

287 if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {

288 A = R11;

289 D = R12;

291 Ok = true;

292 } else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {

293 A = R12;

294 D = R11;

296 Ok = true;

297 }

298

299

301 Ok = false;

302

303

304 if (!Ok) {

306 R11 = R2;

308 }

309

310 if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {

311 A = R11;

312 D = R12;

313 E = R1;

314 } else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {

315 A = R12;

316 D = R11;

317 E = R1;

318 } else {

319 return std::nullopt;

320 }

321 }

322 }

323

324

326 return std::nullopt;

327

328 if (L11 == A) {

329 B = L12;

330 C = L2;

331 } else if (L12 == A) {

332 B = L11;

333 C = L2;

334 } else if (L21 == A) {

335 B = L22;

336 C = L1;

337 } else if (L22 == A) {

338 B = L21;

339 C = L1;

340 }

341

344 return std::optional<std::pair<unsigned, unsigned>>(

345 std::make_pair(LeftType, RightType));

346}

347

348

349

350

351

352

357

358

359

360

361

362

363

364

365

366

367 const APInt *BCst, *DCst, *OrigECst;

370 return nullptr;

371

373

374

375

376

377

378 APInt ECst = *OrigECst;

379 if (PredR != NewCC)

380 ECst ^= *DCst;

381

382

383

384 if (*BCst == 0 || *DCst == 0)

385 return nullptr;

386

387

388

389

390

394 !Builder.GetInsertBlock()->getParent()->hasFnAttribute(

395 Attribute::StrictFP)) {

397 if (!Ty->isIEEELikeFPTy())

398 return nullptr;

399

401 if (ECst != ExpBits)

402 return nullptr;

403 APInt FractionBits = ~ExpBits;

405 if (*BCst != FractionBits)

406 return nullptr;

407

410 }

411 return nullptr;

412 }

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430 if ((((*BCst & *DCst) & ECst) == 0) &&

431 (*BCst & (*BCst ^ *DCst)).isPowerOf2()) {

432 APInt BorD = *BCst | *DCst;

433 APInt BandBxorDorE = (*BCst & (*BCst ^ *DCst)) | ECst;

434 Value *NewMask = ConstantInt::get(A->getType(), BorD);

435 Value *NewMaskedValue = ConstantInt::get(A->getType(), BandBxorDorE);

436 Value *NewAnd = Builder.CreateAnd(A, NewMask);

437 return Builder.CreateICmp(NewCC, NewAnd, NewMaskedValue);

438 }

439

440 auto IsSubSetOrEqual = [](const APInt *C1, const APInt *C2) {

441 return (*C1 & *C2) == *C1;

442 };

443 auto IsSuperSetOrEqual = [](const APInt *C1, const APInt *C2) {

444 return (*C1 & *C2) == *C2;

445 };

446

447

448

449

450

451

452

453 if (!IsSubSetOrEqual(BCst, DCst) && !IsSuperSetOrEqual(BCst, DCst))

454 return nullptr;

455

456

457

458

459

460

461

462

463

465 if (IsSubSetOrEqual(BCst, DCst))

466 return ConstantInt::get(LHS->getType(), !IsAnd);

467 return nullptr;

468 }

469

470

471

472

473

474

475

476 if (IsSuperSetOrEqual(BCst, DCst)) {

477

479 ICmp->setSameSign(false);

480 return RHS;

481 }

482

483

484

485 assert(IsSubSetOrEqual(BCst, DCst) && "Precondition due to above code");

486 if ((*BCst & ECst) != 0) {

487

489 ICmp->setSameSign(false);

490 return RHS;

491 }

492

493

494

495

496 return ConstantInt::get(LHS->getType(), !IsAnd);

497}

498

499

500

501

502

508 "Expected equality predicates for masked type of icmps.");

509

510

511

512

513

514 if (!IsAnd) {

517 }

520 LHS, RHS, IsAnd, A, B, D, E, PredL, PredR, Builder)) {

521 return V;

522 }

525 RHS, LHS, IsAnd, A, D, B, C, PredR, PredL, Builder)) {

526 return V;

527 }

528 }

529 return nullptr;

530}

531

532

533

535 bool IsLogical,

538 Value *A = nullptr, *B = nullptr, *C = nullptr, *D = nullptr, *E = nullptr;

540 std::optional<std::pair<unsigned, unsigned>> MaskPair =

542 if (!MaskPair)

543 return nullptr;

545 "Expected equality predicates for masked type of icmps.");

546 unsigned LHSMask = MaskPair->first;

547 unsigned RHSMask = MaskPair->second;

548 unsigned Mask = LHSMask & RHSMask;

549 if (Mask == 0) {

550

551

553 LHS, RHS, IsAnd, A, B, C, D, E, PredL, PredR, LHSMask, RHSMask,

554 Builder))

555 return V;

556 return nullptr;

557 }

558

559

560

561

562

563

564

565

566

567

568

569

570

572 if (!IsAnd) {

573

574

576 }

577

579

580

582 return nullptr;

583 Value *NewOr = Builder.CreateOr(B, D);

584 Value *NewAnd = Builder.CreateAnd(A, NewOr);

585

586

587

589 return Builder.CreateICmp(NewCC, NewAnd, Zero);

590 }

592

593

595 return nullptr;

596 Value *NewOr = Builder.CreateOr(B, D);

597 Value *NewAnd = Builder.CreateAnd(A, NewOr);

598 return Builder.CreateICmp(NewCC, NewAnd, NewOr);

599 }

601

602

604 return nullptr;

605 Value *NewAnd1 = Builder.CreateAnd(B, D);

606 Value *NewAnd2 = Builder.CreateAnd(A, NewAnd1);

607 return Builder.CreateICmp(NewCC, NewAnd2, A);

608 }

609

610 const APInt *ConstB, *ConstD;

613

614

615

616

617

618 APInt NewMask = *ConstB & *ConstD;

619 if (NewMask == *ConstB)

620 return LHS;

621 if (NewMask == *ConstD) {

622 if (IsLogical) {

624 RHSI->dropPoisonGeneratingFlags();

625 }

626 return RHS;

627 }

628 }

629

631

632

633

634

635 APInt NewMask = *ConstB | *ConstD;

636 if (NewMask == *ConstB)

637 return LHS;

638 if (NewMask == *ConstD)

639 return RHS;

640 }

641

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665 const APInt *OldConstC, *OldConstE;

667 return nullptr;

668

671 const APInt ConstC = PredL != CC ? *ConstB ^ *OldConstC : *OldConstC;

672 const APInt ConstE = PredR != CC ? *ConstD ^ *OldConstE : *OldConstE;

673

674 if (((*ConstB & *ConstD) & (ConstC ^ ConstE)).getBoolValue())

675 return IsNot ? nullptr : ConstantInt::get(LHS->getType(), !IsAnd);

676

677 if (IsNot && !ConstB->isSubsetOf(*ConstD) &&

678 !ConstD->isSubsetOf(*ConstB))

679 return nullptr;

680

682 if (IsNot) {

683 BD = *ConstB & *ConstD;

684 CE = ConstC & ConstE;

685 } else {

686 BD = *ConstB | *ConstD;

687 CE = ConstC | ConstE;

688 }

689 Value *NewAnd = Builder.CreateAnd(A, BD);

690 Value *CEVal = ConstantInt::get(A->getType(), CE);

691 return Builder.CreateICmp(CC, NewAnd, CEVal);

692 };

693

695 return FoldBMixed(NewCC, false);

697 return FoldBMixed(NewCC, true);

698 }

699 }

700

701

702

703

704

705

709

710

711 if (IsLogical)

712 D = Builder.CreateFreeze(D);

713 Value *Mask = Builder.CreateOr(B, D);

715 return Builder.CreateICmp(NewCC, Masked, Mask);

716 }

717 return nullptr;

718}

719

720

721

722

723

725 bool Inverted) {

726

727

729 if (!RangeStart)

730 return nullptr;

731

734

735

738 return nullptr;

739

742

748

750 RangeEnd = Cmp1Op1;

752

754 RangeEnd = Cmp1Op0;

756 } else {

757 return nullptr;

758 }

759

760

762 switch (Pred1) {

765 default: return nullptr;

766 }

767

768

771 return nullptr;

772

773 if (Inverted)

775

776 return Builder.CreateICmp(NewPred, Input, RangeEnd);

777}

778

779

780

781

782

788

789 if (LHS->getPredicate() != Pred || RHS->getPredicate() != Pred)

790 return nullptr;

791

792

793

796

798

799

800

801

802

803

804

805

806

811 return nullptr;

812

813 Value *And = Builder.CreateAnd(Op, Pow2);

814 return Builder.CreateICmp(Pred, And, Op);

815}

816

817

818

819

820

821

822

823

824

825

826

827

828

829

830

831

832

833

834

835

836

837

838

839

840

841

842

843

844

845

846

851

852

853 auto tryToMatchSignedTruncationCheck = [](ICmpInst *ICmp, Value *&X,

854 APInt &SignBitMask) -> bool {

855 const APInt *I01, *I1;

859 I1->ugt(*I01) && I01->shl(1) == *I1))

860 return false;

861

862 SignBitMask = *I01;

863 return true;

864 };

865

866

867

869 APInt HighestBit;

871 if (tryToMatchSignedTruncationCheck(ICmp1, X1, HighestBit))

872 OtherICmp = ICmp0;

873 else if (tryToMatchSignedTruncationCheck(ICmp0, X1, HighestBit))

874 OtherICmp = ICmp1;

875 else

876 return nullptr;

877

878 assert(HighestBit.isPowerOf2() && "expected to be power of two (non-zero)");

879

880

882 APInt &UnsetBitsMask) -> bool {

884

887 false, false,

888 true);

890 X = Res->X;

891 UnsetBitsMask = Res->Mask;

892 return true;

893 }

894

895 return false;

896 };

897

898

900 APInt UnsetBitsMask;

901 if (!tryToDecompose(OtherICmp, X0, UnsetBitsMask))

902 return nullptr;

903

904 assert(!UnsetBitsMask.isZero() && "empty mask makes no sense.");

905

906

908 if (X1 == X0) {

909

910 X = X1;

913 X = X1;

914 } else

915 return nullptr;

916

917

918

919 APInt SignBitsMask = ~(HighestBit - 1U);

920

921

922 if (!UnsetBitsMask.intersects(SignBitsMask))

923 return nullptr;

924

925

926 if (!UnsetBitsMask.isSubsetOf(SignBitsMask)) {

927 APInt OtherHighestBit = (~UnsetBitsMask) + 1U;

929 return nullptr;

930 HighestBit = APIntOps::umin(HighestBit, OtherHighestBit);

931 }

932

933

934

935 return Builder.CreateICmpULT(X, ConstantInt::get(X->getType(), HighestBit),

936 CxtI.getName() + ".simplified");

937}

938

939

940

941

942

951 return nullptr;

952

955

956 CtPop->dropPoisonGeneratingAnnotations();

958 return Builder.CreateICmpUGT(CtPop, ConstantInt::get(CtPop->getType(), 1));

959 }

961

962 CtPop->dropPoisonGeneratingAnnotations();

964 return Builder.CreateICmpULT(CtPop, ConstantInt::get(CtPop->getType(), 2));

965 }

966

967 return nullptr;

968}

969

970

971

972

976

981

982

984 if (JoinedByAnd &&

990

991 CtPop->dropPoisonGeneratingAnnotations();

993 return Builder.CreateICmpEQ(CtPop, ConstantInt::get(CtPop->getType(), 1));

994 }

995

996 if (!JoinedByAnd &&

1002

1003 CtPop->dropPoisonGeneratingAnnotations();

1005 return Builder.CreateICmpNE(CtPop, ConstantInt::get(CtPop->getType(), 1));

1006 }

1007 return nullptr;

1008}

1009

1010

1011

1012

1013

1014

1019 "Expected equality predicates for masked type of icmps.");

1021 return nullptr;

1022

1025 return nullptr;

1026

1027

1028

1029

1030

1031

1032

1033

1034

1035

1036

1037

1038 auto isReducible = [](const Value *B, const Value *D, const Value *E) {

1039 const APInt *BCst, *DCst, *ECst;

1044 };

1045

1046

1052

1053 if (!BFVTy || !BConst || !DConst || !EConst)

1054 return nullptr;

1055

1056 for (unsigned I = 0; I != BFVTy->getNumElements(); ++I) {

1057 const auto *BElt = BConst->getAggregateElement(I);

1058 const auto *DElt = DConst->getAggregateElement(I);

1059 const auto *EElt = EConst->getAggregateElement(I);

1060

1061 if (!BElt || !DElt || !EElt)

1062 return nullptr;

1063 if (!isReducible(BElt, DElt, EElt))

1064 return nullptr;

1065 }

1066 } else {

1067

1068 if (!isReducible(B, D, E))

1069 return nullptr;

1070 }

1072}

1073

1074

1075

1076

1077

1078

1079

1080

1082 bool JoinedByAnd,

1084 if (!JoinedByAnd)

1085 return nullptr;

1086 Value *A = nullptr, *B = nullptr, *C = nullptr, *D = nullptr, *E = nullptr;

1088

1089

1090

1091 std::optional<std::pair<unsigned, unsigned>> MaskPair =

1093 if (!MaskPair)

1094 return nullptr;

1095

1097 unsigned CmpMask0 = MaskPair->first;

1098 unsigned CmpMask1 = MaskPair->second;

1099 if ((CmpMask0 & Mask_AllZeros) && (CmpMask1 == compareBMask)) {

1101 CmpPred1, Builder))

1102 return V;

1103 } else if ((CmpMask0 == compareBMask) && (CmpMask1 & Mask_AllZeros)) {

1105 CmpPred0, Builder))

1106 return V;

1107 }

1108 return nullptr;

1109}

1110

1111

1112

1114 ICmpInst *UnsignedICmp, bool IsAnd,

1117 Value *ZeroCmpOp;

1121 return nullptr;

1122

1124

1126 if (match(UnsignedICmp,

1130 auto GetKnownNonZeroAndOther = [&](Value *&NonZero, Value *&Other) {

1134 };

1135

1136

1137

1138

1139

1140

1142 IsAnd && GetKnownNonZeroAndOther(B, A))

1143 return Builder.CreateICmpULT(Builder.CreateNeg(B), A);

1145 !IsAnd && GetKnownNonZeroAndOther(B, A))

1146 return Builder.CreateICmpUGE(Builder.CreateNeg(B), A);

1147 }

1148

1149 return nullptr;

1150}

1151

1157

1158

1162 return std::nullopt;

1163

1164 unsigned NumOriginalBits = X->getType()->getScalarSizeInBits();

1165 unsigned NumExtractedBits = V->getType()->getScalarSizeInBits();

1167 const APInt *Shift;

1168

1169

1171 Shift->ule(NumOriginalBits - NumExtractedBits))

1173 return {{X, 0, NumExtractedBits}};

1174}

1175

1176

1179 if (P.StartBit)

1180 V = Builder.CreateLShr(V, P.StartBit);

1182 if (TruncTy != V->getType())

1183 V = Builder.CreateTrunc(V, TruncTy);

1184 return V;

1185}

1186

1187

1188

1189

1190Value *InstCombinerImpl::foldEqOfParts(Value *Cmp0, Value *Cmp1, bool IsAnd) {

1192 return nullptr;

1193

1195 auto GetMatchPart = [&](Value *CmpV,

1196 unsigned OpNo) -> std::optional {

1198

1200

1201

1205 return {{OpNo == 0 ? X : Y, 0, 1}};

1206

1208 if (!Cmp)

1209 return std::nullopt;

1210

1211 if (Pred == Cmp->getPredicate())

1213

1214 const APInt *C;

1215

1216

1220 return std::nullopt;

1221 }

1222

1223

1224

1229 return std::nullopt;

1230 } else {

1231 return std::nullopt;

1232 }

1233

1234 unsigned From = Pred == CmpInst::ICMP_NE ? C->popcount() : C->countr_zero();

1236 return {{I->getOperand(OpNo), From, C->getBitWidth() - From}};

1237 };

1238

1239 std::optional L0 = GetMatchPart(Cmp0, 0);

1240 std::optional R0 = GetMatchPart(Cmp0, 1);

1241 std::optional L1 = GetMatchPart(Cmp1, 0);

1242 std::optional R1 = GetMatchPart(Cmp1, 1);

1243 if (!L0 || !R0 || !L1 || !R1)

1244 return nullptr;

1245

1246

1247

1248 if (L0->From != L1->From || R0->From != R1->From) {

1249 if (L0->From != R1->From || R0->From != L1->From)

1250 return nullptr;

1252 }

1253

1254

1255

1256 if (L0->StartBit + L0->NumBits != L1->StartBit ||

1257 R0->StartBit + R0->NumBits != R1->StartBit) {

1258 if (L1->StartBit + L1->NumBits != L0->StartBit ||

1259 R1->StartBit + R1->NumBits != R0->StartBit)

1260 return nullptr;

1263 }

1264

1265

1266 IntPart L = {L0->From, L0->StartBit, L0->NumBits + L1->NumBits};

1267 IntPart R = {R0->From, R0->StartBit, R0->NumBits + R1->NumBits};

1271}

1272

1273

1274

1275

1277 bool IsAnd, bool IsLogical,

1281

1282

1288 return nullptr;

1291 return nullptr;

1292

1293

1294

1295

1299 return nullptr;

1300

1301

1302

1303

1304

1305

1307 if (!SubstituteCmp) {

1308

1309

1311 return nullptr;

1312 SubstituteCmp = Builder.CreateICmp(Pred1, Y, C);

1313 }

1314 if (IsLogical) {

1317 return IsAnd ? Builder.CreateLogicalAnd(Cmp0, SubstituteCmp, "", MDFrom)

1318 : Builder.CreateLogicalOr(Cmp0, SubstituteCmp, "", MDFrom);

1319 }

1320 return Builder.CreateBinOp(IsAnd ? Instruction::And : Instruction::Or, Cmp0,

1321 SubstituteCmp);

1322}

1323

1324

1325

1326

1327

1328Value *InstCombinerImpl::foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1,

1330 bool IsAnd) {

1331

1332 auto MatchExactRangeCheck =

1333 [](ICmpInst *ICmp) -> std::optional<std::pair<Value *, ConstantRange>> {

1334 const APInt *C;

1336 return std::nullopt;

1337 Value *LHS = ICmp->getOperand(0);

1338 CmpPredicate Pred = ICmp->getPredicate();

1340

1341 const APInt *Mask;

1344 C->countr_zero() >= Mask->countr_zero()) {

1345 ConstantRange CR(*C, *C - *Mask);

1347 CR = CR.inverse();

1348 return std::make_pair(X, CR);

1349 }

1351

1352

1353 const APInt *C1;

1355 return std::make_pair(X, CR.subtract(*C1));

1356 return std::make_pair(LHS, CR);

1357 };

1358

1359 auto RC1 = MatchExactRangeCheck(ICmp1);

1360 if (!RC1)

1361 return nullptr;

1362

1363 auto RC2 = MatchExactRangeCheck(ICmp2);

1364 if (!RC2)

1365 return nullptr;

1366

1367 auto &[V1, CR1] = *RC1;

1368 auto &[V2, CR2] = *RC2;

1369 if (V1 != V2)

1370 return nullptr;

1371

1372

1373 if (IsAnd) {

1374 CR1 = CR1.inverse();

1375 CR2 = CR2.inverse();

1376 }

1377

1378 Type *Ty = V1->getType();

1379 Value *NewV = V1;

1380 std::optional CR = CR1.exactUnionWith(CR2);

1381 if (!CR) {

1382 if (!(ICmp1->hasOneUse() && ICmp2->hasOneUse()) || CR1.isWrappedSet() ||

1383 CR2.isWrappedSet())

1384 return nullptr;

1385

1386

1387

1388 APInt LowerDiff = CR1.getLower() ^ CR2.getLower();

1389 APInt UpperDiff = (CR1.getUpper() - 1) ^ (CR2.getUpper() - 1);

1390 APInt CR1Size = CR1.getUpper() - CR1.getLower();

1391 if (!LowerDiff.isPowerOf2() || LowerDiff != UpperDiff ||

1392 CR1Size != CR2.getUpper() - CR2.getLower())

1393 return nullptr;

1394

1395 CR = CR1.getLower().ult(CR2.getLower()) ? CR1 : CR2;

1396 NewV = Builder.CreateAnd(NewV, ConstantInt::get(Ty, ~LowerDiff));

1397 }

1398

1399 if (IsAnd)

1400 CR = CR->inverse();

1401

1404 CR->getEquivalentICmp(NewPred, NewC, Offset);

1405

1407 NewV = Builder.CreateAdd(NewV, ConstantInt::get(Ty, Offset));

1408 return Builder.CreateICmp(NewPred, NewV, ConstantInt::get(Ty, NewC));

1409}

1410

1411

1412

1419

1420

1424

1425

1430

1431

1432

1433

1436 Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);

1437 Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);

1439

1442 return nullptr;

1443

1446}

1447

1449 bool IsAnd, bool IsLogicalSelect) {

1450 Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);

1451 Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);

1453

1454 if (LHS0 == RHS1 && RHS0 == LHS1) {

1455

1458 }

1459

1460

1461

1462

1463

1464

1465

1466

1467

1468

1469

1470

1471

1472

1473

1474 if (LHS0 == RHS0 && LHS1 == RHS1) {

1475 unsigned FCmpCodeL = getFCmpCode(PredL);

1476 unsigned FCmpCodeR = getFCmpCode(PredR);

1477 unsigned NewPred = IsAnd ? FCmpCodeL & FCmpCodeR : FCmpCodeL | FCmpCodeR;

1478

1479

1480

1483 }

1484

1485

1486 if (!IsLogicalSelect &&

1489 !IsAnd))) {

1491 return nullptr;

1492

1493

1494

1496

1497

1498

1499 return Builder.CreateFCmpFMF(PredL, LHS0, RHS0,

1501 }

1502 }

1503

1504

1505 if (!IsLogicalSelect && IsAnd &&

1507

1508

1510 return Left;

1513 }

1514

1515

1516

1517

1518

1519

1521 auto [ClassValRHS, ClassMaskRHS] =

1523 if (ClassValRHS) {

1524 auto [ClassValLHS, ClassMaskLHS] =

1526 if (ClassValLHS == ClassValRHS) {

1527 unsigned CombinedMask = IsAnd ? (ClassMaskLHS & ClassMaskRHS)

1528 : (ClassMaskLHS | ClassMaskRHS);

1529 return Builder.CreateIntrinsic(

1530 Intrinsic::is_fpclass, {ClassValLHS->getType()},

1531 {ClassValLHS, Builder.getInt32(CombinedMask)});

1532 }

1533 }

1534 }

1535

1536

1537

1538

1539

1540

1541

1542 const APFloat *LHSC, *RHSC;

1549 switch (Pred) {

1554 return true;

1555 default:

1556 return false;

1557 }

1558 };

1559 if (IsLessThanOrLessEqual(IsAnd ? PredR : PredL)) {

1562 }

1563 if (IsLessThanOrLessEqual(IsAnd ? PredL : PredR)) {

1564 FastMathFlags NewFlag = LHS->getFastMathFlags();

1565 if (!IsLogicalSelect)

1566 NewFlag |= RHS->getFastMathFlags();

1567

1569 Builder.CreateUnaryIntrinsic(Intrinsic::fabs, LHS0, NewFlag);

1570 return Builder.CreateFCmpFMF(

1571 PredL, FAbs, ConstantFP::get(LHS0->getType(), *LHSC), NewFlag);

1572 }

1573 }

1574

1575 return nullptr;

1576}

1577

1578

1579

1583 if (!FCmp || !FCmp->hasOneUse())

1584 return false;

1585

1586 std::tie(ClassVal, ClassMask) =

1587 fcmpToClassTest(FCmp->getPredicate(), *FCmp->getParent()->getParent(),

1588 FCmp->getOperand(0), FCmp->getOperand(1));

1589 return ClassVal != nullptr;

1590}

1591

1592

1593

1594

1595

1596

1597

1600 Value *ClassVal0 = nullptr;

1601 Value *ClassVal1 = nullptr;

1602 uint64_t ClassMask0, ClassMask1;

1603

1604

1605

1606

1607

1608

1609

1610 bool IsLHSClass =

1613 bool IsRHSClass =

1618 ClassVal0 == ClassVal1) {

1619 unsigned NewClassMask;

1621 case Instruction::And:

1622 NewClassMask = ClassMask0 & ClassMask1;

1623 break;

1624 case Instruction::Or:

1625 NewClassMask = ClassMask0 | ClassMask1;

1626 break;

1627 case Instruction::Xor:

1628 NewClassMask = ClassMask0 ^ ClassMask1;

1629 break;

1630 default:

1632 }

1633

1634 if (IsLHSClass) {

1636 II->setArgOperand(

1637 1, ConstantInt::get(II->getArgOperand(1)->getType(), NewClassMask));

1639 }

1640

1641 if (IsRHSClass) {

1643 II->setArgOperand(

1644 1, ConstantInt::get(II->getArgOperand(1)->getType(), NewClassMask));

1646 }

1647

1648 CallInst *NewClass =

1649 Builder.CreateIntrinsic(Intrinsic::is_fpclass, {ClassVal0->getType()},

1650 {ClassVal0, Builder.getInt32(NewClassMask)});

1652 }

1653

1654 return nullptr;

1655}

1656

1657

1658

1659

1660

1661

1662

1663

1664Instruction *InstCombinerImpl::canonicalizeConditionalNegationViaMathToSelect(

1666 assert(I.getOpcode() == BinaryOperator::Xor && "Only for xor!");

1668

1671 Cond->getType()->isIntOrIntVectorTy(1) ||

1673 return nullptr;

1675 X);

1676}

1677

1678

1679

1680

1681

1685 assert((Opcode == Instruction::And || Opcode == Instruction::Or) &&

1686 "Expecting and/or op for fcmp transform");

1687

1688

1689

1693

1694

1695 Value *BO10, *BO11;

1700 return nullptr;

1701

1702

1705 X->getType() != Y->getType())

1707

1709 X->getType() != Y->getType())

1710 return nullptr;

1711

1712

1713

1714

1715 Value *NewFCmp =

1718}

1719

1720

1721

1722

1726 assert((Opcode == Instruction::And || Opcode == Instruction::Or) &&

1727 "Trying to match De Morgan's Laws with something other than and/or");

1728

1729

1731 (Opcode == Instruction::And) ? Instruction::Or : Instruction::And;

1732

1733 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);

1742 }

1743

1744

1745

1746

1747

1748

1754 }

1755

1756 return nullptr;

1757}

1758

1759bool InstCombinerImpl::shouldOptimizeCast(CastInst *CI) {

1761

1762

1764 return false;

1765

1766

1767

1769 if (isEliminableCastPair(PrecedingCI, CI))

1770 return false;

1771

1772 return true;

1773}

1774

1775

1779 if (C)

1780 return nullptr;

1781

1782 auto LogicOpc = Logic.getOpcode();

1785

1786

1787

1788

1789

1795

1797 auto *ZExt = new ZExtInst(NewOp, DestTy);

1798 ZExt->setNonNeg(Flags.NNeg);

1799 ZExt->andIRFlags(Cast);

1800 return ZExt;

1801 }

1802 }

1803

1806

1808 return new SExtInst(NewOp, DestTy);

1809 }

1810 }

1811

1812 return nullptr;

1813}

1814

1815

1818 assert(I.isBitwiseLogicOp() && "Unexpected opcode for bitwise logic folding");

1819

1820 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);

1821

1822

1823

1824

1825

1826 auto FoldBitwiseICmpZeroWithICmp = [&](Value *Op0,

1827 Value *Op1) -> Instruction * {

1829 bool IsMatched =

1835

1836 if (!IsMatched)

1837 return nullptr;

1838

1839 auto *ICmpL =

1842 auto *BitwiseOp = Builder.CreateBinOp(LogicOpc, ICmpL, ICmpR);

1843

1844 return new ZExtInst(BitwiseOp, Op0->getType());

1845 };

1846

1847 if (auto *Ret = FoldBitwiseICmpZeroWithICmp(Op0, Op1))

1848 return Ret;

1849

1850 if (auto *Ret = FoldBitwiseICmpZeroWithICmp(Op1, Op0))

1851 return Ret;

1852

1854 if (!Cast0)

1855 return nullptr;

1856

1857

1858

1859 Type *DestTy = I.getType();

1862 return nullptr;

1863

1865 return Ret;

1866

1868 if (!Cast1)

1869 return nullptr;

1870

1871

1872

1874 if (CastOpcode != Cast1->getOpcode())

1875 return nullptr;

1876

1877

1879 return nullptr;

1880

1884

1885 unsigned XNumBits = X->getType()->getScalarSizeInBits();

1886 unsigned YNumBits = Y->getType()->getScalarSizeInBits();

1887 if (XNumBits != YNumBits) {

1888

1889

1891 return nullptr;

1892

1893

1894

1895 if (XNumBits < YNumBits) {

1896 X = Builder.CreateCast(CastOpcode, X, Y->getType());

1897 } else if (YNumBits < XNumBits) {

1898 Y = Builder.CreateCast(CastOpcode, Y, X->getType());

1899 }

1900 }

1901

1902

1903 Value *NarrowLogic = Builder.CreateBinOp(LogicOpc, X, Y, I.getName());

1906 if (Disjoint && NewDisjoint)

1907 NewDisjoint->setIsDisjoint(Disjoint->isDisjoint());

1909 }

1910

1911

1912 if (SrcTy != Cast1->getSrcTy())

1913 return nullptr;

1914

1917

1918

1919 if (shouldOptimizeCast(Cast0) && shouldOptimizeCast(Cast1)) {

1920 Value *NewOp = Builder.CreateBinOp(LogicOpc, Cast0Src, Cast1Src,

1921 I.getName());

1923 }

1924

1925 return nullptr;

1926}

1927

1930 assert(I.getOpcode() == Instruction::And);

1931 Value *Op0 = I.getOperand(0);

1932 Value *Op1 = I.getOperand(1);

1934

1935

1936

1937

1940 return BinaryOperator::CreateXor(A, B);

1941

1942

1943

1944

1945

1950

1951 return nullptr;

1952}

1953

1956 assert(I.getOpcode() == Instruction::Or);

1957 Value *Op0 = I.getOperand(0);

1958 Value *Op1 = I.getOperand(1);

1960

1961

1962

1963

1968

1969

1970

1971

1976

1977

1978

1979

1980

1983 return BinaryOperator::CreateXor(A, B);

1984

1985 return nullptr;

1986}

1987

1988

1989

1991 APInt Threshold(C->getType()->getScalarSizeInBits(), BitWidth);

1993}

1994

1995

1996

1998

1999

2000

2001

2002

2003 Value *Op0 = And.getOperand(0), *Op1 = And.getOperand(1);

2010 return nullptr;

2011

2014 return nullptr;

2015

2016 Type *Ty = And.getType();

2017 if (isa<VectorType>(Ty) && !shouldChangeType(Ty, X->getType()))

2018 return nullptr;

2019

2020

2021

2022

2024 if (Opc == Instruction::LShr || Opc == Instruction::Shl)

2026 return nullptr;

2027

2028

2029

2031 Value *NewBO = Opc == Instruction::Sub ? Builder.CreateBinOp(Opc, NewC, X)

2033 return new ZExtInst(Builder.CreateAnd(NewBO, X), Ty);

2034}

2035

2036

2037

2041 assert(Opcode == Instruction::And || Opcode == Instruction::Or);

2042

2043

2045 (Opcode == Instruction::And) ? Instruction::Or : Instruction::And;

2046

2047 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);

2049

2050

2051

2052

2053

2054 const auto matchNotOrAnd =

2055 [Opcode, FlippedOpcode](Value *Op, auto m_A, auto m_B, auto m_C,

2056 Value *&X, bool CountUses = false) -> bool {

2057 if (CountUses && Op->hasOneUse())

2058 return false;

2059

2063 return !CountUses || X->hasOneUse();

2064

2065 return false;

2066 };

2067

2068

2069

2070

2071

2072

2074

2075

2077 true)) {

2078 Value *Xor = Builder.CreateXor(B, C);

2079 return (Opcode == Instruction::Or)

2080 ? BinaryOperator::CreateAnd(Xor, Builder.CreateNot(A))

2082 }

2083

2084

2085

2087 true)) {

2088 Value *Xor = Builder.CreateXor(A, C);

2089 return (Opcode == Instruction::Or)

2090 ? BinaryOperator::CreateAnd(Xor, Builder.CreateNot(B))

2092 }

2093

2094

2095

2099 Opcode, Builder.CreateBinOp(FlippedOpcode, B, C), A));

2100

2101

2102

2106 Opcode, Builder.CreateBinOp(FlippedOpcode, A, C), B));

2107

2108

2109

2110

2111

2112 if (Opcode == Instruction::Or && Op0->hasOneUse() &&

2117

2118

2121 }

2122 }

2123

2124

2125

2126

2127

2128

2137

2138

2139

2149 Value *Xor = Builder.CreateXor(B, C);

2150 return (Opcode == Instruction::Or)

2152 : BinaryOperator::CreateOr(Xor, X);

2153 }

2154

2155

2156

2160 FlippedOpcode, Builder.CreateBinOp(Opcode, C, Builder.CreateNot(B)),

2161 X);

2162

2163

2164

2168 FlippedOpcode, Builder.CreateBinOp(Opcode, B, Builder.CreateNot(C)),

2169 X);

2170 }

2171

2172 return nullptr;

2173}

2174

2175

2176

2177

2178

2187

2188 if (X->hasOneUse()) {

2189 Value *YZ = Builder.CreateBinOp(Opcode, Y, Z);

2191 }

2192

2193 if (Y->hasOneUse()) {

2194 Value *XZ = Builder.CreateBinOp(Opcode, X, Z);

2196 }

2197 }

2198 }

2199

2200 return nullptr;

2201}

2202

2203

2204

2205

2206

2207

2208

2209

2210

2211

2214 Type *Ty = I.getType();

2216 Value *Op0 = I.getOperand(0);

2217 Value *Op1 = I.getOperand(1);

2219 const APInt *C, *C2;

2220

2223 return nullptr;

2224

2225 unsigned Width = Ty->getScalarSizeInBits();

2226 unsigned LastOneMath = Width - C2->countr_zero();

2227

2228 switch (OpC) {

2229 case Instruction::And:

2230 if (C->countl_one() < LastOneMath)

2231 return nullptr;

2232 break;

2233 case Instruction::Xor:

2234 case Instruction::Or:

2235 if (C->countl_zero() < LastOneMath)

2236 return nullptr;

2237 break;

2238 default:

2240 }

2241

2242 Value *NewBinOp = Builder.CreateBinOp(OpC, X, ConstantInt::get(Ty, *C));

2244 ConstantInt::get(Ty, *C2), Op0);

2245}

2246

2247

2248

2249

2251 assert((I.isBitwiseLogicOp() || I.getOpcode() == Instruction::Add) &&

2252 "Unexpected opcode");

2253

2255 Constant *ShiftedC1, *ShiftedC2, *AddC;

2256 Type *Ty = I.getType();

2262 return nullptr;

2263

2264

2265 if (match(AddC,

2267 return nullptr;

2268

2269

2272 if (!Op0Inst || !Op1Inst)

2273 return nullptr;

2274

2275

2278 if (ShiftOp != Op1Inst->getOpcode())

2279 return nullptr;

2280

2281

2282 if (I.getOpcode() == Instruction::Add && ShiftOp != Instruction::Shl)

2283 return nullptr;

2284

2286 I.getOpcode(), ShiftedC1, Builder.CreateBinOp(ShiftOp, ShiftedC2, AddC));

2288}

2289

2290

2291

2292

2293

2294

2295

2296

2297

2298

2302 assert(I.isBitwiseLogicOp() && "Should and/or/xor");

2303 if (I.getOperand(0)->hasOneUse())

2304 return nullptr;

2306 if (X)

2307 return nullptr;

2308

2310 if (Y && (Y->hasOneUse() || X->getIntrinsicID() != Y->getIntrinsicID()))

2311 return nullptr;

2312

2314 const APInt *RHSC;

2315

2316 if (Y && (!(IID == Intrinsic::bswap || IID == Intrinsic::bitreverse) ||

2318 return nullptr;

2319

2320 switch (IID) {

2321 case Intrinsic::fshl:

2322 case Intrinsic::fshr: {

2323 if (X->getOperand(2) != Y->getOperand(2))

2324 return nullptr;

2326 Builder.CreateBinOp(I.getOpcode(), X->getOperand(0), Y->getOperand(0));

2328 Builder.CreateBinOp(I.getOpcode(), X->getOperand(1), Y->getOperand(1));

2332 }

2333 case Intrinsic::bswap:

2334 case Intrinsic::bitreverse: {

2335 Value *NewOp0 = Builder.CreateBinOp(

2336 I.getOpcode(), X->getOperand(0),

2337 Y ? Y->getOperand(0)

2338 : ConstantInt::get(I.getType(), IID == Intrinsic::bswap

2344 }

2345 default:

2346 return nullptr;

2347 }

2348}

2349

2350

2351

2352

2353

2354

2356 bool SimplifyOnly,

2358 unsigned Depth = 0) {

2359 if (Op == RepOp)

2360 return nullptr;

2361

2362 if (V == Op)

2363 return RepOp;

2364

2366 if (I || I->isBitwiseLogicOp() || Depth >= 3)

2367 return nullptr;

2368

2369 if (I->hasOneUse())

2370 SimplifyOnly = true;

2371

2373 SimplifyOnly, IC, Depth + 1);

2375 SimplifyOnly, IC, Depth + 1);

2376 if (!NewOp0 && !NewOp1)

2377 return nullptr;

2378

2379 if (!NewOp0)

2380 NewOp0 = I->getOperand(0);

2381 if (!NewOp1)

2382 NewOp1 = I->getOperand(1);

2383

2386 return Res;

2387

2388 if (SimplifyOnly)

2389 return nullptr;

2391}

2392

2393

2394

2395

2398 bool RHSIsLogical) {

2400

2401

2402 if (Value *Res = foldBooleanAndOr(LHS, X, I, IsAnd, false))

2403 return RHSIsLogical ? Builder.CreateLogicalOp(Opcode, Res, Y)

2404 : Builder.CreateBinOp(Opcode, Res, Y);

2405

2406

2407 if (Value *Res = foldBooleanAndOr(LHS, Y, I, IsAnd, false))

2408 return RHSIsLogical ? Builder.CreateLogicalOp(Opcode, X, Res)

2409 : Builder.CreateBinOp(Opcode, X, Res);

2410 return nullptr;

2411}

2412

2413

2414

2415

2417 Type *Ty = I.getType();

2418

2420 SQ.getWithInstruction(&I)))

2422

2424 return &I;

2425

2427 return X;

2428

2430 return Phi;

2431

2432

2433

2435 return &I;

2436

2437

2439 return Xor;

2440

2442 return X;

2443

2444

2447

2449 return R;

2450

2451 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);

2452

2458

2459

2460 Value *IsZero = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, 0));

2461 return new ZExtInst(IsZero, Ty);

2462 }

2463

2464

2471 }

2472

2473

2474

2479 return BinaryOperator::CreateAnd(Builder.CreateNot(X), Y);

2480

2482 const APInt *XorC;

2484

2485 Constant *NewC = ConstantInt::get(Ty, *C & *XorC);

2487 And->takeName(Op0);

2488 return BinaryOperator::CreateXor(And, NewC);

2489 }

2490

2491 const APInt *OrC;

2493

2494

2495

2496

2497

2498

2499 APInt Together = *C & *OrC;

2500 Value *And = Builder.CreateAnd(X, ConstantInt::get(Ty, Together ^ *C));

2501 And->takeName(Op0);

2502 return BinaryOperator::CreateOr(And, ConstantInt::get(Ty, Together));

2503 }

2504

2505 unsigned Width = Ty->getScalarSizeInBits();

2506 const APInt *ShiftC;

2508 ShiftC->ult(Width)) {

2510

2511

2513 Constant *ShAmtC = ConstantInt::get(Ty, ShiftC->zext(Width));

2514 return BinaryOperator::CreateLShr(Sext, ShAmtC);

2515 }

2516 }

2517

2518

2519

2522 return BinaryOperator::CreateLShr(X, ConstantInt::get(Ty, *ShiftC));

2523

2524 const APInt *AddC;

2526

2527

2528

2529

2530 if (Op0->hasOneUse() && C->isPowerOf2() && (*AddC & (*C - 1)) == 0) {

2531 assert((*C & *AddC) != 0 && "Expected common bit");

2533 return BinaryOperator::CreateXor(NewAnd, Op1);

2534 }

2535 }

2536

2537

2538

2540 switch (B->getOpcode()) {

2541 case Instruction::Xor:

2542 case Instruction::Or:

2543 case Instruction::Mul:

2544 case Instruction::Add:

2545 case Instruction::Sub:

2546 return true;

2547 default:

2548 return false;

2549 }

2550 };

2555 const APInt *C1;

2556

2557

2558

2559

2561 C->isIntN(X->getType()->getScalarSizeInBits())) {

2562 unsigned XWidth = X->getType()->getScalarSizeInBits();

2563 Constant *TruncC1 = ConstantInt::get(X->getType(), C1->trunc(XWidth));

2565 ? Builder.CreateBinOp(BOpcode, X, TruncC1)

2566 : Builder.CreateBinOp(BOpcode, TruncC1, X);

2567 Constant *TruncC = ConstantInt::get(X->getType(), C->trunc(XWidth));

2570 }

2571

2572

2573

2574

2577 C->isMask(X->getType()->getScalarSizeInBits())) {

2579 Value *TrY = Builder.CreateTrunc(Y, X->getType(), Y->getName() + ".tr");

2581 Builder.CreateBinOp(BOpcode, X, TrY, BO->getName() + ".narrow");

2582 return new ZExtInst(NewBO, Ty);

2583 }

2584

2587 C->isMask(X->getType()->getScalarSizeInBits())) {

2589 Value *TrY = Builder.CreateTrunc(Y, X->getType(), Y->getName() + ".tr");

2591 Builder.CreateBinOp(BOpcode, TrY, X, BO->getName() + ".narrow");

2592 return new ZExtInst(NewBO, Ty);

2593 }

2594 }

2595

2596

2597

2598

2601 APInt NotAndMask(~(*C));

2604

2605

2606 Value *NewRHS = Builder.CreateAnd(Y, Op1, Y->getName() + ".masked");

2608 }

2610

2611

2612 Value *NewLHS = Builder.CreateAnd(X, Op1, X->getName() + ".masked");

2614 }

2615 }

2616

2617

2618

2619

2620

2621 if (C->isPowerOf2() &&

2624 int Log2C = C->exactLogBase2();

2625 bool IsShiftLeft =

2627 int BitNum = IsShiftLeft ? Log2C - Log2ShiftC : Log2ShiftC - Log2C;

2628 assert(BitNum >= 0 && "Expected demanded bits to handle impossible mask");

2629 Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, BitNum));

2632 }

2633

2635 const APInt *C3 = C;

2646

2647

2652 }

2653 }

2654

2661 if (Cmp && Cmp->isZeroValue()) {

2662

2663

2669 }

2670 }

2671 }

2672 }

2673

2674

2675

2676

2677

2678

2679

2680

2681

2685 Builder.GetInsertBlock()->getParent()->hasFnAttribute(

2686 Attribute::NoImplicitFloat)) {

2690 Value *FAbs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, CastOp);

2692 }

2693 }

2694

2695

2696

2701 APInt(Ty->getScalarSizeInBits(),

2702 Ty->getScalarSizeInBits() -

2703 X->getType()->getScalarSizeInBits())))) {

2704 auto *SExt = Builder.CreateSExt(X, Ty, X->getName() + ".signext");

2705 return BinaryOperator::CreateAnd(SExt, Op1);

2706 }

2707

2709 return Z;

2710

2711 if (I.getType()->isIntOrIntVectorTy(1)) {

2713 if (auto *R =

2714 foldAndOrOfSelectUsingImpliedCond(Op1, *SI0, true))

2715 return R;

2716 }

2718 if (auto *R =

2719 foldAndOrOfSelectUsingImpliedCond(Op0, *SI1, true))

2720 return R;

2721 }

2722 }

2723

2725 return FoldedLogic;

2726

2728 return DeMorgan;

2729

2730 {

2732

2734 return BinaryOperator::CreateAnd(Op0, B);

2735

2737 return BinaryOperator::CreateAnd(Op1, B);

2738

2739

2745 if (NotC != nullptr)

2746 return BinaryOperator::CreateAnd(Op0, NotC);

2747 }

2748

2749

2755 if (NotC != nullptr)

2756 return BinaryOperator::CreateAnd(Op1, Builder.CreateNot(C));

2757 }

2758

2759

2760

2761

2762

2765 return BinaryOperator::CreateAnd(A, B);

2766

2767

2768

2769

2770

2773 return BinaryOperator::CreateAnd(A, B);

2774

2775

2776

2777

2778

2781 return BinaryOperator::CreateAnd(Builder.CreateNot(A), B);

2782

2783

2784

2785

2786

2789 return BinaryOperator::CreateAnd(Builder.CreateNot(A), B);

2790 }

2791

2792 if (Value *Res =

2793 foldBooleanAndOr(Op0, Op1, I, true, false))

2795

2798 if (auto *V = reassociateBooleanAndOr(Op0, X, Y, I, true,

2799 IsLogical))

2801 }

2804 if (auto *V = reassociateBooleanAndOr(Op1, X, Y, I, true,

2805 IsLogical))

2807 }

2808

2810 return FoldedFCmps;

2811

2812 if (Instruction *CastedAnd = foldCastedBitwiseLogic(I))

2813 return CastedAnd;

2814

2815 if (Instruction *Sel = foldBinopOfSextBoolToSelect(I))

2816 return Sel;

2817

2818

2819

2820

2821

2822

2825 A->getType()->isIntOrIntVectorTy(1))

2827

2828

2829

2831 A->getType()->isIntOrIntVectorTy(1))

2833

2834

2836 A->getType()->isIntOrIntVectorTy(1))

2839

2840

2843 if (A->getType()->isIntOrIntVectorTy(1))

2849 }

2850 }

2851

2852

2856 *C == X->getType()->getScalarSizeInBits() - 1) {

2859 }

2860

2861

2865 *C == X->getType()->getScalarSizeInBits() - 1) {

2868 }

2869

2870

2872 return &I;

2873

2874

2876 Value *Start = nullptr, *Step = nullptr;

2879

2881 return R;

2882

2884 return Canonicalized;

2885

2886 if (Instruction *Folded = foldLogicOfIsFPClass(I, Op0, Op1))

2887 return Folded;

2888

2889 if (Instruction *Res = foldBinOpOfDisplacedShifts(I))

2890 return Res;

2891

2893 return Res;

2894

2897 false, *this))

2898 return BinaryOperator::CreateAnd(V, Op1);

2901 false, *this))

2902 return BinaryOperator::CreateAnd(Op0, V);

2903

2904 return nullptr;

2905}

2906

2908 bool MatchBSwaps,

2909 bool MatchBitReversals) {

2912 Insts))

2913 return nullptr;

2916

2917 for (auto *Inst : Insts) {

2918 Inst->setDebugLoc(I.getDebugLoc());

2920 }

2921 return LastInst;

2922}

2923

2924std::optional<std::pair<Intrinsic::ID, SmallVector<Value *, 3>>>

2926

2927

2928 assert(Or.getOpcode() == BinaryOperator::Or && "Expecting or instruction");

2929

2930 unsigned Width = Or.getType()->getScalarSizeInBits();

2931

2935 return std::nullopt;

2936

2937 bool IsFshl = true;

2939

2940

2941

2943 Value *ShVal0, *ShVal1, *ShAmt0, *ShAmt1;

2949 return std::nullopt;

2950

2951

2952 if (Or0->getOpcode() == BinaryOperator::LShr) {

2956 }

2958 Or1->getOpcode() == BinaryOperator::LShr &&

2959 "Illegal or(shift,shift) pair");

2960

2961

2962

2963 auto matchShiftAmount = [&](Value *L, Value *R, unsigned Width) -> Value * {

2964

2965 const APInt *LI, *RI;

2967 if (LI->ult(Width) && RI->ult(Width) && (*LI + *RI) == Width)

2968 return ConstantInt::get(L->getType(), *LI);

2969

2978

2979

2980

2981

2982

2983

2986 return KnownL.getMaxValue().ult(Width) ? L : nullptr;

2987 }

2988

2989

2990

2991

2992 if (ShVal0 != ShVal1)

2993 return nullptr;

2994

2995

2996

2998 return nullptr;

2999

3000

3001

3003 unsigned Mask = Width - 1;

3006 return X;

3007

3008

3010 return L;

3011

3012

3013

3018 return L;

3019

3022 return L;

3023

3024 return nullptr;

3025 };

3026

3027 Value *ShAmt = matchShiftAmount(ShAmt0, ShAmt1, Width);

3028 if (!ShAmt) {

3029 ShAmt = matchShiftAmount(ShAmt1, ShAmt0, Width);

3030 IsFshl = false;

3031 }

3032 if (!ShAmt)

3033 return std::nullopt;

3034

3035 FShiftArgs = {ShVal0, ShVal1, ShAmt};

3037

3038

3039

3040

3041

3042

3043

3044

3045

3046

3047

3050

3052 const APInt *ZextHighShlAmt;

3055 return std::nullopt;

3056

3059 return std::nullopt;

3060

3061 unsigned HighSize = High->getType()->getScalarSizeInBits();

3062 unsigned LowSize = Low->getType()->getScalarSizeInBits();

3063

3064

3065 if (ZextHighShlAmt->ult(LowSize) || ZextHighShlAmt->ugt(Width - HighSize))

3066 return std::nullopt;

3067

3068 for (User *U : ZextHigh->users()) {

3071 continue;

3072

3075

3076 const APInt *ZextLowShlAmt;

3079 continue;

3080

3081

3082

3083 if (*ZextLowShlAmt + *ZextHighShlAmt != Width)

3084 continue;

3085

3086

3087

3088 assert(ZextLowShlAmt->uge(HighSize) &&

3089 ZextLowShlAmt->ule(Width - LowSize) && "Invalid concat");

3090

3091

3092

3093

3095

3097

3098 FShiftArgs = {U, U, ConstantInt::get(Or0->getType(), *ZextHighShlAmt)};

3099 break;

3100 }

3101 }

3102

3103 if (FShiftArgs.empty())

3104 return std::nullopt;

3105

3106 Intrinsic::ID IID = IsFshl ? Intrinsic::fshl : Intrinsic::fshr;

3107 return std::make_pair(IID, FShiftArgs);

3108}

3109

3110

3113 auto [IID, FShiftArgs] = *Opt;

3117 }

3118

3119 return nullptr;

3120}

3121

3122

3124 assert(Or.getOpcode() == Instruction::Or && "bswap requires an 'or'");

3125 Value *Op0 = Or.getOperand(0), *Op1 = Or.getOperand(1);

3126 Type *Ty = Or.getType();

3127

3128 unsigned Width = Ty->getScalarSizeInBits();

3129 if ((Width & 1) != 0)

3130 return nullptr;

3131 unsigned HalfWidth = Width / 2;

3132

3133

3136

3137

3138 Value *LowerSrc, *ShlVal, *UpperSrc;

3143 return nullptr;

3144 if (*C != HalfWidth || LowerSrc->getType() != UpperSrc->getType() ||

3146 return nullptr;

3147

3149 Value *NewLower = Builder.CreateZExt(Lo, Ty);

3150 Value *NewUpper = Builder.CreateZExt(Hi, Ty);

3151 NewUpper = Builder.CreateShl(NewUpper, HalfWidth);

3152 Value *BinOp = Builder.CreateOr(NewLower, NewUpper);

3153 return Builder.CreateIntrinsic(id, Ty, BinOp);

3154 };

3155

3156

3157

3158 Value *LowerBSwap, *UpperBSwap;

3161 return ConcatIntrinsicCalls(Intrinsic::bswap, UpperBSwap, LowerBSwap);

3162

3163

3164

3165 Value *LowerBRev, *UpperBRev;

3168 return ConcatIntrinsicCalls(Intrinsic::bitreverse, UpperBRev, LowerBRev);

3169

3170

3171

3172

3173

3179 m_SpecificInt(X->getType()->getScalarSizeInBits() - 1)))))

3180 return Builder.CreateSExt(X, Ty);

3181

3182 return nullptr;

3183}

3184

3185

3188 for (unsigned i = 0; i != NumElts; ++i) {

3191 if (!EltC1 || !EltC2)

3192 return false;

3193

3194

3197 return false;

3198 }

3199 return true;

3200}

3201

3202

3203

3204

3205

3207 bool ABIsTheSame) {

3208

3209

3210 Type *Ty = A->getType();

3212 return nullptr;

3213

3214

3216

3218 return A;

3219

3220

3221

3222

3223

3224

3226 if (A->getType()->isIntOrIntVectorTy()) {

3228 if (NumSignBits == A->getType()->getScalarSizeInBits() &&

3231 }

3232 return nullptr;

3233 }

3234

3235

3236 if (ABIsTheSame)

3237 return nullptr;

3238

3239

3245

3246

3247

3251 Cond->getType()->isIntOrIntVectorTy(1)) {

3252

3254 return Cond;

3255

3256

3257

3258

3259

3263 return Cond;

3264 }

3265 }

3266

3267

3268

3270 return nullptr;

3271

3272

3273

3274

3277 Cond->getType()->isIntOrIntVectorTy(1) &&

3281 }

3282 return nullptr;

3283}

3284

3285

3286

3287

3288

3289

3291 Value *D, bool InvertFalseVal) {

3292

3293

3297 if (Value *Cond = getSelectCondition(A, C, InvertFalseVal)) {

3298

3299

3300

3301

3302 Type *SelTy = A->getType();

3304

3305 unsigned Elts = VecTy->getElementCount().getKnownMinValue();

3306

3307

3309 Type *EltTy = Builder.getIntNTy(SelEltSize / Elts);

3310 SelTy = VectorType::get(EltTy, VecTy->getElementCount());

3311 }

3312 Value *BitcastB = Builder.CreateBitCast(B, SelTy);

3313 if (InvertFalseVal)

3315 Value *BitcastD = Builder.CreateBitCast(D, SelTy);

3318 }

3319

3320 return nullptr;

3321}

3322

3323

3324

3326 bool IsAnd, bool IsLogical,

3328 Value *LHS0 = LHS->getOperand(0);

3329 Value *RHS0 = RHS->getOperand(0);

3330 Value *RHS1 = RHS->getOperand(1);

3331

3333 IsAnd ? LHS->getInversePredicate() : LHS->getPredicate();

3335 IsAnd ? RHS->getInversePredicate() : RHS->getPredicate();

3336

3337 const APInt *CInt;

3341 !(LHS->hasOneUse() || RHS->hasOneUse()))

3342 return nullptr;

3343

3344 auto MatchRHSOp = [LHS0, CInt](const Value *RHSOp) {

3345 return match(RHSOp,

3347 (CInt->isZero() && RHSOp == LHS0);

3348 };

3349

3355 else

3356 return nullptr;

3357

3358 if (IsLogical)

3359 Other = Builder.CreateFreeze(Other);

3360

3361 return Builder.CreateICmp(

3363 Builder.CreateSub(LHS0, ConstantInt::get(LHS0->getType(), *CInt + 1)),

3365}

3366

3367

3368

3369

3372 bool IsLogical) {

3373 const SimplifyQuery Q = SQ.getWithInstruction(&I);

3374

3376 Value *LHS0 = LHS->getOperand(0), *RHS0 = RHS->getOperand(0);

3377 Value *LHS1 = LHS->getOperand(1), *RHS1 = RHS->getOperand(1);

3378

3379 const APInt *LHSC = nullptr, *RHSC = nullptr;

3382

3383

3384

3386 if (LHS0 == RHS1 && LHS1 == RHS0) {

3389 }

3390 if (LHS0 == RHS0 && LHS1 == RHS1) {

3393 bool IsSigned = LHS->isSigned() || RHS->isSigned();

3395 }

3396 }

3397

3400 return V;

3401

3402

3404 false, Builder))

3405 return V;

3406

3409 return V;

3410

3411

3413 RHS, LHS, IsAnd, false, Builder, Q, I)) {

3414

3415 if (IsLogical && RHS->hasSameSign() && RHS->use_empty()) {

3416 RHS->setSameSign(false);

3418 }

3419 return V;

3420 }

3421

3423 return V;

3425 return V;

3426

3427

3428

3429 if (!IsLogical) {

3430

3431

3433 return V;

3434

3435

3436

3438 return V;

3439 }

3440

3441

3442 if (IsAnd && !IsLogical)

3444 return V;

3445

3447 return V;

3448

3450 return V;

3451

3452

3453 if (!IsLogical) {

3455 return X;

3457 return X;

3458 }

3459

3460

3461

3462

3467 Value *NewOr = Builder.CreateOr(LHS0, RHS0);

3468 return Builder.CreateICmp(PredL, NewOr,

3470 }

3471

3472

3473

3478 Value *NewAnd = Builder.CreateAnd(LHS0, RHS0);

3479 return Builder.CreateICmp(PredL, NewAnd,

3481 }

3482

3483 if (!IsLogical)

3486 return V;

3487

3488

3489 if (!LHSC || !RHSC)

3490 return nullptr;

3491

3492

3493

3494

3495

3499 const APInt *AndC, *SmallC = nullptr, *BigC = nullptr;

3500

3501

3502

3505 SmallC = RHSC;

3506 BigC = LHSC;

3509 SmallC = LHSC;

3510 BigC = RHSC;

3511 }

3512

3513 if (SmallC && BigC) {

3514 unsigned BigBitSize = BigC->getBitWidth();

3515 unsigned SmallBitSize = SmallC->getBitWidth();

3516

3517

3521 APInt N = SmallC->zext(BigBitSize) | *BigC;

3522 Value *NewVal = ConstantInt::get(NewAnd->getType(), N);

3523 return Builder.CreateICmp(PredL, NewAnd, NewVal);

3524 }

3525 }

3526 }

3527

3528

3529

3530

3531

3532

3533 bool TrueIfSignedL, TrueIfSignedR;

3538 if (IsAnd) {

3539 if ((TrueIfSignedL && !TrueIfSignedR &&

3542 (!TrueIfSignedL && TrueIfSignedR &&

3546 return Builder.CreateIsNeg(NewXor);

3547 }

3548 } else {

3549 if ((TrueIfSignedL && !TrueIfSignedR &&

3552 (!TrueIfSignedL && TrueIfSignedR &&

3556 return Builder.CreateIsNotNeg(NewXor);

3557 }

3558 }

3559 }

3560

3561

3562

3564 const APInt *MaskC;

3565 if (LHS0 == RHS0 && PredL == PredR &&

3567 I.getFunction()->hasFnAttribute(Attribute::NoImplicitFloat) &&

3570 X->getType()->getScalarType()->isIEEELikeFPTy() &&

3571 APFloat(X->getType()->getScalarType()->getFltSemantics(), *MaskC)

3572 .isPosInfinity() &&

3573 ((LHSC->isZero() && *RHSC == *MaskC) ||

3574 (RHSC->isZero() && *LHSC == *MaskC)))

3577

3578 return foldAndOrOfICmpsUsingRanges(LHS, RHS, IsAnd);

3579}

3580

3581

3582

3585 bool IsLogical) {

3587 return nullptr;

3588

3589

3590

3591

3593 SQ.getWithInstruction(&I)))

3594 return V;

3595

3598 if (Value *Res = foldAndOrOfICmps(LHSCmp, RHSCmp, I, IsAnd, IsLogical))

3599 return Res;

3600

3603 if (Value *Res = foldLogicOfFCmps(LHSCmp, RHSCmp, IsAnd, IsLogical))

3604 return Res;

3605

3606 if (Value *Res = foldEqOfParts(LHS, RHS, IsAnd))

3607 return Res;

3608

3609 return nullptr;

3610}

3611

3614 assert(I.getOpcode() == Instruction::Or &&

3615 "Simplification only supports or at the moment.");

3616

3617 Value *Cmp1, *Cmp2, *Cmp3, *Cmp4;

3620 return nullptr;

3621

3622

3624 return Builder.CreateXor(Cmp1, Cmp4);

3626 return Builder.CreateXor(Cmp1, Cmp3);

3627

3628 return nullptr;

3629}

3630

3631

3632

3633

3634

3635

3636

3637

3638

3639

3641 int64_t &VecOffset,

3644

3648 ShlAmt))) {

3650 if (!VecTy)

3651 return false;

3653 if (!EltTy)

3654 return false;

3655

3656 const unsigned EltBitWidth = EltTy->getBitWidth();

3658 if (TargetBitWidth % EltBitWidth != 0 || ShlAmt % EltBitWidth != 0)

3659 return false;

3660 const unsigned TargetEltWidth = TargetBitWidth / EltBitWidth;

3661 const unsigned ShlEltAmt = ShlAmt / EltBitWidth;

3662

3663 const unsigned MaskIdx =

3664 DL.isLittleEndian() ? ShlEltAmt : TargetEltWidth - ShlEltAmt - 1;

3665

3666 VecOffset = static_cast<int64_t>(VecIdx) - static_cast<int64_t>(MaskIdx);

3667 Mask.resize(TargetEltWidth);

3668 Mask.set(MaskIdx);

3669 return true;

3670 }

3671

3672

3675 return false;

3676

3678 if (!SrcTy)

3679 return false;

3680

3681 Mask.resize(SrcTy->getNumElements());

3682

3683

3688 m_Mask(ShuffleMask))))

3689 return false;

3690

3692 if (!VecTy)

3693 return false;

3694

3695 const unsigned NumVecElts = VecTy->getNumElements();

3696 bool FoundVecOffset = false;

3697 for (unsigned Idx = 0; Idx < ShuffleMask.size(); ++Idx) {

3699 return false;

3700 const unsigned ShuffleIdx = ShuffleMask[Idx];

3701 if (ShuffleIdx >= NumVecElts) {

3702 const unsigned ConstIdx = ShuffleIdx - NumVecElts;

3703 auto *ConstElt =

3705 if (!ConstElt || !ConstElt->isNullValue())

3706 return false;

3707 continue;

3708 }

3709

3710 if (FoundVecOffset) {

3711 if (VecOffset + Idx != ShuffleIdx)

3712 return false;

3713 } else {

3714 if (ShuffleIdx < Idx)

3715 return false;

3716 VecOffset = ShuffleIdx - Idx;

3717 FoundVecOffset = true;

3718 }

3719 Mask.set(Idx);

3720 }

3721 return FoundVecOffset;

3722 }

3723

3724

3726 if (match(SrcVecI,

3728 return false;

3729

3731 if (!VecTy)

3732 return false;

3733 VecOffset = 0;

3734 bool AlreadyInsertedMaskedElt = Mask.test(InsertIdx);

3735 Mask.set();

3736 if (!AlreadyInsertedMaskedElt)

3737 Mask.reset(InsertIdx);

3738 return true;

3739}

3740

3741

3742

3746 assert(I.getOpcode() == Instruction::Or);

3747 Value *LhsVec, *RhsVec;

3748 int64_t LhsVecOffset, RhsVecOffset;

3751 Mask, DL))

3752 return nullptr;

3754 Mask, DL))

3755 return nullptr;

3756 if (LhsVec != RhsVec || LhsVecOffset != RhsVecOffset)

3757 return nullptr;

3758

3759

3760 const unsigned ZeroVecIdx =

3763 for (unsigned Idx : Mask.set_bits()) {

3764 assert(LhsVecOffset + Idx >= 0);

3765 ShuffleMask[Idx] = LhsVecOffset + Idx;

3766 }

3767

3768 Value *MaskedVec = Builder.CreateShuffleVector(

3770 I.getName() + ".v");

3771 return CastInst::Create(Instruction::BitCast, MaskedVec, I.getType());

3772}

3773

3774

3775

3776

3777

3778

3779

3782 bool &IsShlNSW) {

3786 return false;

3787

3790

3793 return false;

3794

3795 Value *MaskedOp0;

3796 const APInt *ShiftedMaskConst = nullptr;

3798 m_APInt(ShiftedMaskConst))),

3800 return false;

3801

3803 if (match(MaskedOp0,

3806 return false;

3807

3808 if (LShrAmt > ShlAmt)

3809 return false;

3810 Offset = ShlAmt - LShrAmt;

3811

3812 Mask = ShiftedMaskConst ? ShiftedMaskConst->shl(LShrAmt)

3814 Int->getType()->getScalarSizeInBits(), LShrAmt);

3815

3816 return true;

3817}

3818

3819

3820

3823

3824 Value *LhsInt, *RhsInt;

3825 APInt LhsMask, RhsMask;

3826 uint64_t LhsOffset, RhsOffset;

3827 bool IsLhsShlNUW, IsLhsShlNSW, IsRhsShlNUW, IsRhsShlNSW;

3829 IsLhsShlNSW))

3830 return nullptr;

3832 IsRhsShlNSW))

3833 return nullptr;

3834 if (LhsInt != RhsInt || LhsOffset != RhsOffset)

3835 return nullptr;

3836

3837 APInt Mask = LhsMask | RhsMask;

3838

3840 Value *Res = Builder.CreateShl(

3841 Builder.CreateZExt(

3842 Builder.CreateAnd(LhsInt, Mask, LhsInt->getName() + ".mask"), DestTy,

3843 LhsInt->getName() + ".zext"),

3844 ConstantInt::get(DestTy, LhsOffset), "", IsLhsShlNUW && IsRhsShlNUW,

3845 IsLhsShlNSW && IsRhsShlNSW);

3847 return Res;

3848}

3849

3850

3851

3852

3853

3866

3869 if (Op)

3870 return std::nullopt;

3871

3872

3873 Value *Original = nullptr;

3874 const APInt *Mask = nullptr;

3875 const APInt *MulConst = nullptr;

3878 if (MulConst->isZero() || Mask->isZero())

3879 return std::nullopt;

3880

3881 return std::optional(

3882 {Original, *MulConst, *Mask,

3885 }

3886

3888 const APInt *EqZero = nullptr, *NeZero = nullptr;

3889

3890

3892 auto ICmpDecompose =

3894 false, true);

3895 if (!ICmpDecompose.has_value())

3896 return std::nullopt;

3897

3899 ICmpDecompose->C.isZero());

3900

3903

3904 if (!EqZero->isZero() || NeZero->isZero())

3905 return std::nullopt;

3906

3907 if (!ICmpDecompose->Mask.isPowerOf2() || ICmpDecompose->Mask.isZero() ||

3908 NeZero->getBitWidth() != ICmpDecompose->Mask.getBitWidth())

3909 return std::nullopt;

3910

3911 if (!NeZero->urem(ICmpDecompose->Mask).isZero())

3912 return std::nullopt;

3913

3914 return std::optional(

3915 {ICmpDecompose->X, NeZero->udiv(ICmpDecompose->Mask),

3916 ICmpDecompose->Mask, false, false});

3917 }

3918

3919 return std::nullopt;

3920}

3921

3922

3923

3924

3928 if (!Decomp1)

3929 return nullptr;

3930

3932 if (!Decomp0)

3933 return nullptr;

3934

3935 if (Decomp0->isCombineableWith(*Decomp1)) {

3936 Value *NewAnd = Builder.CreateAnd(

3937 Decomp0->X,

3938 ConstantInt::get(Decomp0->X->getType(), Decomp0->Mask + Decomp1->Mask));

3939

3940 return Builder.CreateMul(

3941 NewAnd, ConstantInt::get(NewAnd->getType(), Decomp1->Factor), "",

3942 Decomp0->NUW && Decomp1->NUW, Decomp0->NSW && Decomp1->NSW);

3943 }

3944

3945 return nullptr;

3946}

3947

3950 return Res;

3952 return Res;

3953

3954 return nullptr;

3955}

3956

3958

3961 if (Value *Res = foldDisjointOr(LHS, X))

3962 return Builder.CreateOr(Res, Y, "", true);

3963 if (Value *Res = foldDisjointOr(LHS, Y))

3964 return Builder.CreateOr(Res, X, "", true);

3965 }

3966

3968 if (Value *Res = foldDisjointOr(X, RHS))

3969 return Builder.CreateOr(Res, Y, "", true);

3970 if (Value *Res = foldDisjointOr(Y, RHS))

3971 return Builder.CreateOr(Res, X, "", true);

3972 }

3973

3974 return nullptr;

3975}

3976

3977

3978

3979

3980

3985 const APInt *C1, *C2;

3994 Constant *NewC = ConstantInt::get(X->getType(), C2->udiv(*C1));

3996 }

3997 return nullptr;

3998}

3999

4000

4001

4015 return Builder.CreateBinaryIntrinsic(Intrinsic::abs, X,

4016 Builder.getFalse());

4017 }

4018 return nullptr;

4019}

4020

4021

4022

4023

4026 SQ.getWithInstruction(&I)))

4028

4030 return &I;

4031

4033 return X;

4034

4036 return Phi;

4037

4038

4039

4041 return &I;

4042

4043

4045 return Xor;

4046

4048 return X;

4049

4051 return X;

4052

4053

4054

4057

4058

4061

4062 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);

4063 Type *Ty = I.getType();

4064 if (Ty->isIntOrIntVectorTy(1)) {

4066 if (auto *R =

4067 foldAndOrOfSelectUsingImpliedCond(Op1, *SI0, false))

4068 return R;

4069 }

4071 if (auto *R =

4072 foldAndOrOfSelectUsingImpliedCond(Op0, *SI1, false))

4073 return R;

4074 }

4075 }

4076

4078 return FoldedLogic;

4079

4081 true))

4082 return BitOp;

4083

4085 return Funnel;

4086

4089

4091 return R;

4092

4094 return R;

4095

4099 true, true))

4100 return R;

4103 true, true))

4104 return R;

4105

4106 if (Value *Res = foldDisjointOr(I.getOperand(0), I.getOperand(1)))

4108

4109 if (Value *Res = reassociateDisjointOr(I.getOperand(0), I.getOperand(1)))

4111 }

4112

4114 const APInt *CV;

4117

4118

4120 return BinaryOperator::CreateXor(Or, ConstantInt::get(Ty, *CV));

4121 }

4122

4123

4124

4127 Value *IncrementY = Builder.CreateAdd(Y, ConstantInt::get(Ty, 1));

4128 return BinaryOperator::CreateMul(X, IncrementY);

4129 }

4130

4131

4135

4136

4137 const APInt *C0, *C1;

4140 if (*C0 == ~*C1) {

4141

4143 return BinaryOperator::CreateOr(Builder.CreateAnd(X, *C0), B);

4144

4146 return BinaryOperator::CreateOr(Builder.CreateAnd(X, *C1), A);

4147

4148

4150 return BinaryOperator::CreateXor(Builder.CreateAnd(X, *C0), B);

4151

4153 return BinaryOperator::CreateXor(Builder.CreateAnd(X, *C1), A);

4154 }

4155

4156 if ((*C0 & *C1).isZero()) {

4157

4158

4161 Constant *C01 = ConstantInt::get(Ty, *C0 | *C1);

4162 return BinaryOperator::CreateAnd(A, C01);

4163 }

4164

4165

4168 Constant *C01 = ConstantInt::get(Ty, *C0 | *C1);

4169 return BinaryOperator::CreateAnd(B, C01);

4170 }

4171

4172

4173 const APInt *C2, *C3;

4176 (*C2 & ~*C0).isZero() && (*C3 & ~*C1).isZero()) {

4178 Constant *C01 = ConstantInt::get(Ty, *C0 | *C1);

4179 return BinaryOperator::CreateAnd(Or, C01);

4180 }

4181 }

4182 }

4183

4184

4185

4186

4188

4189 if (Value *V = matchSelectFromAndOr(A, C, B, D))

4191 if (Value *V = matchSelectFromAndOr(A, C, D, B))

4193 if (Value *V = matchSelectFromAndOr(C, A, B, D))

4195 if (Value *V = matchSelectFromAndOr(C, A, D, B))

4197 if (Value *V = matchSelectFromAndOr(B, D, A, C))

4199 if (Value *V = matchSelectFromAndOr(B, D, C, A))

4201 if (Value *V = matchSelectFromAndOr(D, B, A, C))

4203 if (Value *V = matchSelectFromAndOr(D, B, C, A))

4205 }

4206 }

4207

4211

4212 if (Value *V = matchSelectFromAndOr(A, C, B, D, true))

4214 if (Value *V = matchSelectFromAndOr(A, C, D, B, true))

4216 if (Value *V = matchSelectFromAndOr(C, A, B, D, true))

4218 if (Value *V = matchSelectFromAndOr(C, A, D, B, true))

4220 }

4221

4222

4227 return BinaryOperator::CreateOr(Op0, C);

4228

4229

4234 return BinaryOperator::CreateOr(Op1, C);

4235

4237 return DeMorgan;

4238

4239

4240 bool SwappedForXor = false;

4243 SwappedForXor = true;

4244 }

4245

4247

4248

4250 return BinaryOperator::CreateOr(Op0, B);

4252 return BinaryOperator::CreateOr(Op0, A);

4253

4254

4255

4257 return BinaryOperator::CreateOr(A, B);

4258

4259

4260

4261

4265

4266

4267

4268

4278

4279

4280

4285 return BinaryOperator::CreateOr(Nand, C);

4286 }

4287 }

4288

4289 if (SwappedForXor)

4291

4292 if (Value *Res =

4293 foldBooleanAndOr(Op0, Op1, I, false, false))

4295

4298 if (auto *V = reassociateBooleanAndOr(Op0, X, Y, I, false,

4299 IsLogical))

4301 }

4304 if (auto *V = reassociateBooleanAndOr(Op1, X, Y, I, false,

4305 IsLogical))

4307 }

4308

4310 return FoldedFCmps;

4311

4312 if (Instruction *CastedOr = foldCastedBitwiseLogic(I))

4313 return CastedOr;

4314

4315 if (Instruction *Sel = foldBinopOfSextBoolToSelect(I))

4316 return Sel;

4317

4318

4319

4320

4321

4322

4324 A->getType()->isIntOrIntVectorTy(1))

4326

4327

4328

4329

4330

4331

4332

4333

4334

4335

4336

4337

4346 return IsDisjointOuter && IsDisjointInner

4347 ? BinaryOperator::CreateDisjointOr(Inner, CI)

4348 : BinaryOperator::CreateOr(Inner, CI);

4349 }

4350

4351

4352

4353

4354 {

4355 Value *X = nullptr, *Y = nullptr;

4362 }

4363 }

4364

4365

4366 {

4375 }

4376 }

4377

4378 {

4379

4380

4381

4382

4387 return BinaryOperator::CreateXor(A, B);

4388 }

4389 return nullptr;

4390 };

4391

4392 if (Instruction *Result = TryXorOpt(Op0, Op1))

4393 return Result;

4394 if (Instruction *Result = TryXorOpt(Op1, Op0))

4395 return Result;

4396 }

4397

4400 return V;

4401

4403 Value *Mul, *Ov, *MulIsNotZero, *UMulWithOv;

4404

4405

4406

4407

4421 return BinaryOperator::CreateAnd(NotNullA, NotNullB);

4422 }

4423 }

4424

4425

4426

4427

4429 const Value *WOV;

4430 const APInt *C1, *C2;

4435 (WO->getBinaryOp() == Instruction::Add ||

4436 WO->getBinaryOp() == Instruction::Sub) &&

4440 bool Overflow;

4443 : C2->usub_ov(*C1, Overflow))

4445 : C2->uadd_ov(*C1, Overflow));

4449 return BinaryOperator::CreateOr(Ov, NewCmp);

4450 }

4451 }

4452

4453

4454

4457

4458

4460 return &I;

4461

4462

4463

4468 ConstantInt::get(Ty, Ty->getScalarSizeInBits() - 1), X);

4470 }

4471

4472

4474 Value *Start = nullptr, *Step = nullptr;

4477

4478

4479

4482

4483

4484

4485

4486

4487

4488

4489

4492 return BinaryOperator::CreateOr(

4494

4495

4496

4497

4498

4499

4500

4501

4504 return BinaryOperator::CreateOr(

4506 }

4507

4509 return R;

4510

4512 return Canonicalized;

4513

4514 if (Instruction *Folded = foldLogicOfIsFPClass(I, Op0, Op1))

4515 return Folded;

4516

4517 if (Instruction *Res = foldBinOpOfDisplacedShifts(I))

4518 return Res;

4519

4520

4521

4522

4523

4524

4525

4526

4527

4528

4529

4530

4534 Builder.GetInsertBlock()->getParent()->hasFnAttribute(

4535 Attribute::NoImplicitFloat)) {

4539 Value *FAbs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, CastOp);

4541 return new BitCastInst(FNegFAbs, I.getType());

4542 }

4543 }

4544

4545

4549 if ((KnownX.One & *C2) == *C2)

4550 return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, *C1 | *C2));

4551 }

4552

4554 return Res;

4555

4558 false, *this))

4559 return BinaryOperator::CreateOr(V, Op1);

4562 false, *this))

4563 return BinaryOperator::CreateOr(Op0, V);

4564

4568

4571

4572 return nullptr;

4573}

4574

4575

4576

4579 assert(I.getOpcode() == Instruction::Xor);

4580 Value *Op0 = I.getOperand(0);

4581 Value *Op1 = I.getOperand(1);

4583

4584

4585

4586

4587

4588

4589

4592 return BinaryOperator::CreateXor(A, B);

4593

4594

4595

4596

4597

4600 return BinaryOperator::CreateXor(A, B);

4601

4602

4603

4604

4605

4608 return BinaryOperator::CreateXor(A, B);

4609

4610

4612 return nullptr;

4613

4614

4615

4616

4617

4618

4624

4625 return nullptr;

4626}

4627

4630 assert(I.getOpcode() == Instruction::Xor && I.getOperand(0) == LHS &&

4631 I.getOperand(1) == RHS && "Should be 'xor' with these operands");

4632

4634 Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);

4635 Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);

4636

4638 if (LHS0 == RHS1 && LHS1 == RHS0) {

4641 }

4642 if (LHS0 == RHS0 && LHS1 == RHS1) {

4643

4645 bool IsSigned = LHS->isSigned() || RHS->isSigned();

4647 }

4648 }

4649

4650 const APInt *LC, *RC;

4654

4655

4656

4657

4658

4659 bool TrueIfSignedL, TrueIfSignedR;

4663 Value *XorLR = Builder.CreateXor(LHS0, RHS0);

4664 return TrueIfSignedL == TrueIfSignedR ? Builder.CreateIsNeg(XorLR) :

4665 Builder.CreateIsNotNeg(XorLR);

4666 }

4667

4668

4669

4670 if (LHS0 == RHS0) {

4675 if (CRUnion && CRIntersect)

4676 if (auto CR = CRUnion->exactIntersectWith(CRIntersect->inverse())) {

4677 if (CR->isFullSet())

4679 if (CR->isEmptySet())

4681

4684 CR->getEquivalentICmp(NewPred, NewC, Offset);

4685

4688 Value *NewV = LHS0;

4690 if (Offset.isZero())

4691 NewV = Builder.CreateAdd(NewV, ConstantInt::get(Ty, Offset));

4692 return Builder.CreateICmp(NewPred, NewV,

4693 ConstantInt::get(Ty, NewC));

4694 }

4695 }

4696 }

4697

4698

4699

4711 }

4712 }

4713

4714

4715

4716

4717

4718

4719

4721

4722

4724

4725 ICmpInst *X = nullptr, *Y = nullptr;

4726 if (OrICmp == LHS && AndICmp == RHS) {

4727

4730 }

4731 if (OrICmp == RHS && AndICmp == LHS) {

4732

4735 }

4737

4738 Y->setPredicate(Y->getInversePredicate());

4739

4740 if (Y->hasOneUse()) {

4741

4742

4743

4744

4746

4747 Builder.SetInsertPoint(Y->getParent(), ++(Y->getIterator()));

4748 Value *NotY = Builder.CreateNot(Y, Y->getName() + ".not");

4749

4750 Worklist.pushUsersToWorkList(*Y);

4751 Y->replaceUsesWithIf(NotY,

4752 [NotY](Use &U) { return U.getUser() != NotY; });

4753 }

4754

4756 }

4757 }

4758 }

4759

4760 return nullptr;

4761}

4762

4763

4764

4765

4766

4767

4768

4769

4770

4771

4772

4773

4774

4775

4776

4785 return nullptr;

4786

4789

4790 Value *NewA = Builder.CreateAnd(D, NotM);

4791 return BinaryOperator::CreateXor(NewA, X);

4792 }

4793

4796

4797 Type *EltTy = C->getType()->getScalarType();

4799

4800 Value *LHS = Builder.CreateAnd(X, C);

4801 Value *NotC = Builder.CreateNot(C);

4802 Value *RHS = Builder.CreateAnd(B, NotC);

4803 return BinaryOperator::CreateOr(LHS, RHS);

4804 }

4805

4806 return nullptr;

4807}

4808

4812

4813

4815 return nullptr;

4816

4818 return A == C || A == D || B == C || B == D;

4819 };

4820

4822

4823

4826 Value *NotY = Builder.CreateNot(Y);

4827 return BinaryOperator::CreateOr(X, NotY);

4828 };

4829

4830

4831

4834 Value *NotX = Builder.CreateNot(X);

4835 return BinaryOperator::CreateOr(Y, NotX);

4836 };

4837

4838 return nullptr;

4839}

4840

4841

4842

4845 assert(Xor.getOpcode() == Instruction::Xor && "Expected an xor instruction.");

4846

4847

4848

4849

4850

4851 Value *Op0 = Xor.getOperand(0), *Op1 = Xor.getOperand(1);

4854

4855 Type *Ty = Xor.getType();

4857 const APInt *ShAmt;

4859 Op1->hasNUses(2) && *ShAmt == Ty->getScalarSizeInBits() - 1 &&

4861

4862

4863

4864 Value *IsNeg = Builder.CreateIsNeg(A);

4865

4867 Value *NegA = Add->hasNoUnsignedWrap()

4869 : Builder.CreateNeg(A, "", Add->hasNoSignedWrap());

4871 }

4872 return nullptr;

4873}

4874

4881

4887 Op->replaceUsesWithIf(NotOp,

4888 [NotOp](Use &U) { return U.getUser() != NotOp; });

4890 return NotOp;

4891}

4892

4893

4894

4895

4896

4897

4899 Value *Op0, *Op1;

4901 return false;

4902

4903

4904

4905 if (Op0 == Op1)

4906 return false;

4907

4908

4909

4910

4912 return false;

4913

4917

4918

4920 return false;

4921

4922

4924 return false;

4925

4928

4929 Builder.SetInsertPoint(*I.getInsertionPointAfterDef());

4930 Value *NewLogicOp;

4931 if (IsBinaryOp)

4932 NewLogicOp = Builder.CreateBinOp(NewOpc, Op0, Op1, I.getName() + ".not");

4933 else

4934 NewLogicOp =

4935 Builder.CreateLogicalOp(NewOpc, Op0, Op1, I.getName() + ".not");

4936

4938

4939

4940

4942 return true;

4943}

4944

4945

4946

4947

4948

4949

4951 Value *Op0, *Op1;

4953 return false;

4957

4958 Value *NotOp0 = nullptr;

4959 Value *NotOp1 = nullptr;

4960 Value **OpToInvert = nullptr;

4962 Op0 = NotOp0;

4963 OpToInvert = &Op1;

4966 Op1 = NotOp1;

4967 OpToInvert = &Op0;

4968 } else

4969 return false;

4970

4971

4973 return false;

4974

4975 *OpToInvert = freelyInvert(*this, *OpToInvert, &I);

4976

4977 Builder.SetInsertPoint(*I.getInsertionPointAfterDef());

4978 Value *NewBinOp;

4979 if (IsBinaryOp)

4980 NewBinOp = Builder.CreateBinOp(NewOpc, Op0, Op1, I.getName() + ".not");

4981 else

4982 NewBinOp = Builder.CreateLogicalOp(NewOpc, Op0, Op1, I.getName() + ".not");

4984

4985

4986

4988 return true;

4989}

4990

4994 return nullptr;

4995

4996

4997

4998

4999

5000

5001

5002

5003

5004

5005 Type *Ty = I.getType();

5008 Value *NotY = Builder.CreateNot(Y, Y->getName() + ".not");

5009 return BinaryOperator::CreateOr(X, NotY);

5010 }

5012 Value *NotY = Builder.CreateNot(Y, Y->getName() + ".not");

5014 }

5015

5016

5017

5019 Value *NotY = Builder.CreateNot(Y, Y->getName() + ".not");

5020 return BinaryOperator::CreateAnd(X, NotY);

5021 }

5023 Value *NotY = Builder.CreateNot(Y, Y->getName() + ".not");

5025 }

5026

5027

5028 BinaryOperator *NotVal;

5030

5031 if (match(NotVal,

5035 return BinaryOperator::CreateAnd(DecX, NotY);

5036 }

5037

5038

5040 return BinaryOperator::CreateAShr(X, Y);

5041

5042

5043

5046 return BinaryOperator::CreateAShr(X, Y);

5047

5048

5049

5052 Value *IsNotNeg = Builder.CreateIsNotNeg(X, "isnotneg");

5053 return new SExtInst(IsNotNeg, Ty);

5054 }

5055

5056

5057

5058

5059

5060

5061

5066

5067

5071

5072

5075

5076

5077

5080 return BinaryOperator::CreateAdd(Builder.CreateNot(X), Y);

5081

5082

5085 NotVal);

5086 }

5087

5088

5089 CmpPredicate Pred;

5093 nullptr))) {

5096 return &I;

5097 }

5098

5099

5103 return new BitCastInst(X, Ty);

5104 }

5105

5106

5107

5109 X->getType()->isIntOrIntVectorTy(1)) {

5112 Value *Sext = Builder.CreateSExt(NotX, SextTy);

5113 return new BitCastInst(Sext, Ty);

5114 }

5115

5118 return &I;

5119

5120

5121

5122

5124 if (II && II->hasOneUse()) {

5128 Value *InvMaxMin = Builder.CreateBinaryIntrinsic(InvID, X, NotY);

5130 }

5131

5132 if (II->getIntrinsicID() == Intrinsic::is_fpclass) {

5134 II->setArgOperand(

5135 1, ConstantInt::get(ClassMask->getType(),

5138 }

5139 }

5140

5142

5143

5144

5145

5146

5147

5148

5149

5151 Value *TV = Sel->getTrueValue();

5152 Value *FV = Sel->getFalseValue();

5155 bool InvertibleT = (CmpT && CmpT->hasOneUse()) || isa(TV);

5156 bool InvertibleF = (CmpF && CmpF->hasOneUse()) || isa(FV);

5157 if (InvertibleT && InvertibleF) {

5158 if (CmpT)

5159 CmpT->setPredicate(CmpT->getInversePredicate());

5160 else

5162 if (CmpF)

5163 CmpF->setPredicate(CmpF->getInversePredicate());

5164 else

5167 }

5168 }

5169 }

5170

5172 return NewXor;

5173

5174

5175

5178

5179 return nullptr;

5180}

5181

5182

5183

5184

5187 SQ.getWithInstruction(&I)))

5189

5191 return &I;

5192

5194 return X;

5195

5197 return Phi;

5198

5200 return NewXor;

5201

5202

5205

5206

5207

5209 return &I;

5210

5212 return R;

5213

5215 return R;

5216

5217 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);

5219

5220

5221

5225 return BinaryOperator::CreateXor(XorAC, Y);

5226

5228 return BinaryOperator::CreateXor(XorBC, X);

5229 }

5230

5231

5232

5233

5234

5238 return BinaryOperator::CreateDisjointOr(Op0, Op1);

5239 else

5240 return BinaryOperator::CreateOr(Op0, Op1);

5241 }

5242

5244 return Xor;

5245

5249

5252

5257 return BinaryOperator::CreateXor(

5259 }

5260

5261

5263

5266 }

5268

5271 }

5272

5273

5274

5275

5276

5277 const APInt *CA;

5280 *CA == X->getType()->getScalarSizeInBits() - 1 &&

5285 }

5286 }

5287

5288 Type *Ty = I.getType();

5289 {

5290 const APInt *RHSC;

5294

5296 return BinaryOperator::CreateSub(ConstantInt::get(Ty, *C + *RHSC), X);

5297

5298

5300 return BinaryOperator::CreateAdd(X, ConstantInt::get(Ty, *C + *RHSC));

5301

5302

5305 return BinaryOperator::CreateXor(X, ConstantInt::get(Ty, *C ^ *RHSC));

5306

5307

5308

5309

5311 if (II && II->hasOneUse() && *RHSC == Ty->getScalarSizeInBits() - 1) {

5313 if ((IID == Intrinsic::ctlz || IID == Intrinsic::cttz) &&

5316 IID = (IID == Intrinsic::ctlz) ? Intrinsic::cttz : Intrinsic::ctlz;

5320 }

5321 }

5322

5323

5324

5325

5329 return BinaryOperator::CreateShl(NotX, ConstantInt::get(Ty, *C));

5330 }

5331

5335 return BinaryOperator::CreateLShr(NotX, ConstantInt::get(Ty, *C));

5336 }

5337

5338

5339

5340 }

5341

5342

5343

5344

5345

5346

5347

5348

5349

5353 Builder.GetInsertBlock()->getParent()->hasFnAttribute(

5354 Attribute::NoImplicitFloat)) {

5360 }

5361 }

5362 }

5363

5364

5365 {

5368

5373

5375 FoldConst ^= C3->getValue();

5376

5377 auto *Opnd0 = Builder.CreateLShr(X, C2);

5378 Opnd0->takeName(Op0);

5379 return BinaryOperator::CreateXor(Opnd0, ConstantInt::get(Ty, FoldConst));

5380 }

5381 }

5382

5384 return FoldedLogic;

5385

5386

5387

5389 return BinaryOperator::CreateAnd(X, Builder.CreateNot(Op0));

5390

5391

5393 return BinaryOperator::CreateAnd(X, Builder.CreateNot(Op1));

5394

5395

5396

5398 return BinaryOperator::CreateAnd(Op0, Builder.CreateNot(X));

5399

5400

5401

5402

5403

5406 return BinaryOperator::CreateAnd(Op1, Builder.CreateNot(X));

5407

5409

5412 return BinaryOperator::CreateXor(

5414

5415

5418 return BinaryOperator::CreateXor(

5420

5421

5424 return BinaryOperator::CreateOr(A, B);

5425

5428 return BinaryOperator::CreateOr(A, B);

5429

5430

5431

5435

5436

5438 return BinaryOperator::CreateOr(A, B);

5439

5440

5443

5444

5447

5448

5449

5453 if (B == C || B == D)

5455 if (A == C)

5457 if (A == D) {

5459 return BinaryOperator::CreateAnd(Builder.CreateXor(B, C), NotA);

5460 }

5461 }

5462

5463

5464 if (I.getType()->isIntOrIntVectorTy(1) &&

5468 if (B == C || B == D)

5470 if (A == C)

5472 if (A == D) {

5473 if (NeedFreeze)

5477 }

5478 }

5479

5482 if (Value *V = foldXorOfICmps(LHS, RHS, I))

5484

5485 if (Instruction *CastedXor = foldCastedBitwiseLogic(I))

5486 return CastedXor;

5487

5489 return Abs;

5490

5491

5492

5493

5494

5498 return BinaryOperator::CreateXor(Builder.CreateXor(X, Y), C1);

5499

5501 return R;

5502

5504 return Canonicalized;

5505

5506 if (Instruction *Folded = foldLogicOfIsFPClass(I, Op0, Op1))

5507 return Folded;

5508

5509 if (Instruction *Folded = canonicalizeConditionalNegationViaMathToSelect(I))

5510 return Folded;

5511

5512 if (Instruction *Res = foldBinOpOfDisplacedShifts(I))

5513 return Res;

5514

5516 return Res;

5517

5518 return nullptr;

5519}

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

AMDGPU Register Bank Select

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static bool isSigned(unsigned int Opcode)

static Value * foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd, bool IsLogical, InstCombiner::BuilderTy &Builder, const SimplifyQuery &Q, Instruction &I)

Reduce logic-of-compares with equality to a constant by substituting a common operand with the consta...

Definition InstCombineAndOrXor.cpp:1276

static Value * foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd, InstCombiner::BuilderTy &Builder, InstCombinerImpl &IC)

Fold (icmp eq ctpop(X) 1) | (icmp eq X 0) into (icmp ult ctpop(X) 2) and fold (icmp ne ctpop(X) 1) & ...

Definition InstCombineAndOrXor.cpp:943

static Value * foldBitmaskMul(Value *Op0, Value *Op1, InstCombiner::BuilderTy &Builder)

(A & N) * C + (A & M) * C -> (A & (N + M)) & C This also accepts the equivalent select form of (A & N...

Definition InstCombineAndOrXor.cpp:3925

static unsigned conjugateICmpMask(unsigned Mask)

Convert an analysis of a masked ICmp into its equivalent if all boolean operations had the opposite s...

Definition InstCombineAndOrXor.cpp:176

static Instruction * foldNotXor(BinaryOperator &I, InstCombiner::BuilderTy &Builder)

Definition InstCombineAndOrXor.cpp:4809

static Value * foldLogOpOfMaskedICmps(Value *LHS, Value *RHS, bool IsAnd, bool IsLogical, InstCombiner::BuilderTy &Builder, const SimplifyQuery &Q)

Try to fold (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E) into a single (icmp(A & X) ==/!...

Definition InstCombineAndOrXor.cpp:534

static Value * getFCmpValue(unsigned Code, Value *LHS, Value *RHS, InstCombiner::BuilderTy &Builder, FMFSource FMF)

This is the complement of getFCmpCode, which turns an opcode and two operands into either a FCmp inst...

Definition InstCombineAndOrXor.cpp:49

static bool matchIsFPClassLikeFCmp(Value *Op, Value *&ClassVal, uint64_t &ClassMask)

Match an fcmp against a special value that performs a test possible by llvm.is.fpclass.

Definition InstCombineAndOrXor.cpp:1580

static Value * foldSignedTruncationCheck(ICmpInst *ICmp0, ICmpInst *ICmp1, Instruction &CxtI, InstCombiner::BuilderTy &Builder)

General pattern: X & Y.

Definition InstCombineAndOrXor.cpp:847

static Instruction * visitMaskedMerge(BinaryOperator &I, InstCombiner::BuilderTy &Builder)

If we have a masked merge, in the canonical form of: (assuming that A only has one use....

Definition InstCombineAndOrXor.cpp:4777

static Instruction * canonicalizeAbs(BinaryOperator &Xor, InstCombiner::BuilderTy &Builder)

Canonicalize a shifty way to code absolute value to the more common pattern that uses negation and se...

Definition InstCombineAndOrXor.cpp:4843

static Value * foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd, InstCombiner::BuilderTy &Builder, InstCombinerImpl &IC)

Reduce a pair of compares that check if a value has exactly 1 bit set.

Definition InstCombineAndOrXor.cpp:973

static Value * foldUnsignedUnderflowCheck(ICmpInst *ZeroICmp, ICmpInst *UnsignedICmp, bool IsAnd, const SimplifyQuery &Q, InstCombiner::BuilderTy &Builder)

Commuted variants are assumed to be handled by calling this function again with the parameters swappe...

Definition InstCombineAndOrXor.cpp:1113

static Instruction * foldOrToXor(BinaryOperator &I, InstCombiner::BuilderTy &Builder)

Definition InstCombineAndOrXor.cpp:1954

static Value * simplifyAndOrWithOpReplaced(Value *V, Value *Op, Value *RepOp, bool SimplifyOnly, InstCombinerImpl &IC, unsigned Depth=0)

Definition InstCombineAndOrXor.cpp:2355

static Instruction * matchDeMorgansLaws(BinaryOperator &I, InstCombiner &IC)

Match variations of De Morgan's Laws: (~A & ~B) == (~(A | B)) (~A | ~B) == (~(A & B))

Definition InstCombineAndOrXor.cpp:1723

static Value * foldLogOpOfMaskedICmpsAsymmetric(Value *LHS, Value *RHS, bool IsAnd, Value *A, Value *B, Value *C, Value *D, Value *E, ICmpInst::Predicate PredL, ICmpInst::Predicate PredR, unsigned LHSMask, unsigned RHSMask, InstCombiner::BuilderTy &Builder)

Try to fold (icmp(A & B) ==/!= 0) &/| (icmp(A & D) ==/!= E) into a single (icmp(A & X) ==/!...

Definition InstCombineAndOrXor.cpp:503

static Value * FoldOrOfSelectSmaxToAbs(BinaryOperator &I, InstCombiner::BuilderTy &Builder)

Fold select(X >s 0, 0, -X) | smax(X, 0) --> abs(X) select(X <s 0, -X, 0) | smax(X,...

Definition InstCombineAndOrXor.cpp:4002

static Instruction * foldAndToXor(BinaryOperator &I, InstCombiner::BuilderTy &Builder)

Definition InstCombineAndOrXor.cpp:1928

static unsigned getMaskedICmpType(Value *A, Value *B, Value *C, ICmpInst::Predicate Pred)

Return the set of patterns (from MaskedICmpType) that (icmp SCC (A & B), C) satisfies.

Definition InstCombineAndOrXor.cpp:126

static Instruction * foldXorToXor(BinaryOperator &I, InstCombiner::BuilderTy &Builder)

A ^ B can be specified using other logic ops in a variety of patterns.

Definition InstCombineAndOrXor.cpp:4577

static bool canNarrowShiftAmt(Constant *C, unsigned BitWidth)

Return true if a constant shift amount is always less than the specified bit-width.

Definition InstCombineAndOrXor.cpp:1990

static Instruction * foldLogicCastConstant(BinaryOperator &Logic, CastInst *Cast, InstCombinerImpl &IC)

Fold {and,or,xor} (cast X), C.

Definition InstCombineAndOrXor.cpp:1776

static Value * foldAndOrOfICmpEqConstantAndICmp(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd, bool IsLogical, IRBuilderBase &Builder)

Definition InstCombineAndOrXor.cpp:3325

static bool canFreelyInvert(InstCombiner &IC, Value *Op, Instruction *IgnoredUser)

Definition InstCombineAndOrXor.cpp:4875

static Value * foldNegativePower2AndShiftedMask(Value *A, Value *B, Value *D, Value *E, ICmpInst::Predicate PredL, ICmpInst::Predicate PredR, InstCombiner::BuilderTy &Builder)

Try to fold (icmp(A & B) == 0) & (icmp(A & D) != E) into (icmp A u< D) iff B is a contiguous set of o...

Definition InstCombineAndOrXor.cpp:1015

static Value * matchIsFiniteTest(InstCombiner::BuilderTy &Builder, FCmpInst *LHS, FCmpInst *RHS)

and (fcmp ord x, 0), (fcmp u* x, inf) -> fcmp o* x, inf

Definition InstCombineAndOrXor.cpp:1434

static Value * foldPowerOf2AndShiftedMask(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd, InstCombiner::BuilderTy &Builder)

Try to fold ((icmp X u< P) & (icmp(X & M) != M)) or ((icmp X s> -1) & (icmp(X & M) !...

Definition InstCombineAndOrXor.cpp:1081

static Value * stripSignOnlyFPOps(Value *Val)

Ignore all operations which only change the sign of a value, returning the underlying magnitude value...

Definition InstCombineAndOrXor.cpp:1413

static Value * foldOrUnsignedUMulOverflowICmp(BinaryOperator &I, InstCombiner::BuilderTy &Builder, const DataLayout &DL)

Fold Res, Overflow = (umul.with.overflow x c1); (or Overflow (ugt Res c2)) --> (ugt x (c2/c1)).

Definition InstCombineAndOrXor.cpp:3981

static Value * freelyInvert(InstCombinerImpl &IC, Value *Op, Instruction *IgnoredUser)

Definition InstCombineAndOrXor.cpp:4882

static Value * foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(Value *LHS, Value *RHS, bool IsAnd, Value *A, Value *B, Value *D, Value *E, ICmpInst::Predicate PredL, ICmpInst::Predicate PredR, InstCombiner::BuilderTy &Builder)

Try to fold (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E) into a single (icmp(A & X) ==/!...

Definition InstCombineAndOrXor.cpp:353

static std::optional< IntPart > matchIntPart(Value *V)

Match an extraction of bits from an integer.

Definition InstCombineAndOrXor.cpp:1159

static Instruction * canonicalizeLogicFirst(BinaryOperator &I, InstCombiner::BuilderTy &Builder)

Definition InstCombineAndOrXor.cpp:2212

static Instruction * reassociateFCmps(BinaryOperator &BO, InstCombiner::BuilderTy &Builder)

This a limited reassociation for a special case (see above) where we are checking if two values are e...

Definition InstCombineAndOrXor.cpp:1682

static Value * getNewICmpValue(unsigned Code, bool Sign, Value *LHS, Value *RHS, InstCombiner::BuilderTy &Builder)

This is the complement of getICmpCode, which turns an opcode and two operands into either a constant ...

Definition InstCombineAndOrXor.cpp:39

static Value * extractIntPart(const IntPart &P, IRBuilderBase &Builder)

Materialize an extraction of bits from an integer in IR.

Definition InstCombineAndOrXor.cpp:1177

static bool matchUnorderedInfCompare(FCmpInst::Predicate P, Value *LHS, Value *RHS)

Matches fcmp u__ x, +/-inf.

Definition InstCombineAndOrXor.cpp:1426

static bool matchIsNotNaN(FCmpInst::Predicate P, Value *LHS, Value *RHS)

Matches canonical form of isnan, fcmp ord x, 0.

Definition InstCombineAndOrXor.cpp:1421

static bool areInverseVectorBitmasks(Constant *C1, Constant *C2)

If all elements of two constant vectors are 0/-1 and inverses, return true.

Definition InstCombineAndOrXor.cpp:3186

MaskedICmpType

Classify (icmp eq (A & B), C) and (icmp ne (A & B), C) as matching patterns that can be simplified.

Definition InstCombineAndOrXor.cpp:111

@ BMask_NotMixed

Definition InstCombineAndOrXor.cpp:121

@ AMask_NotMixed

Definition InstCombineAndOrXor.cpp:119

@ BMask_NotAllOnes

Definition InstCombineAndOrXor.cpp:115

@ Mask_AllZeros

Definition InstCombineAndOrXor.cpp:116

@ BMask_Mixed

Definition InstCombineAndOrXor.cpp:120

@ BMask_AllOnes

Definition InstCombineAndOrXor.cpp:114

@ AMask_NotAllOnes

Definition InstCombineAndOrXor.cpp:113

@ AMask_AllOnes

Definition InstCombineAndOrXor.cpp:112

@ Mask_NotAllZeros

Definition InstCombineAndOrXor.cpp:117

@ AMask_Mixed

Definition InstCombineAndOrXor.cpp:118

static Instruction * foldComplexAndOrPatterns(BinaryOperator &I, InstCombiner::BuilderTy &Builder)

Try folding relatively complex patterns for both And and Or operations with all And and Or swapped.

Definition InstCombineAndOrXor.cpp:2038

static bool matchZExtedSubInteger(Value *V, Value *&Int, APInt &Mask, uint64_t &Offset, bool &IsShlNUW, bool &IsShlNSW)

Match V as "lshr -> mask -> zext -> shl".

Definition InstCombineAndOrXor.cpp:3780

static std::optional< DecomposedBitMaskMul > matchBitmaskMul(Value *V)

Definition InstCombineAndOrXor.cpp:3867

static Value * foldOrOfInversions(BinaryOperator &I, InstCombiner::BuilderTy &Builder)

Definition InstCombineAndOrXor.cpp:3612

static bool matchSubIntegerPackFromVector(Value *V, Value *&Vec, int64_t &VecOffset, SmallBitVector &Mask, const DataLayout &DL)

Match V as "shufflevector -> bitcast" or "extractelement -> zext -> shl" patterns,...

Definition InstCombineAndOrXor.cpp:3640

static Instruction * matchFunnelShift(Instruction &Or, InstCombinerImpl &IC)

Match UB-safe variants of the funnel shift intrinsic.

Definition InstCombineAndOrXor.cpp:3111

static Instruction * reassociateForUses(BinaryOperator &BO, InstCombinerImpl::BuilderTy &Builder)

Try to reassociate a pair of binops so that values with one use only are part of the same instruction...

Definition InstCombineAndOrXor.cpp:2179

static Value * matchOrConcat(Instruction &Or, InstCombiner::BuilderTy &Builder)

Attempt to combine or(zext(x),shl(zext(y),bw/2) concat packing patterns.

Definition InstCombineAndOrXor.cpp:3123

static Value * foldAndOrOfICmpsWithPow2AndWithZero(InstCombiner::BuilderTy &Builder, ICmpInst *LHS, ICmpInst *RHS, bool IsAnd, const SimplifyQuery &Q)

Definition InstCombineAndOrXor.cpp:784

static Instruction * foldBitwiseLogicWithIntrinsics(BinaryOperator &I, InstCombiner::BuilderTy &Builder)

Definition InstCombineAndOrXor.cpp:2300

static std::optional< std::pair< unsigned, unsigned > > getMaskedTypeForICmpPair(Value *&A, Value *&B, Value *&C, Value *&D, Value *&E, Value *LHS, Value *RHS, ICmpInst::Predicate &PredL, ICmpInst::Predicate &PredR)

Handle (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E).

Definition InstCombineAndOrXor.cpp:210

static Instruction * foldIntegerPackFromVector(Instruction &I, InstCombiner::BuilderTy &Builder, const DataLayout &DL)

Try to fold the join of two scalar integers whose contents are packed elements of the same vector.

Definition InstCombineAndOrXor.cpp:3743

static Value * foldIntegerRepackThroughZExt(Value *Lhs, Value *Rhs, InstCombiner::BuilderTy &Builder)

Try to fold the join of two scalar integers whose bits are unpacked and zexted from the same source i...

Definition InstCombineAndOrXor.cpp:3821

This file provides internal interfaces used to implement the InstCombine.

This file provides the interface for the instcombine pass implementation.

static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)

uint64_t IntrinsicInst * II

const SmallVectorImpl< MachineOperand > & Cond

This file implements the SmallBitVector class.

static unsigned getScalarSizeInBits(Type *Ty)

static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")

static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")

static constexpr int Concat[]

The Input class is used to parse a yaml document into in-memory structs and vectors.

static LLVM_ABI bool hasSignBitInMSB(const fltSemantics &)

bool bitwiseIsEqual(const APFloat &RHS) const

APInt bitcastToAPInt() const

static APFloat getInf(const fltSemantics &Sem, bool Negative=false)

Factory for Positive and Negative Infinity.

Class for arbitrary precision integers.

LLVM_ABI APInt udiv(const APInt &RHS) const

Unsigned division operation.

static APInt getAllOnes(unsigned numBits)

Return an APInt of a specified width with all bits set.

LLVM_ABI APInt zext(unsigned width) const

Zero extend to a new width.

uint64_t getZExtValue() const

Get zero extended value.

LLVM_ABI APInt trunc(unsigned width) const

Truncate to new width.

unsigned countLeadingOnes() const

bool isAllOnes() const

Determine if all bits are set. This is true for zero-width values.

LLVM_ABI APInt usub_ov(const APInt &RHS, bool &Overflow) const

bool ugt(const APInt &RHS) const

Unsigned greater than comparison.

bool isZero() const

Determine if this value is zero, i.e. all bits are clear.

bool isSignMask() const

Check if the APInt's value is returned by getSignMask.

unsigned getBitWidth() const

Return the number of bits in the APInt.

bool ult(const APInt &RHS) const

Unsigned less than comparison.

LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const

bool intersects(const APInt &RHS) const

This operation tests if there are any pairs of corresponding bits between this APInt and RHS that are...

int32_t exactLogBase2() const

LLVM_ABI APInt reverseBits() const

LLVM_ABI APInt uadd_ov(const APInt &RHS, bool &Overflow) const

unsigned countr_zero() const

Count the number of trailing zero bits.

unsigned countLeadingZeros() const

bool ule(const APInt &RHS) const

Unsigned less or equal comparison.

APInt shl(unsigned shiftAmt) const

Left-shift function.

LLVM_ABI APInt byteSwap() const

bool isSubsetOf(const APInt &RHS) const

This operation checks that all bits set in this APInt are also set in RHS.

bool isPowerOf2() const

Check if this APInt's value is a power of two greater than zero.

static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)

Constructs an APInt value that has the bottom loBitsSet bits set.

LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const

static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)

Constructs an APInt value that has a contiguous range of bits set.

APInt lshr(unsigned shiftAmt) const

Logical right-shift function.

bool uge(const APInt &RHS) const

Unsigned greater or equal comparison.

void clearSignBit()

Set the sign bit to 0.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

LLVM_ABI bool isSigned() const

Whether the intrinsic is signed or unsigned.

LLVM_ABI Instruction::BinaryOps getBinaryOp() const

Returns the binary operation underlying the intrinsic.

BinaryOps getOpcode() const

static LLVM_ABI BinaryOperator * CreateNot(Value *Op, const Twine &Name="", InsertPosition InsertBefore=nullptr)

static LLVM_ABI BinaryOperator * Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name=Twine(), InsertPosition InsertBefore=nullptr)

Construct a binary instruction, given the opcode and the two operands.

static BinaryOperator * CreateWithCopiedFlags(BinaryOps Opc, Value *V1, Value *V2, Value *CopyO, const Twine &Name="", InsertPosition InsertBefore=nullptr)

This class represents a no-op cast from one type to another.

static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

This is the base class for all instructions that perform data casts.

Type * getSrcTy() const

Return the source type, as a convenience.

Instruction::CastOps getOpcode() const

Return the opcode of this CastInst.

static LLVM_ABI CastInst * Create(Instruction::CastOps, Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)

Provides a way to construct any of the CastInst subclasses using an opcode instead of the subclass's ...

Type * getDestTy() const

Return the destination type, as a convenience.

static Type * makeCmpResultType(Type *opnd_type)

Create a result type for fcmp/icmp.

Predicate

This enumeration lists the possible predicates for CmpInst subclasses.

@ ICMP_SLT

signed less than

@ ICMP_SLE

signed less or equal

@ FCMP_OLT

0 1 0 0 True if ordered and less than

@ FCMP_ULE

1 1 0 1 True if unordered, less than, or equal

@ ICMP_UGE

unsigned greater or equal

@ ICMP_UGT

unsigned greater than

@ ICMP_SGT

signed greater than

@ FCMP_ULT

1 1 0 0 True if unordered or less than

@ ICMP_ULT

unsigned less than

@ FCMP_OLE

0 1 0 1 True if ordered and less than or equal

@ FCMP_ORD

0 1 1 1 True if ordered (no nans)

@ ICMP_SGE

signed greater or equal

@ ICMP_ULE

unsigned less or equal

@ FCMP_UNO

1 0 0 0 True if unordered: isnan(X) | isnan(Y)

Predicate getSwappedPredicate() const

For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.

Predicate getInversePredicate() const

For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...

Predicate getPredicate() const

Return the predicate for this instruction.

static LLVM_ABI bool isUnordered(Predicate predicate)

Determine if the predicate is an unordered operation.

static Predicate getOrderedPredicate(Predicate Pred)

Returns the ordered variant of a floating point compare.

An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...

static LLVM_ABI Constant * getSub(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)

static LLVM_ABI Constant * getNot(Constant *C)

static LLVM_ABI Constant * getXor(Constant *C1, Constant *C2)

static LLVM_ABI Constant * getAdd(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)

static LLVM_ABI Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)

static LLVM_ABI Constant * getExactLogBase2(Constant *C)

If C is a scalar/fixed width vector of known powers of 2, then this function returns a new scalar/fix...

static LLVM_ABI Constant * getZero(Type *Ty, bool Negative=false)

This is the shared class of boolean and integer constants.

bool isMinusOne() const

This function will return true iff every bit in this constant is set to true.

static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)

bool isZero() const

This is just a convenience method to make client code smaller for a common code.

static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)

uint64_t getZExtValue() const

Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...

const APInt & getValue() const

Return the constant as an APInt value reference.

LLVM_ABI std::optional< ConstantRange > exactUnionWith(const ConstantRange &CR) const

Union the two ranges and return the result if it can be represented exactly, otherwise return std::nu...

LLVM_ABI ConstantRange subtract(const APInt &CI) const

Subtract the specified constant from the endpoints of this constant range.

static LLVM_ABI ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred, const APInt &Other)

Produce the exact range such that all values in the returned range satisfy the given predicate with a...

LLVM_ABI std::optional< ConstantRange > exactIntersectWith(const ConstantRange &CR) const

Intersect the two ranges and return the result if it can be represented exactly, otherwise return std...

This is an important base class in LLVM.

static LLVM_ABI Constant * replaceUndefsWith(Constant *C, Constant *Replacement)

Try to replace undefined constant C or undefined elements in C with Replacement.

static LLVM_ABI Constant * mergeUndefsWith(Constant *C, Constant *Other)

Merges undefs of a Constant with another Constant, along with the undefs already present.

static LLVM_ABI Constant * getAllOnesValue(Type *Ty)

static LLVM_ABI Constant * getNullValue(Type *Ty)

Constructor to create a '0' constant of arbitrary type.

LLVM_ABI Constant * getAggregateElement(unsigned Elt) const

For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...

LLVM_ABI bool isZeroValue() const

Return true if the value is negative zero or null value.

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

This instruction compares its operands according to the predicate given to the constructor.

This provides a helper for copying FMF from an instruction or setting specified flags.

static FMFSource intersect(Value *A, Value *B)

Intersect the FMF from two instructions.

This instruction compares its operands according to the predicate given to the constructor.

Predicate getSignedPredicate() const

For example, EQ->EQ, SLE->SLE, UGT->SGT, etc.

bool isEquality() const

Return true if this predicate is either EQ or NE.

static bool isEquality(Predicate P)

Return true if this predicate is either EQ or NE.

Common base class shared among various IRBuilders.

Value * CreateNot(Value *V, const Twine &Name="")

Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)

void SetInsertPoint(BasicBlock *TheBB)

This specifies that created instructions should be appended to the end of the specified block.

Instruction * canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(BinaryOperator &I)

Instruction * foldBinOpIntoSelectOrPhi(BinaryOperator &I)

This is a convenience wrapper function for the above two functions.

Instruction * visitOr(BinaryOperator &I)

Definition InstCombineAndOrXor.cpp:4024

bool SimplifyAssociativeOrCommutative(BinaryOperator &I)

Performs a few simplifications for operators which are associative or commutative.

Value * foldUsingDistributiveLaws(BinaryOperator &I)

Tries to simplify binary operations which some other binary operation distributes over.

Instruction * foldBinOpShiftWithShift(BinaryOperator &I)

Value * insertRangeTest(Value *V, const APInt &Lo, const APInt &Hi, bool isSigned, bool Inside)

Emit a computation of: (V >= Lo && V < Hi) if Inside is true, otherwise (V < Lo || V >= Hi).

Definition InstCombineAndOrXor.cpp:60

bool sinkNotIntoLogicalOp(Instruction &I)

Definition InstCombineAndOrXor.cpp:4898

std::optional< std::pair< Intrinsic::ID, SmallVector< Value *, 3 > > > convertOrOfShiftsToFunnelShift(Instruction &Or)

Definition InstCombineAndOrXor.cpp:2925

Instruction * visitAnd(BinaryOperator &I)

Definition InstCombineAndOrXor.cpp:2416

bool sinkNotIntoOtherHandOfLogicalOp(Instruction &I)

Definition InstCombineAndOrXor.cpp:4950

Instruction * foldBinopWithPhiOperands(BinaryOperator &BO)

For a binary operator with 2 phi operands, try to hoist the binary operation before the phi.

Instruction * foldAddLikeCommutative(Value *LHS, Value *RHS, bool NSW, bool NUW)

Common transforms for add / disjoint or.

Value * simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, bool Inverted)

Try to fold a signed range checked with lower bound 0 to an unsigned icmp.

Definition InstCombineAndOrXor.cpp:724

Instruction * tryFoldInstWithCtpopWithNot(Instruction *I)

Value * SimplifyAddWithRemainder(BinaryOperator &I)

Tries to simplify add operations using the definition of remainder.

Instruction * visitXor(BinaryOperator &I)

Definition InstCombineAndOrXor.cpp:5185

bool SimplifyDemandedInstructionBits(Instruction &Inst)

Tries to simplify operands to an integer instruction based on its demanded bits.

Instruction * foldVectorBinop(BinaryOperator &Inst)

Canonicalize the position of binops relative to shufflevector.

Instruction * matchBSwapOrBitReverse(Instruction &I, bool MatchBSwaps, bool MatchBitReversals)

Given an initial instruction, check to see if it is the root of a bswap/bitreverse idiom.

Definition InstCombineAndOrXor.cpp:2907

void freelyInvertAllUsersOf(Value *V, Value *IgnoredUser=nullptr)

Freely adapt every user of V as-if V was changed to !V.

The core instruction combiner logic.

const DataLayout & getDataLayout() const

IRBuilder< TargetFolder, IRBuilderCallbackInserter > BuilderTy

An IRBuilder that automatically inserts new instructions into the worklist.

bool isFreeToInvert(Value *V, bool WillInvertAllUses, bool &DoesConsume)

Return true if the specified value is free to invert (apply ~ to).

unsigned ComputeNumSignBits(const Value *Op, const Instruction *CxtI=nullptr, unsigned Depth=0) const

Instruction * replaceInstUsesWith(Instruction &I, Value *V)

A combiner-aware RAUW-like routine.

InstructionWorklist & Worklist

A worklist of the instructions that need to be simplified.

void computeKnownBits(const Value *V, KnownBits &Known, const Instruction *CxtI, unsigned Depth=0) const

static Value * peekThroughBitcast(Value *V, bool OneUseOnly=false)

Return the source operand of a potentially bitcasted value while optionally checking if it has one us...

bool canFreelyInvertAllUsersOf(Instruction *V, Value *IgnoredUser)

Given i1 V, can every user of V be freely adapted if V is changed to !V ?

void addToWorklist(Instruction *I)

bool MaskedValueIsZero(const Value *V, const APInt &Mask, const Instruction *CxtI=nullptr, unsigned Depth=0) const

Value * getFreelyInverted(Value *V, bool WillInvertAllUses, BuilderTy *Builder, bool &DoesConsume)

const SimplifyQuery & getSimplifyQuery() const

bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero=false, const Instruction *CxtI=nullptr, unsigned Depth=0)

LLVM_ABI void removeFromParent()

This method unlinks 'this' from the containing basic block, but does not delete it.

unsigned getOpcode() const

Returns a member of one of the enums like Instruction::Add.

A wrapper class for inspecting calls to intrinsic functions.

This class represents a sign extension of integer types.

static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, const Instruction *MDFrom=nullptr)

This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

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

LLVM_ABI unsigned getIntegerBitWidth() const

bool isVectorTy() const

True if this is an instance of VectorType.

bool isIntOrIntVectorTy() const

Return true if this is an integer type or a vector of integer types.

Type * getScalarType() const

If this is a vector type, return the element type, otherwise return 'this'.

LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY

Return the basic size of this type if it is a primitive type.

LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const

Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...

LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY

If this is a vector type, return the getPrimitiveSizeInBits value for the element type.

bool isFloatingPointTy() const

Return true if this is one of the floating-point types.

LLVM_ABI const fltSemantics & getFltSemantics() const

A Use represents the edge between a Value definition and its users.

Value * getOperand(unsigned i) const

LLVM Value Representation.

Type * getType() const

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

bool hasOneUse() const

Return true if there is exactly one use of this value.

iterator_range< user_iterator > users()

LLVM_ABI bool hasNUsesOrMore(unsigned N) const

Return true if this value has N uses or more.

LLVM_ABI bool hasNUses(unsigned N) const

Return true if this Value has exactly N uses.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

LLVM_ABI void takeName(Value *V)

Transfer the name from V to this value.

static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)

This static method is the primary way to construct an VectorType.

Represents an op.with.overflow intrinsic.

This class represents zero extension of integer types.

constexpr ScalarTy getKnownMinValue() const

Returns the minimum value this quantity can represent.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

const APInt & umin(const APInt &A, const APInt &B)

Determine the smaller of two APInts considered to be unsigned.

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.

@ C

The default llvm calling convention, compatible with C.

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

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

SpecificConstantMatch m_ZeroInt()

Convenience matchers for specific integer values.

BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)

Matches a register negated by a G_SUB.

BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)

Matches a register not-ed by a G_XOR.

OneUse_match< SubPat > m_OneUse(const SubPat &SP)

cst_pred_ty< is_all_ones > m_AllOnes()

Match an integer or vector with all bits set.

cst_pred_ty< is_lowbit_mask > m_LowBitMask()

Match an integer or vector with only the low bit(s) set.

BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)

cst_pred_ty< is_negative > m_Negative()

Match an integer or vector of negative values.

BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)

class_match< BinaryOperator > m_BinOp()

Match an arbitrary binary operation and ignore it.

CmpClass_match< LHS, RHS, FCmpInst > m_FCmp(CmpPredicate &Pred, const LHS &L, const RHS &R)

cst_pred_ty< is_sign_mask > m_SignMask()

Match an integer or vector with only the sign bit(s) set.

BinaryOp_match< LHS, RHS, Instruction::AShr > m_AShr(const LHS &L, const RHS &R)

cstfp_pred_ty< is_inf > m_Inf()

Match a positive or negative infinity FP constant.

m_Intrinsic_Ty< Opnd0 >::Ty m_BitReverse(const Opnd0 &Op0)

cst_pred_ty< is_power2 > m_Power2()

Match an integer or vector power-of-2.

match_combine_or< CastInst_match< OpTy, TruncInst >, OpTy > m_TruncOrSelf(const OpTy &Op)

auto m_LogicalOp()

Matches either L && R or L || R where L and R are arbitrary values.

class_match< Constant > m_Constant()

Match an arbitrary Constant and ignore it.

ap_match< APInt > m_APInt(const APInt *&Res)

Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.

BinaryOp_match< LHS, RHS, Instruction::And, true > m_c_And(const LHS &L, const RHS &R)

Matches an And with LHS and RHS in either order.

CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)

Matches Trunc.

BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)

ap_match< APInt > m_APIntAllowPoison(const APInt *&Res)

Match APInt while allowing poison in splat vector constants.

OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoSignedWrap > m_NSWSub(const LHS &L, const RHS &R)

specific_intval< false > m_SpecificInt(const APInt &V)

Match a specific integer value or vector with all elements equal to the value.

match_combine_or< CastInst_match< OpTy, ZExtInst >, OpTy > m_ZExtOrSelf(const OpTy &Op)

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

cst_pred_ty< is_shifted_mask > m_ShiftedMask()

bind_ty< Instruction > m_Instruction(Instruction *&I)

Match an instruction, capturing it if we match.

cstfp_pred_ty< is_any_zero_fp > m_AnyZeroFP()

Match a floating-point negative zero or positive zero.

specificval_ty m_Specific(const Value *V)

Match if we have a specific specified value.

DisjointOr_match< LHS, RHS > m_DisjointOr(const LHS &L, const RHS &R)

constantexpr_match m_ConstantExpr()

Match a constant expression or a constant that contains a constant expression.

specific_intval< true > m_SpecificIntAllowPoison(const APInt &V)

ap_match< APFloat > m_APFloatAllowPoison(const APFloat *&Res)

Match APFloat while allowing poison in splat vector constants.

CmpClass_match< LHS, RHS, ICmpInst, true > m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)

Matches an ICmp with a predicate over LHS and RHS in either order.

TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)

Matches ExtractElementInst.

cst_pred_ty< is_nonnegative > m_NonNegative()

Match an integer or vector of non-negative values.

class_match< ConstantInt > m_ConstantInt()

Match an arbitrary ConstantInt and ignore it.

cst_pred_ty< is_one > m_One()

Match an integer 1 or a vector with all elements equal to 1.

IntrinsicID_match m_Intrinsic()

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

ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)

Matches SelectInst.

match_combine_or< CastInst_match< OpTy, SExtInst >, OpTy > m_SExtOrSelf(const OpTy &Op)

ExtractValue_match< Ind, Val_t > m_ExtractValue(const Val_t &V)

Match a single index ExtractValue instruction.

BinOpPred_match< LHS, RHS, is_logical_shift_op > m_LogicalShift(const LHS &L, const RHS &R)

Matches logical shift operations.

ShiftLike_match< LHS, Instruction::Shl > m_ShlOrSelf(const LHS &L, uint64_t &R)

Matches shl L, ConstShAmt or L itself (R will be set to zero in this case).

bind_ty< WithOverflowInst > m_WithOverflowInst(WithOverflowInst *&I)

Match a with overflow intrinsic, capturing it if we match.

BinaryOp_match< LHS, RHS, Instruction::Xor, true > m_c_Xor(const LHS &L, const RHS &R)

Matches an Xor with LHS and RHS in either order.

SpecificCmpClass_match< LHS, RHS, CmpInst > m_SpecificCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)

BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)

deferredval_ty< Value > m_Deferred(Value *const &V)

Like m_Specific(), but works if the specific value to match is determined as part of the same match()...

auto m_LogicalOr()

Matches L || R where L and R are arbitrary values.

TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)

Matches ShuffleVectorInst independently of mask value.

SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)

CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)

Matches ZExt.

class_match< CmpInst > m_Cmp()

Matches any compare instruction and ignore it.

cst_pred_ty< is_negated_power2 > m_NegatedPower2()

Match a integer or vector negated power-of-2.

match_immconstant_ty m_ImmConstant()

Match an arbitrary immediate Constant and ignore it.

DisjointOr_match< LHS, RHS, true > m_c_DisjointOr(const LHS &L, const RHS &R)

BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)

Matches a Add with LHS and RHS in either order.

SpecificCmpClass_match< LHS, RHS, FCmpInst > m_SpecificFCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)

match_combine_or< BinaryOp_match< LHS, RHS, Instruction::Add >, DisjointOr_match< LHS, RHS > > m_AddLike(const LHS &L, const RHS &R)

Match either "add" or "or disjoint".

CastOperator_match< OpTy, Instruction::BitCast > m_BitCast(const OpTy &Op)

Matches BitCast.

match_combine_or< match_combine_or< MaxMin_match< ICmpInst, LHS, RHS, smax_pred_ty, true >, MaxMin_match< ICmpInst, LHS, RHS, smin_pred_ty, true > >, match_combine_or< MaxMin_match< ICmpInst, LHS, RHS, umax_pred_ty, true >, MaxMin_match< ICmpInst, LHS, RHS, umin_pred_ty, true > > > m_c_MaxOrMin(const LHS &L, const RHS &R)

match_combine_or< CastInst_match< OpTy, SExtInst >, NNegZExt_match< OpTy > > m_SExtLike(const OpTy &Op)

Match either "sext" or "zext nneg".

MaxMin_match< ICmpInst, LHS, RHS, smax_pred_ty > m_SMax(const LHS &L, const RHS &R)

cst_pred_ty< is_maxsignedvalue > m_MaxSignedValue()

Match an integer or vector with values having all bits except for the high bit set (0x7f....

class_match< Value > m_Value()

Match an arbitrary value and ignore it.

AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)

Matches a BinaryOperator with LHS and RHS in either order.

BinaryOp_match< LHS, RHS, Instruction::LShr > m_LShr(const LHS &L, const RHS &R)

CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)

match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)

FNeg_match< OpTy > m_FNeg(const OpTy &X)

Match 'fneg X' as 'fsub -0.0, X'.

BinOpPred_match< LHS, RHS, is_shift_op > m_Shift(const LHS &L, const RHS &R)

Matches shift operations.

cstfp_pred_ty< is_pos_zero_fp > m_PosZeroFP()

Match a floating-point positive zero.

BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)

auto m_LogicalAnd()

Matches L && R where L and R are arbitrary values.

BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(const LHS &L, const RHS &R)

m_Intrinsic_Ty< Opnd0 >::Ty m_BSwap(const Opnd0 &Op0)

CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)

Matches SExt.

is_zero m_Zero()

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

BinaryOp_match< LHS, RHS, Instruction::Or, true > m_c_Or(const LHS &L, const RHS &R)

Matches an Or with LHS and RHS in either order.

ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)

Matches InsertElementInst.

ElementWiseBitCast_match< OpTy > m_ElementWiseBitCast(const OpTy &Op)

m_Intrinsic_Ty< Opnd0 >::Ty m_FAbs(const Opnd0 &Op0)

m_Intrinsic_Ty< Opnd0, Opnd1 >::Ty m_CopySign(const Opnd0 &Op0, const Opnd1 &Op1)

BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)

match_unless< Ty > m_Unless(const Ty &M)

Match if the inner matcher does NOT match.

match_combine_or< LTy, RTy > m_CombineOr(const LTy &L, const RTy &R)

Combine two pattern matchers matching L || R.

cst_pred_ty< icmp_pred_with_threshold > m_SpecificInt_ICMP(ICmpInst::Predicate Predicate, const APInt &Threshold)

Match an integer or vector with every element comparing 'pred' (eg/ne/...) to Threshold.

NodeAddr< CodeNode * > Code

friend class Instruction

Iterator for Instructions in a `BasicBlock.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI Intrinsic::ID getInverseMinMaxIntrinsic(Intrinsic::ID MinMaxID)

@ Low

Lower the current thread's priority such that it does not affect foreground tasks significantly.

FunctionAddr VTableAddr Value

Constant * getPredForFCmpCode(unsigned Code, Type *OpTy, CmpInst::Predicate &Pred)

This is the complement of getFCmpCode.

LLVM_ABI bool isSignBitCheck(ICmpInst::Predicate Pred, const APInt &RHS, bool &TrueIfSigned)

Given an exploded icmp instruction, return true if the comparison only checks the sign bit.

decltype(auto) dyn_cast(const From &Val)

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

bool predicatesFoldable(CmpInst::Predicate P1, CmpInst::Predicate P2)

Return true if both predicates match sign or if at least one of them is an equality comparison (which...

LLVM_ABI Constant * ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, const Instruction *I=nullptr)

Attempt to constant fold a compare instruction (icmp/fcmp) with the specified operands.

LLVM_ABI Value * simplifyOrInst(Value *LHS, Value *RHS, const SimplifyQuery &Q)

Given operands for an Or, fold the result or return null.

LLVM_ABI Value * simplifyXorInst(Value *LHS, Value *RHS, const SimplifyQuery &Q)

Given operands for an Xor, fold the result or return null.

LLVM_ABI bool isGuaranteedNotToBeUndef(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)

Returns true if V cannot be undef, but may be poison.

LLVM_ABI bool matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO, Value *&Start, Value *&Step)

Attempt to match a simple first order recurrence cycle of the form: iv = phi Ty [Start,...

LLVM_ABI bool isKnownNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)

Returns true if the given value is known be negative (i.e.

LLVM_ABI Constant * getLosslessUnsignedTrunc(Constant *C, Type *DestTy, const DataLayout &DL, PreservedCastFlags *Flags=nullptr)

LLVM_ABI bool recognizeBSwapOrBitReverseIdiom(Instruction *I, bool MatchBSwaps, bool MatchBitReversals, SmallVectorImpl< Instruction * > &InsertedInsts)

Try to match a bswap or bitreverse idiom.

constexpr bool isPowerOf2_32(uint32_t Value)

Return true if the argument is a power of two > 0.

LLVM_ABI Value * simplifyICmpInst(CmpPredicate Pred, Value *LHS, Value *RHS, const SimplifyQuery &Q)

Given operands for an ICmpInst, fold the result or return null.

LLVM_ABI Constant * getLosslessSignedTrunc(Constant *C, Type *DestTy, const DataLayout &DL, PreservedCastFlags *Flags=nullptr)

LLVM_ABI Value * simplifyAndInst(Value *LHS, Value *RHS, const SimplifyQuery &Q)

Given operands for an And, fold the result or return null.

LLVM_ABI bool isKnownInversion(const Value *X, const Value *Y)

Return true iff:

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.

constexpr int PoisonMaskElem

LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)

Given operands for a BinaryOperator, fold the result or return null.

std::optional< DecomposedBitTest > decomposeBitTest(Value *Cond, bool LookThroughTrunc=true, bool AllowNonZeroC=false, bool DecomposeAnd=false)

Decompose an icmp into the form ((X & Mask) pred C) if possible.

@ Mul

Product of integers.

@ Xor

Bitwise or logical XOR of integers.

@ And

Bitwise or logical AND of integers.

@ Sub

Subtraction of integers.

DWARFExpression::Operation Op

LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)

Return true if this function can prove that V does not have undef bits and is never poison.

constexpr unsigned BitWidth

decltype(auto) cast(const From &Val)

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

APFloat neg(APFloat X)

Returns the negated value of the argument.

cl::opt< bool > ProfcheckDisableMetadataFixes("profcheck-disable-metadata-fixes", cl::Hidden, cl::init(false), cl::desc("Disable metadata propagation fixes discovered through Issue #147390"))

unsigned getICmpCode(CmpInst::Predicate Pred)

Encode a icmp predicate into a three bit mask.

LLVM_ABI bool isKnownToBeAPowerOfTwo(const Value *V, const DataLayout &DL, bool OrZero=false, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)

Return true if the given value is known to have exactly one bit set when defined.

LLVM_ABI bool isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)

Returns true if V cannot be poison, but may be undef.

std::pair< Value *, FPClassTest > fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS, Value *RHS, bool LookThroughSrc=true)

Returns a pair of values, which if passed to llvm.is.fpclass, returns the same result as an fcmp with...

unsigned getFCmpCode(CmpInst::Predicate CC)

Similar to getICmpCode but for FCmpInst.

std::optional< DecomposedBitTest > decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate Pred, bool LookThroughTrunc=true, bool AllowNonZeroC=false, bool DecomposeAnd=false)

Decompose an icmp into the form ((X & Mask) pred C) if possible.

Constant * getPredForICmpCode(unsigned Code, bool Sign, Type *OpTy, CmpInst::Predicate &Pred)

This is the complement of getICmpCode.

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.

Value * X

Definition InstCombineAndOrXor.cpp:3855

bool NSW

Definition InstCombineAndOrXor.cpp:3859

APInt Factor

Definition InstCombineAndOrXor.cpp:3856

APInt Mask

Definition InstCombineAndOrXor.cpp:3857

bool isCombineableWith(const DecomposedBitMaskMul Other)

Definition InstCombineAndOrXor.cpp:3861

bool NUW

Definition InstCombineAndOrXor.cpp:3858

unsigned NumBits

Definition InstCombineAndOrXor.cpp:1155

Value * From

Definition InstCombineAndOrXor.cpp:1153

unsigned StartBit

Definition InstCombineAndOrXor.cpp:1154

bool isNonNegative() const

Returns true if this value is known to be non-negative.

APInt getMaxValue() const

Return the maximal unsigned value possible given these KnownBits.

SimplifyQuery getWithInstruction(const Instruction *I) const