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

1

2

3

4

5

6

7

8

9

10

11

12

43#include

44#include

45

46#define DEBUG_TYPE "instcombine"

48

49using namespace llvm;

50using namespace PatternMatch;

51

52

53

54

58

63 return nullptr;

64

65 bool IsEq;

67 IsEq = Pred == ICmpInst::ICMP_EQ;

68 else if (Pred == FCmpInst::FCMP_OEQ)

69 IsEq = true;

70 else if (Pred == FCmpInst::FCMP_UNE)

71 IsEq = false;

72 else

73 return nullptr;

74

75

78 return nullptr;

79

80

81

84 if (IdC != C) {

86 return nullptr;

88 return nullptr;

89 }

90

91

94 return nullptr;

96 return nullptr;

97

98

99

100 if (isa(BO))

104 return nullptr;

105

106

107

108

109

111}

112

113

114

115

116

117

118

119

120

121

124 const APInt *SelTC, *SelFC;

127 return nullptr;

128

129

131 if (SelType->isVectorTy() != Cmp->getType()->isVectorTy())

132 return nullptr;

133

136 bool CreateAnd = false;

139 if (match(Cmp->getOperand(1), m_Zero()))

140 return nullptr;

141

142 V = Cmp->getOperand(0);

143 const APInt *AndRHS;

145 return nullptr;

146

147 AndMask = *AndRHS;

149 Cmp->getOperand(1), Pred)) {

151 if (!Res->Mask.isPowerOf2())

152 return nullptr;

153

154 V = Res->X;

155 AndMask = Res->Mask;

156 Pred = Res->Pred;

157 CreateAnd = true;

158 } else {

159 return nullptr;

160 }

161 if (Pred == ICmpInst::ICMP_NE)

163

164

165

166

167

168 const APInt &TC = *SelTC;

169 const APInt &FC = *SelFC;

170 if (!TC.isZero() && !FC.isZero()) {

172 return nullptr;

173

174

175 if (CreateAnd && !Cmp->hasOneUse())

176 return nullptr;

177

178

179

180

181

182 Constant *TCC = ConstantInt::get(SelType, TC);

183 Constant *FCC = ConstantInt::get(SelType, FC);

184 Constant *MaskC = ConstantInt::get(SelType, AndMask);

185 for (auto Opc : {Instruction::Or, Instruction::Xor, Instruction::Add,

186 Instruction::Sub}) {

188 FCC) {

189 if (CreateAnd)

192 }

193 }

194

195 return nullptr;

196 }

197

198

199 if (!TC.isPowerOf2() && !FC.isPowerOf2())

200 return nullptr;

201

202

203

204 const APInt &ValC = !TC.isZero() ? TC : FC;

205 unsigned ValZeros = ValC.logBase2();

206 unsigned AndZeros = AndMask.logBase2();

207 bool ShouldNotVal = !TC.isZero();

208

209

210

211

212 if (CreateAnd && ShouldNotVal && ValZeros != AndZeros)

213 return nullptr;

214

215

216 if (CreateAnd)

217 V = Builder.CreateAnd(V, ConstantInt::get(V->getType(), AndMask));

218

219

220

221 if (ValZeros > AndZeros) {

223 V = Builder.CreateShl(V, ValZeros - AndZeros);

224 } else if (ValZeros < AndZeros) {

225 V = Builder.CreateLShr(V, AndZeros - ValZeros);

227 } else {

229 }

230

231

232

233 if (ShouldNotVal)

235

236 return V;

237}

238

239

240

241

242

243

244

245

246

247

248

250 switch (I->getOpcode()) {

251 case Instruction::Add:

252 case Instruction::FAdd:

253 case Instruction::Mul:

254 case Instruction::FMul:

255 case Instruction::And:

256 case Instruction::Or:

257 case Instruction::Xor:

258 return 3;

259 case Instruction::Sub:

260 case Instruction::FSub:

261 case Instruction::FDiv:

262 case Instruction::Shl:

263 case Instruction::LShr:

264 case Instruction::AShr:

265 return 1;

266 default:

267 return 0;

268 }

269}

270

271

274

275

276

277

282 return nullptr;

283

284

286 Type *CondTy = Cond->getType();

290 return nullptr;

291

292

293

294 if (auto *CondVTy = dyn_cast(CondTy)) {

296 CondVTy->getElementCount() !=

297 cast(FIOpndTy)->getElementCount())

298 return nullptr;

299

300

301

302

303

304

305

306

307

308 if (TI->getOpcode() != Instruction::BitCast &&

310 return nullptr;

312

313

314

315 return nullptr;

316 }

317

318

321 SI.getName() + ".v", &SI);

324 }

325

326 Value *OtherOpT, *OtherOpF;

327 bool MatchIsOpZero;

329 bool Swapped = false) -> Value * {

330 assert(!(Commute && Swapped) &&

331 "Commute and Swapped can't set at the same time");

332 if (!Swapped) {

336 MatchIsOpZero = true;

341 MatchIsOpZero = false;

343 }

344 }

345

346 if (!Commute && !Swapped)

347 return nullptr;

348

349

350

351

355 MatchIsOpZero = true;

360 MatchIsOpZero = false;

362 }

363 return nullptr;

364 };

365

367

370

371

374 FMF |= SI.getFastMathFlags();

377 if (auto *NewSelI = dyn_cast(NewSel))

378 NewSelI->setFastMathFlags(FMF);

379 Instruction *NewFNeg = UnaryOperator::CreateFNeg(NewSel);

381 return NewFNeg;

382 }

383

384

385

386

387

388 auto *TII = dyn_cast(TI);

389 auto *FII = dyn_cast(FI);

390 if (TII && FII && TII->getIntrinsicID() == FII->getIntrinsicID()) {

392 if (Value *MatchOp = getCommonOp(TI, FI, true)) {

396 }

397 }

398

399

400

401

402

403

404 if (TII->getIntrinsicID() == Intrinsic::ldexp) {

405 Value *LdexpVal0 = TII->getArgOperand(0);

406 Value *LdexpExp0 = TII->getArgOperand(1);

407 Value *LdexpVal1 = FII->getArgOperand(0);

408 Value *LdexpExp1 = FII->getArgOperand(1);

410 FPMathOperator *SelectFPOp = cast(&SI);

411 FastMathFlags FMF = cast(TII)->getFastMathFlags();

412 FMF &= cast(FII)->getFastMathFlags();

414

417

419 TII->getType(), Intrinsic::ldexp, {SelectVal, SelectExp});

422 }

423 }

424 }

425

426

427

435 if (Value *MatchOp =

438 SI.getName() + ".v", &SI);

441 MatchOp, NewSel);

442 }

443 }

444 }

445 }

446

447

448

449

450

453 (!isa(TI) && !isa(TI)) ||

455 return nullptr;

456

457

459 if (!MatchOp)

460 return nullptr;

461

462

463

464

467 return nullptr;

468

469

470

471

472

473

474

475 auto *BO = dyn_cast(TI);

477

478

479 if (BO->getOpcode() == Instruction::SDiv ||

480 BO->getOpcode() == Instruction::SRem || MatchIsOpZero)

482 }

483

484

486 SI.getName() + ".v", &SI);

487 Value *Op0 = MatchIsOpZero ? MatchOp : NewSI;

488 Value *Op1 = MatchIsOpZero ? NewSI : MatchOp;

489 if (auto *BO = dyn_cast(TI)) {

493 return NewBO;

494 }

495 if (auto *TGEP = dyn_cast(TI)) {

496 auto *FGEP = cast(FI);

497 Type *ElementType = TGEP->getSourceElementType();

499 ElementType, Op0, Op1, TGEP->getNoWrapFlags() & FGEP->getNoWrapFlags());

500 }

502 return nullptr;

503}

504

506 if (!C1I.isZero() && !C2I.isZero())

507 return false;

509}

510

511

512

514 Value *FalseVal) {

515

516

517 auto TryFoldSelectIntoOp = [&](SelectInst &SI, Value *TrueVal,

520 auto *TVI = dyn_cast(TrueVal);

521 if (!TVI || !TVI->hasOneUse() || isa(FalseVal))

522 return nullptr;

523

525 unsigned OpToFold = 0;

526 if ((SFO & 1) && FalseVal == TVI->getOperand(0))

527 OpToFold = 1;

528 else if ((SFO & 2) && FalseVal == TVI->getOperand(1))

529 OpToFold = 2;

530

531 if (!OpToFold)

532 return nullptr;

533

535 if (isa(&SI))

536 FMF = SI.getFastMathFlags();

538 TVI->getOpcode(), TVI->getType(), true, FMF.noSignedZeros());

539 Value *OOp = TVI->getOperand(2 - OpToFold);

540

541

542 const APInt *OOpC;

544 if (isa(OOp) &&

545 (!OOpIsAPInt || isSelect01(C->getUniqueInteger(), *OOpC)))

546 return nullptr;

547

548

549

550

551

552

553

554 if (isa(&SI) &&

556 return nullptr;

557

559 Swapped ? OOp : C, "", &SI);

560 if (isa(&SI))

561 cast(NewSel)->setFastMathFlags(FMF);

566 if (isa(&SI)) {

567

570

571

573 }

574 return BO;

575 };

576

577 if (Instruction *R = TryFoldSelectIntoOp(SI, TrueVal, FalseVal, false))

578 return R;

579

580 if (Instruction *R = TryFoldSelectIntoOp(SI, FalseVal, TrueVal, true))

581 return R;

582

583 return nullptr;

584}

585

586

587

588

589

590

591

592

593

597 if (!(Cmp->hasOneUse() && Cmp->getOperand(0)->hasOneUse() &&

600 return nullptr;

601

602

605 return nullptr;

606

607

610

611

612

613

614 if (HasShift &&

618 return nullptr;

619

620 if (!HasShift)

621 X = B;

622

625 return nullptr;

626

627

628

629 Constant *One = ConstantInt::get(SelType, 1);

630 Value *MaskB = HasShift ? Builder.CreateShl(One, Z) : One;

634 return new ZExtInst(ICmpNeZero, SelType);

635}

636

637

638

639

640

641

648 return nullptr;

649

653 }

654

656 const APInt *C2, *C1;

660 return nullptr;

661

664 return nullptr;

665

666 auto *FI = dyn_cast(FVal);

667 if (!FI)

668 return nullptr;

669

670 FI->setHasNoSignedWrap(false);

671 FI->setHasNoUnsignedWrap(false);

672 return FVal;

673}

674

675

676

677

678

679

687 return nullptr;

688

697 return nullptr;

698

699

702

706 const auto *Ashr = cast(FalseVal);

707

708 bool IsExact = Ashr->isExact() && cast(TrueVal)->isExact();

710 }

711

712 return nullptr;

713}

714

715

716

717

718

719

720

721

722

723

724

725

726

727

728

729

730

731

732

733

734

738

739

740 if (!TrueVal->getType()->isIntOrIntVectorTy() ||

742 return nullptr;

743

746

747 unsigned C1Log;

752 return nullptr;

753

756 return nullptr;

757

759 } else {

761 if (!Res || !Res->Mask.isPowerOf2())

762 return nullptr;

763

764 CmpLHS = Res->X;

765 Pred = Res->Pred;

766 C1Log = Res->Mask.logBase2();

768 }

769

770 Value *Y, *V = CmpLHS;

773 bool NeedXor;

775 Y = TrueVal;

776 BinOp = cast(FalseVal);

779 Y = FalseVal;

780 BinOp = cast(TrueVal);

782 } else {

783 return nullptr;

784 }

785

786

787 auto *IdentityC =

789 true);

790 if (IdentityC == nullptr || !IdentityC->isNullValue())

791 return nullptr;

792

793 unsigned C2Log = C2->logBase2();

794

795 bool NeedShift = C1Log != C2Log;

796 bool NeedZExtTrunc = Y->getType()->getScalarSizeInBits() !=

797 V->getType()->getScalarSizeInBits();

798

799

800 if ((NeedShift + NeedXor + NeedZExtTrunc + NeedAnd) >

802 return nullptr;

803

805

807 V = Builder.CreateAnd(V, ConstantInt::get(V->getType(), C1));

808 }

809

810 if (C2Log > C1Log) {

812 V = Builder.CreateShl(V, C2Log - C1Log);

813 } else if (C1Log > C2Log) {

814 V = Builder.CreateLShr(V, C1Log - C2Log);

816 } else

818

819 if (NeedXor)

821

823}

824

825

826

834 const APInt *NotC, *C;

835

836

840 Constant *OrC = ConstantInt::get(Ty, *C);

842 return BinaryOperator::CreateOr(T, NewSel);

843 }

844

845

849 Constant *OrC = ConstantInt::get(Ty, *C);

851 return BinaryOperator::CreateOr(F, NewSel);

852 }

853

854 return nullptr;

855}

856

857

858

859

860

861

862

863

864

865

866

868 auto *CondVal = SI.getCondition();

869 auto *TrueVal = SI.getTrueValue();

870 auto *FalseVal = SI.getFalseValue();

873

874

875

876

879 return nullptr;

880

883

884

885

886

887

888 auto *TrueValC = dyn_cast(TrueVal);

889 if (TrueValC == nullptr ||

891 !isa(FalseVal))

892 return nullptr;

893

894 auto *ZeroC = cast(cast(CondVal)->getOperand(1));

896

897

898

900 return nullptr;

901

902 auto *FalseValI = cast(FalseVal);

905 IC.replaceOperand(*FalseValI, FalseValI->getOperand(0) == Y ? 0 : 1, FrY);

907}

908

909

910

912 const Value *TrueVal,

913 const Value *FalseVal,

918

919

920

924 }

925

927 return nullptr;

928

929

930

934 ConstantInt::get(A->getType(), 1));

935 return nullptr;

936 }

937

939 return nullptr;

940

942

945 }

946

948 "Unexpected isUnsigned predicate!");

949

950

951

952

953

954 bool IsNegative = false;

959 IsNegative = true;

963 return nullptr;

964

965

966

967 if (IsNegative && !TrueVal->hasOneUse() && !ICI->hasOneUse())

968 return nullptr;

969

970

971

973 if (IsNegative)

974 Result = Builder.CreateNeg(Result);

975 return Result;

976}

977

980 if (!Cmp->hasOneUse())

981 return nullptr;

982

983

984 Value *Cmp0 = Cmp->getOperand(0);

985 Value *Cmp1 = Cmp->getOperand(1);

989

990

991

992

996 }

998 return nullptr;

999

1000

1001

1006 Intrinsic::uadd_sat, Cmp0, ConstantInt::get(Cmp0->getType(), 1));

1007 }

1008 return nullptr;

1009 }

1010

1014

1015

1017 ConstantInt::get(Cmp0->getType(), *C));

1018 }

1019

1020

1021

1025

1027 ConstantInt::get(Cmp0->getType(), *C));

1028 }

1029

1030

1031

1035

1037 ConstantInt::get(Cmp0->getType(), *C));

1038 }

1039

1040

1044 }

1046 return nullptr;

1047

1048

1049

1053

1054

1056 }

1057

1058

1059 X = Cmp0;

1060 Y = Cmp1;

1062

1063

1067 }

1068

1069

1073

1074

1076 }

1077

1078 return nullptr;

1079}

1080

1081

1084 auto *TI = dyn_cast(TVal);

1085 auto *FI = dyn_cast(FVal);

1086 if (!TI || !FI)

1087 return nullptr;

1088

1089

1091 Value *A = Cmp->getOperand(0);

1092 Value *B = Cmp->getOperand(1);

1093

1094

1098 }

1099

1100

1101

1105 (TI->hasNoSignedWrap() || TI->hasNoUnsignedWrap()) &&

1106 (FI->hasNoSignedWrap() || FI->hasNoUnsignedWrap())) {

1107

1108

1109

1110

1111

1112

1113 TI->setHasNoUnsignedWrap(false);

1114 if (!TI->hasNoSignedWrap())

1115 TI->setHasNoSignedWrap(TI->hasOneUse());

1117 }

1118

1119 return nullptr;

1120}

1121

1122

1123

1124

1125

1126

1127

1128

1129

1130

1131

1133 Value *FalseVal,

1135 unsigned BitWidth = TrueVal->getType()->getScalarSizeInBits();

1137 return nullptr;

1138

1141

1143 if (match(FalseVal,

1145 return nullptr;

1146

1147 if (match(Ctlz, m_IntrinsicIntrinsic::ctlz()))

1148 return nullptr;

1149

1151 return nullptr;

1152

1154 auto *II = cast(Ctlz);

1156 return nullptr;

1157

1159 II->getModule(), Intrinsic::cttz, II->getType());

1161}

1162

1163

1164

1165

1166

1167

1168

1169

1170

1171

1172

1173

1174

1180

1181

1183 return nullptr;

1184

1188 std::swap(SelectArg, ValueOnZero);

1189

1190

1191 Value *Count = nullptr;

1194 Count = SelectArg;

1195

1196

1197

1199 if (match(Count, m_IntrinsicIntrinsic::cttz(m_Value(X))) &&

1200 match(Count, m_IntrinsicIntrinsic::ctlz(m_Value(X))))

1201 return nullptr;

1202

1203

1204

1205 if ((X != CmpLHS || match(CmpRHS, m_Zero())) &&

1207 return nullptr;

1208

1210

1211

1212

1215

1216

1218

1219 II->dropPoisonGeneratingAnnotations();

1221 return SelectArg;

1222 }

1223

1224

1225

1226

1227 if (II->hasOneUse() && SelectArg->hasOneUse() &&

1230

1231 II->dropUBImplyingAttrsAndMetadata();

1233 }

1234

1235 return nullptr;

1236}

1237

1241

1242 if (TrueVal->getType()->isIntOrIntVectorTy())

1243 return nullptr;

1244

1250 return nullptr;

1251

1252

1256 ConstantInt::get(Type::getInt1Ty(Cmp.getContext()), IntMinIsPoison);

1259

1261 return IC.Builder.CreateNeg(Abs);

1262 return Abs;

1263 }

1264

1268 }

1269

1270 return nullptr;

1271}

1272

1274 unsigned Depth) {

1275

1277 return false;

1278

1279 assert(!isa(Old) && "Only replace non-constant values");

1280

1281 auto *I = dyn_cast(V);

1282 if (I || I->hasOneUse() ||

1284 return false;

1285

1286

1288 return false;

1289

1290 bool Changed = false;

1291 for (Use &U : I->operands()) {

1292 if (U == Old) {

1295 Changed = true;

1296 } else {

1298 }

1299 }

1300 return Changed;

1301}

1302

1303

1304

1305

1306

1307

1308

1309

1310

1311

1312

1313

1314

1315

1316

1317

1318

1321

1322

1324 bool Swapped = false;

1325 if (Cmp.isEquivalence(true)) {

1327 Swapped = true;

1328 } else if (Cmp.isEquivalence()) {

1329 return nullptr;

1330 }

1331

1332 Value *CmpLHS = Cmp.getOperand(0), *CmpRHS = Cmp.getOperand(1);

1333 auto ReplaceOldOpWithNewOp = [&](Value *OldOp,

1335

1336

1337

1338

1339

1340

1341 if (TrueVal == OldOp && (isa(OldOp) || !isa(NewOp)))

1342 return nullptr;

1343

1345 true)) {

1346

1347

1348

1352

1353

1354

1358 return nullptr;

1359 }

1360 }

1361

1362

1363

1364

1365

1366

1367

1372 return &Sel;

1373 return nullptr;

1374 };

1375

1376 if (Instruction *R = ReplaceOldOpWithNewOp(CmpLHS, CmpRHS))

1377 return R;

1378 if (Instruction *R = ReplaceOldOpWithNewOp(CmpRHS, CmpLHS))

1379 return R;

1380

1381 auto *FalseInst = dyn_cast(FalseVal);

1382 if (!FalseInst)

1383 return nullptr;

1384

1385

1386

1387

1388

1389

1390

1391

1392

1395 false,

1396 &DropFlags) == TrueVal ||

1398 false,

1399 &DropFlags) == TrueVal) {

1401 I->dropPoisonGeneratingAnnotations();

1403 }

1404

1406 }

1407

1408 return nullptr;

1409}

1410

1411

1412

1413

1414

1415

1416

1417

1418

1419

1420

1421

1422

1426

1428 return nullptr;

1429

1430 if (match(YeqZ,

1433

1434 if (match(YeqZ,

1436 return nullptr;

1437

1440 return nullptr;

1441

1442 if (match(XeqY,

1444 return nullptr;

1445

1446 cast(XeqY)->setSameSign(false);

1448}

1449

1450

1451

1452

1453

1454

1455

1456

1457

1458

1459

1460

1461

1462

1463

1469

1470

1471

1473 return nullptr;

1479 return nullptr;

1480

1481 if (!isa(Sel1)) {

1484 }

1485

1486

1487

1488 switch (Pred0) {

1491

1492

1493

1497 return nullptr;

1498 break;

1501

1502

1507 return nullptr;

1510 break;

1511 default:

1512 return nullptr;

1513 }

1514

1515

1516

1518 return nullptr;

1519

1520

1521

1522 if (Cmp00->getType() != X->getType() && X->hasOneUse())

1524

1525

1526

1528 if (Cmp00 == X)

1530 else if (match(Cmp00,

1533 return nullptr;

1534

1538 Value *ReplacementLow, *ReplacementHigh;

1540 m_Value(ReplacementHigh))) ||

1544 return nullptr;

1545

1547 return nullptr;

1548

1549

1550

1551

1552

1553 switch (Pred1) {

1555 break;

1557

1558

1559

1560 return nullptr;

1562

1563

1568 return nullptr;

1570 [[fallthrough]];

1572

1573

1575 std::swap(ReplacementLow, ReplacementHigh);

1576 break;

1577 default:

1578 return nullptr;

1579 }

1581 "Unexpected predicate type.");

1582

1583

1586

1589 "Unexpected predicate type.");

1591 std::swap(ThresholdLowIncl, ThresholdHighExcl);

1592

1593

1596 if (!Precond1 || match(Precond1, m_One()))

1597 return nullptr;

1598

1601 if (!Precond2 || match(Precond2, m_One()))

1602 return nullptr;

1603

1604

1605

1606

1607 if (X->getType() != Sel0.getType()) {

1611 return nullptr;

1613 ReplacementLow =

1615 ReplacementHigh =

1617 assert(ReplacementLow && ReplacementHigh &&

1618 "Constant folding of ImmConstant cannot fail");

1619 }

1620

1621

1624 Value *MaybeReplacedLow =

1625 Builder.CreateSelect(ShouldReplaceLow, ReplacementLow, X);

1626

1627

1628

1630 ShouldReplaceHigh, ReplacementHigh, MaybeReplacedLow);

1632}

1633

1634

1635

1636

1637

1638

1639

1640

1641

1643tryToReuseConstantFromSelectInComparison(SelectInst &Sel, ICmpInst &Cmp,

1651 return nullptr;

1652

1653

1655 return nullptr;

1656

1657

1658

1660 return nullptr;

1661

1662

1663

1665 return nullptr;

1666

1667

1668

1669

1671 return nullptr;

1672

1673

1674 Value *SelVal0, *SelVal1;

1676

1677

1680 return nullptr;

1681

1682

1683 auto MatchesSelectValue = [SelVal0, SelVal1](Constant *C) {

1684 return C->isElementWiseEqual(SelVal0) || C->isElementWiseEqual(SelVal1);

1685 };

1686

1687

1688 if (MatchesSelectValue(C0))

1689 return nullptr;

1690

1691

1693 if (!FlippedStrictness)

1694 return nullptr;

1695

1696

1697 if (!MatchesSelectValue(FlippedStrictness->second))

1698 return nullptr;

1699

1700

1703

1706 Cmp.getName() + ".inv");

1710

1711 return &Sel;

1712}

1713

1717 if (Cmp->hasOneUse())

1718 return nullptr;

1719

1720 const APInt *CmpC;

1722 return nullptr;

1723

1724

1729

1730

1734

1735 return nullptr;

1736}

1737

1740 const APInt *CmpC;

1744 return nullptr;

1745

1746

1747 Value *TVal = SI.getTrueValue();

1748 Value *FVal = SI.getFalseValue();

1750

1753

1756

1759

1762 }

1763

1771 else

1772 return nullptr;

1773

1774 const APInt *BinOpC;

1776 return nullptr;

1777

1780 if (R == *C) {

1782 return BO;

1783 }

1784 return nullptr;

1785}

1786

1787

1788

1791 Value *FalseVal) {

1793

1795 return nullptr;

1796

1799

1801 return nullptr;

1802

1806 return nullptr;

1807

1810

1817 } else {

1818 return nullptr;

1819 }

1820

1822 return nullptr;

1823

1824 return new ICmpInst(Pred, CmpLHS, B);

1825}

1826

1831 return nullptr;

1832

1837

1840

1842 foldSelectWithExtremeEqCond(CmpLHS, CmpRHS, TrueVal, FalseVal))

1843 return Res;

1844

1845 return nullptr;

1846}

1847

1848

1849

1850static Value *foldSelectWithConstOpToBinOp(ICmpInst *Cmp, Value *TrueVal,

1851 Value *FalseVal,

1857

1859 return nullptr;

1860

1862 return nullptr;

1863

1867 }

1868

1870 return nullptr;

1871

1872 unsigned Opcode = BOp->getOpcode();

1873

1874

1875

1876

1878 return nullptr;

1879

1881 return nullptr;

1882

1887

1890 RHS = C1;

1892 Opcode, Flipped->second, C2, DL)) {

1894 RHS = Flipped->second;

1895 } else {

1896 return nullptr;

1897 }

1898

1902}

1903

1904

1908 canonicalizeSPF(*ICI, SI.getTrueValue(), SI.getFalseValue(), *this))

1910

1911 if (Value *V = foldSelectInstWithICmpConst(SI, ICI, Builder))

1913

1914 if (Value *V = canonicalizeClampLike(SI, *ICI, Builder, *this))

1916

1918 tryToReuseConstantFromSelectInComparison(SI, *ICI, *this))

1919 return NewSel;

1920

1923

1924

1925 bool Changed = false;

1931

1932 if (Instruction *NewSel = foldSelectICmpEq(SI, ICI, *this))

1933 return NewSel;

1934

1935

1936

1937

1938

1946 SI.swapValues();

1947 SI.swapProfMetadata();

1948 return &SI;

1949 }

1950

1953 return V;

1954

1957

1958 if (Instruction *V = foldSelectCtlzToCttz(ICI, TrueVal, FalseVal, Builder))

1959 return V;

1960

1961 if (Instruction *V = foldSelectZeroOrOnes(ICI, TrueVal, FalseVal, Builder))

1962 return V;

1963

1966

1969

1970 if (Value *V = foldSelectCttzCtlz(ICI, TrueVal, FalseVal, *this))

1972

1975

1978

1981

1982 if (Value *V = foldSelectWithConstOpToBinOp(ICI, TrueVal, FalseVal, Builder))

1984

1985 return Changed ? &SI : nullptr;

1986}

1987

1988

1989

1996 return nullptr;

1997

1998 if (C == A || C == B) {

1999

2000

2001

2004 }

2005

2006 return nullptr;

2007}

2008

2009

2010

2013 Value *CondVal = SI.getCondition();

2016 auto *TI = dyn_cast(TrueVal);

2017 auto *FI = dyn_cast(FalseVal);

2018 if (!TI || !FI || !TI->hasOneUse() || !FI->hasOneUse())

2019 return nullptr;

2020

2021 Instruction *AddOp = nullptr, *SubOp = nullptr;

2022 if ((TI->getOpcode() == Instruction::Sub &&

2023 FI->getOpcode() == Instruction::Add) ||

2024 (TI->getOpcode() == Instruction::FSub &&

2025 FI->getOpcode() == Instruction::FAdd)) {

2026 AddOp = FI;

2027 SubOp = TI;

2028 } else if ((FI->getOpcode() == Instruction::Sub &&

2029 TI->getOpcode() == Instruction::Add) ||

2030 (FI->getOpcode() == Instruction::FSub &&

2031 TI->getOpcode() == Instruction::FAdd)) {

2032 AddOp = TI;

2033 SubOp = FI;

2034 }

2035

2036 if (AddOp) {

2037 Value *OtherAddOp = nullptr;

2038 if (SubOp->getOperand(0) == AddOp->getOperand(0)) {

2040 } else if (SubOp->getOperand(0) == AddOp->getOperand(1)) {

2042 }

2043

2044 if (OtherAddOp) {

2045

2046

2047 Value *NegVal;

2048 if (SI.getType()->isFPOrFPVectorTy()) {

2049 NegVal = Builder.CreateFNeg(SubOp->getOperand(1));

2050 if (Instruction *NegInst = dyn_cast(NegVal)) {

2052 Flags &= SubOp->getFastMathFlags();

2053 NegInst->setFastMathFlags(Flags);

2054 }

2055 } else {

2056 NegVal = Builder.CreateNeg(SubOp->getOperand(1));

2057 }

2058

2059 Value *NewTrueOp = OtherAddOp;

2060 Value *NewFalseOp = NegVal;

2061 if (AddOp != TI)

2062 std::swap(NewTrueOp, NewFalseOp);

2063 Value *NewSel = Builder.CreateSelect(CondVal, NewTrueOp, NewFalseOp,

2064 SI.getName() + ".p", &SI);

2065

2066 if (SI.getType()->isFPOrFPVectorTy()) {

2068 BinaryOperator::CreateFAdd(SubOp->getOperand(0), NewSel);

2069

2071 Flags &= SubOp->getFastMathFlags();

2073 return RI;

2074 } else

2075 return BinaryOperator::CreateAdd(SubOp->getOperand(0), NewSel);

2076 }

2077 }

2078 return nullptr;

2079}

2080

2081

2082

2083

2084

2085

2088 Value *CondVal = SI.getCondition();

2091

2095 return nullptr;

2096

2099

2100 auto IsSignedSaturateLimit = [&](Value *Limit, bool IsAdd) {

2102

2108 return false;

2109

2110 auto IsZeroOrOne = [](const APInt &C) { return C.isZero() || C.isOne(); };

2116 };

2117

2118 if (Op != X && Op != Y)

2119 return false;

2120

2121 if (IsAdd) {

2122

2123

2124

2125

2127 IsMinMax(TrueVal, FalseVal))

2128 return true;

2129

2130

2131

2132

2134 IsMinMax(FalseVal, TrueVal))

2135 return true;

2136 } else {

2137

2138

2140 IsMinMax(TrueVal, FalseVal))

2141 return true;

2142

2143

2145 IsMinMax(FalseVal, TrueVal))

2146 return true;

2147

2148

2150 IsMinMax(FalseVal, TrueVal))

2151 return true;

2152

2153

2155 IsMinMax(TrueVal, FalseVal))

2156 return true;

2157 }

2158

2159 return false;

2160 };

2161

2163 if (II->getIntrinsicID() == Intrinsic::uadd_with_overflow &&

2165

2166 NewIntrinsicID = Intrinsic::uadd_sat;

2167 else if (II->getIntrinsicID() == Intrinsic::usub_with_overflow &&

2169

2170 NewIntrinsicID = Intrinsic::usub_sat;

2171 else if (II->getIntrinsicID() == Intrinsic::sadd_with_overflow &&

2172 IsSignedSaturateLimit(TrueVal, true))

2173

2174

2175

2176

2177

2178

2179

2180

2181 NewIntrinsicID = Intrinsic::sadd_sat;

2182 else if (II->getIntrinsicID() == Intrinsic::ssub_with_overflow &&

2183 IsSignedSaturateLimit(TrueVal, false))

2184

2185

2186

2187

2188

2189

2190

2191

2192 NewIntrinsicID = Intrinsic::ssub_sat;

2193 else

2194 return nullptr;

2195

2197 NewIntrinsicID, SI.getType());

2199}

2200

2205 return nullptr;

2206

2210 return nullptr;

2211

2212 auto ExtOpcode = ExtInst->getOpcode();

2213 if (ExtOpcode != Instruction::ZExt && ExtOpcode != Instruction::SExt)

2214 return nullptr;

2215

2216

2217

2219 Type *SmallType = X->getType();

2221 auto *Cmp = dyn_cast(Cond);

2223 (!Cmp || Cmp->getOperand(0)->getType() != SmallType))

2224 return nullptr;

2225

2226

2227

2230 if (TruncC && ExtInst->hasOneUse()) {

2231 Value *TruncCVal = cast(TruncC);

2234

2235

2236

2239 }

2240

2241 return nullptr;

2242}

2243

2244

2245

2247 Value *CondVal = SI.getCondition();

2249 auto *CondValTy = dyn_cast(CondVal->getType());

2251 return nullptr;

2252

2253 unsigned NumElts = CondValTy->getNumElements();

2255 Mask.reserve(NumElts);

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

2258 if (!Elt)

2259 return nullptr;

2260

2262

2263 Mask.push_back(i);

2265

2266 Mask.push_back(i + NumElts);

2267 } else if (isa(Elt)) {

2268

2269

2270

2271 return nullptr;

2272 } else {

2273

2274 return nullptr;

2275 }

2276 }

2277

2279}

2280

2281

2282

2283

2284

2287 auto *Ty = dyn_cast(Sel.getType());

2288 if (!Ty)

2289 return nullptr;

2290

2291

2294 return nullptr;

2295

2296

2297

2298

2301}

2302

2303

2304

2305

2311

2315 return nullptr;

2316

2317

2318

2319 if (TVal == A || TVal == B || FVal == A || FVal == B)

2320 return nullptr;

2321

2324 return nullptr;

2325

2326

2327 Value *TSrc, *FSrc;

2330 return nullptr;

2331

2332

2333

2334

2336 if (TSrc == C && FSrc == D) {

2337

2338

2340 } else if (TSrc == D && FSrc == C) {

2341

2342

2344 } else {

2345 return nullptr;

2346 }

2348}

2349

2350

2351

2352

2353

2354

2355

2356

2357

2358

2359

2360

2361

2362

2363

2364

2365

2366

2367

2368

2369

2370

2371

2372

2374

2375

2376

2377

2379 auto *Extract = dyn_cast(V);

2380 if (!Extract)

2381 return nullptr;

2382 if (Extract->getIndices()[0] != I)

2383 return nullptr;

2384 return dyn_cast(Extract->getAggregateOperand());

2385 };

2386

2387

2388

2389 if (SI.hasOneUse())

2390 if (auto *Select = dyn_cast(SI.user_back()))

2391 if (Select->getCondition() == SI.getCondition())

2392 if (Select->getFalseValue() == SI.getTrueValue() ||

2393 Select->getTrueValue() == SI.getFalseValue())

2394 return nullptr;

2395

2396

2397 auto *CmpXchg = isExtractFromCmpXchg(SI.getCondition(), 1);

2398 if (!CmpXchg)

2399 return nullptr;

2400

2401

2402

2403

2404 if (auto *X = isExtractFromCmpXchg(SI.getTrueValue(), 0))

2405 if (X == CmpXchg && X->getCompareOperand() == SI.getFalseValue())

2406 return SI.getFalseValue();

2407

2408

2409

2410

2411 if (auto *X = isExtractFromCmpXchg(SI.getFalseValue(), 0))

2412 if (X == CmpXchg && X->getCompareOperand() == SI.getTrueValue())

2413 return SI.getFalseValue();

2414

2415 return nullptr;

2416}

2417

2418

2419

2420

2421

2422

2423

2424

2425

2428

2431 return nullptr;

2432

2435 return nullptr;

2436

2437 Value *SV0, *SV1, *SA0, *SA1;

2443 return nullptr;

2444

2445

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

2450 }

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

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

2454

2455

2458 ShAmt = SA0;

2460 ShAmt = SA1;

2461 else

2462 return nullptr;

2463

2464

2465

2466

2467

2468 bool IsFshl = (ShAmt == SA0);

2470 if ((IsFshl && TVal != SV0) || (!IsFshl && TVal != SV1))

2471 return nullptr;

2472

2473

2477 return nullptr;

2478

2479

2480

2481 if (SV0 != SV1) {

2486 }

2487

2488

2489

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

2495}

2496

2503

2504

2505

2510 return nullptr;

2511

2512 assert(TC != FC && "Expected equal select arms to simplify");

2513

2516 bool IsTrueIfSignSet;

2520 isSignBitCheck(Pred, *C, IsTrueIfSignSet) || X->getType() != SelType)

2521 return nullptr;

2522

2523

2524

2525

2526

2527

2528

2529 if (IsTrueIfSignSet ^ TC->isNegative())

2531

2532

2533

2534 Value *MagArg = ConstantFP::get(SelType, abs(*TC));

2538}

2539

2541 if (!isa(Sel.getType()))

2542 return nullptr;

2543

2548

2552 if (auto *I = dyn_cast(V))

2553 I->copyIRFlags(&Sel);

2556 M, Intrinsic::vector_reverse, V->getType());

2558 };

2559

2561

2564 return createSelReverse(C, X, Y);

2565

2566

2568 return createSelReverse(C, X, FVal);

2569 }

2570

2573 return createSelReverse(C, TVal, Y);

2574 }

2575

2576 auto *VecTy = dyn_cast(Sel.getType());

2577 if (!VecTy)

2578 return nullptr;

2579

2580 unsigned NumElts = VecTy->getNumElements();

2581 APInt PoisonElts(NumElts, 0);

2584 if (V != &Sel)

2586 return &Sel;

2587 }

2588

2589

2590

2591

2595 cast(TVal)->isSelect()) {

2596 if (X == FVal) {

2597

2600 }

2601 if (Y == FVal) {

2602

2605 }

2606 }

2609 cast(FVal)->isSelect()) {

2610 if (X == TVal) {

2611

2614 }

2615 if (Y == TVal) {

2616

2619 }

2620 }

2621

2622 return nullptr;

2623}

2624

2628

2629

2630 auto *IDomNode = DT[BB]->getIDom();

2631 if (!IDomNode)

2632 return nullptr;

2633 BasicBlock *IDom = IDomNode->getBlock();

2634

2636 Value *IfTrue, *IfFalse;

2648 } else

2649 return nullptr;

2650

2651

2652 if (TrueSucc == FalseSucc)

2653 return nullptr;

2654

2655

2656

2657

2658

2659

2664

2670 else

2671 return nullptr;

2672

2673 if (auto *Insn = dyn_cast(Inputs[Pred]))

2675 return nullptr;

2676 }

2677

2682 PN->takeName(&Sel);

2683 return PN;

2684}

2685

2688

2692 if (auto *I = dyn_cast(V))

2693 CandidateBlocks.insert(I->getParent());

2694

2695 for (BasicBlock *BB : CandidateBlocks)

2696 if (auto *PN = foldSelectToPhiImpl(Sel, BB, DT, Builder))

2697 return PN;

2698 return nullptr;

2699}

2700

2701

2702

2703

2704

2705

2706

2709 Value *CondVal = SI.getCondition();

2712

2714 Value *Op, *RemRes, *Remainder;

2716 bool TrueIfSigned = false;

2717

2720 return nullptr;

2721

2722

2723

2724 if (!TrueIfSigned)

2726

2727 auto FoldToBitwiseAnd = [&](Value *Remainder) -> Instruction * {

2730 return BinaryOperator::CreateAnd(Op, Add);

2731 };

2732

2733

2734

2735

2736

2737

2741 FalseVal == RemRes)

2742 return FoldToBitwiseAnd(Remainder);

2743

2744

2745

2746

2747

2750 FalseVal == RemRes)

2751 return FoldToBitwiseAnd(ConstantInt::get(RemRes->getType(), 2));

2752

2753 return nullptr;

2754}

2755

2758 if (!FI)

2759 return nullptr;

2760

2763

2764

2765

2766

2767

2768

2769

2770

2771

2777 }

2778

2779 return nullptr;

2780}

2781

2782

2783static Value *simplifyNestedSelectsUsingImpliedCond(SelectInst &SI,

2785 bool CondIsTrue,

2787 Value *InnerCondVal = SI.getCondition();

2788 Value *InnerTrueVal = SI.getTrueValue();

2789 Value *InnerFalseVal = SI.getFalseValue();

2791 "The type of inner condition must match with the outer.");

2792 if (auto Implied = isImpliedCondition(CondVal, InnerCondVal, DL, CondIsTrue))

2793 return *Implied ? InnerTrueVal : InnerFalseVal;

2794 return nullptr;

2795}

2796

2797Instruction *InstCombinerImpl::foldAndOrOfSelectUsingImpliedCond(Value *Op,

2799 bool IsAnd) {

2800 assert(Op->getType()->isIntOrIntVectorTy(1) &&

2801 "Op must be either i1 or vector of i1.");

2802 if (SI.getCondition()->getType() != Op->getType())

2803 return nullptr;

2804 if (Value *V = simplifyNestedSelectsUsingImpliedCond(SI, Op, IsAnd, DL))

2808 return nullptr;

2809}

2810

2811

2812

2815 Value *CondVal = SI.getCondition();

2816

2817 bool ChangedFMF = false;

2818 for (bool Swap : {false, true}) {

2820 Value *X = SI.getFalseValue();

2822

2823 if (Swap)

2825

2827 continue;

2828

2829

2830

2835 }

2839 }

2840 }

2841

2843 return nullptr;

2844

2845

2846

2847

2848 FastMathFlags FMF = cast(TrueVal)->getFastMathFlags();

2849 if (FMF.noNaNs() && SI.hasNoNaNs()) {

2850 SI.setHasNoNaNs(true);

2851 ChangedFMF = true;

2852 }

2853 if (FMF.noInfs() && SI.hasNoInfs()) {

2854 SI.setHasNoInfs(true);

2855 ChangedFMF = true;

2856 }

2857

2858

2859

2860

2861

2862

2863

2864

2865

2866

2867

2868 if (SI.hasNoSignedZeros() || SI.hasNoNaNs())

2869 return nullptr;

2870

2871 if (Swap)

2873

2878

2879 if (IsLTOrLE) {

2882 }

2883 if (IsGTOrGE) {

2885 Instruction *NewFNeg = UnaryOperator::CreateFNeg(Fabs);

2887 return NewFNeg;

2888 }

2889 }

2890

2891

2892

2893

2894 for (bool Swap : {false, true}) {

2896 Value *X = SI.getFalseValue();

2897

2898 if (Swap)

2900

2903 bool TrueIfSigned;

2904 if (match(CondVal,

2907 continue;

2909 return nullptr;

2910 if (Swap == TrueIfSigned && !CondVal->hasOneUse() && TrueVal->hasOneUse())

2911 return nullptr;

2912

2913

2914

2916 if (Swap != TrueIfSigned)

2919 }

2920

2921 return ChangedFMF ? &SI : nullptr;

2922}

2923

2924

2925

2926

2927

2928

2929

2930

2931

2932

2933

2934

2935

2936

2937

2939foldRoundUpIntegerWithPow2Alignment(SelectInst &SI,

2942 Value *X = SI.getTrueValue();

2943 Value *XBiasedHighBits = SI.getFalseValue();

2944

2946 Value *XLowBits;

2949 return nullptr;

2950

2953

2954

2955

2956 const APInt *LowBitMaskCst;

2958 return nullptr;

2959

2960

2961 const APInt *BiasCst, *HighBitMaskCst;

2962 if (match(XBiasedHighBits,

2965 match(XBiasedHighBits,

2968 return nullptr;

2969

2970 if (!LowBitMaskCst->isMask())

2971 return nullptr;

2972

2973 APInt InvertedLowBitMaskCst = ~*LowBitMaskCst;

2974 if (InvertedLowBitMaskCst != *HighBitMaskCst)

2975 return nullptr;

2976

2977 APInt AlignmentCst = *LowBitMaskCst + 1;

2978

2979 if (*BiasCst != AlignmentCst && *BiasCst != *LowBitMaskCst)

2980 return nullptr;

2981

2982 if (!XBiasedHighBits->hasOneUse()) {

2983

2984 if (*BiasCst == *LowBitMaskCst && impliesPoison(XBiasedHighBits, X))

2985 return XBiasedHighBits;

2986 return nullptr;

2987 }

2988

2989

2990 Type *Ty = X->getType();

2991 Value *XOffset = Builder.CreateAdd(X, ConstantInt::get(Ty, *LowBitMaskCst),

2992 X->getName() + ".biased");

2993 Value *R = Builder.CreateAnd(XOffset, ConstantInt::get(Ty, *HighBitMaskCst));

2994 R->takeName(&SI);

2995 return R;

2996}

2997

2998namespace {

2999struct DecomposedSelect {

3003};

3004}

3005

3006

3007

3008

3009

3011foldSelectOfSymmetricSelect(SelectInst &OuterSelVal,

3013

3014 Value *OuterCond, *InnerCond, *InnerTrueVal, *InnerFalseVal;

3016 &OuterSelVal,

3019 m_Value(InnerFalseVal))),

3023 return nullptr;

3024

3026 return nullptr;

3027

3030}

3031

3032

3033

3034

3035

3036

3037

3038

3041

3042 DecomposedSelect OuterSel;

3043 match(&OuterSelVal,

3045 m_Value(OuterSel.FalseVal)));

3046

3047

3049 std::swap(OuterSel.TrueVal, OuterSel.FalseVal);

3050

3051

3053 return nullptr;

3054

3055

3057 Value *InnerSelVal = IsAndVariant ? OuterSel.FalseVal : OuterSel.TrueVal;

3058

3059

3061 [](Value *V) { return V->hasOneUse(); }))

3062 return nullptr;

3063

3064

3065 DecomposedSelect InnerSel;

3066 if (match(InnerSelVal,

3068 m_Value(InnerSel.FalseVal))))

3069 return nullptr;

3070

3071

3073 std::swap(InnerSel.TrueVal, InnerSel.FalseVal);

3074

3075 Value *AltCond = nullptr;

3076 auto matchOuterCond = [OuterSel, IsAndVariant, &AltCond](auto m_InnerCond) {

3077

3078

3079

3080

3081 return IsAndVariant ? match(OuterSel.Cond,

3085 };

3086

3087

3088

3089

3090

3091 if (matchOuterCond(m_Specific(InnerSel.Cond))) {

3092

3095

3096 std::swap(InnerSel.TrueVal, InnerSel.FalseVal);

3097 InnerSel.Cond = NotInnerCond;

3098 } else

3099 return nullptr;

3100

3102 AltCond, IsAndVariant ? OuterSel.TrueVal : InnerSel.FalseVal,

3103 IsAndVariant ? InnerSel.TrueVal : OuterSel.FalseVal);

3104 SelInner->takeName(InnerSelVal);

3106 IsAndVariant ? SelInner : InnerSel.TrueVal,

3107 !IsAndVariant ? SelInner : InnerSel.FalseVal);

3108}

3109

3110

3111

3112

3113static bool impliesPoisonOrCond(const Value *ValAssumedPoison, const Value *V,

3116 return true;

3117

3118

3119

3120 if (auto *ICmp = dyn_cast(ValAssumedPoison)) {

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

3122 const APInt *RHSC1;

3123 const APInt *RHSC2;

3125 if (ICmp->hasSameSign() &&

3136 *RHSC2);

3137 }

3138 }

3139

3140 return false;

3141}

3142

3144 Value *CondVal = SI.getCondition();

3147 Type *SelType = SI.getType();

3148

3149

3150

3151

3154 return nullptr;

3155

3159

3160

3161

3162

3164 if (impliesPoisonOrCond(FalseVal, CondVal, false)) {

3165

3166 return BinaryOperator::CreateOr(CondVal, FalseVal);

3167 }

3168

3170 impliesPoisonOrCond(FalseVal, B, false)) {

3171

3174 }

3175

3176

3180 bool CondLogicAnd = isa(CondVal);

3181 bool FalseLogicAnd = isa(FalseVal);

3182 auto AndFactorization = [&](Value *Common, Value *InnerCond,

3183 Value *InnerVal,

3184 bool SelFirst = false) -> Instruction * {

3186 if (SelFirst)

3188 if (FalseLogicAnd || (CondLogicAnd && Common == A))

3190 else

3191 return BinaryOperator::CreateAnd(Common, InnerSel);

3192 };

3193

3194 if (A == C)

3195 return AndFactorization(A, B, D);

3196 if (A == D)

3197 return AndFactorization(A, B, C);

3198 if (B == C)

3199 return AndFactorization(B, A, D);

3200 if (B == D)

3201 return AndFactorization(B, A, C, CondLogicAnd && FalseLogicAnd);

3202 }

3203 }

3204

3206 if (impliesPoisonOrCond(TrueVal, CondVal, true)) {

3207

3208 return BinaryOperator::CreateAnd(CondVal, TrueVal);

3209 }

3210

3212 impliesPoisonOrCond(TrueVal, B, true)) {

3213

3216 }

3217

3218

3222 bool CondLogicOr = isa(CondVal);

3223 bool TrueLogicOr = isa(TrueVal);

3224 auto OrFactorization = [&](Value *Common, Value *InnerCond,

3225 Value *InnerVal,

3226 bool SelFirst = false) -> Instruction * {

3228 if (SelFirst)

3230 if (TrueLogicOr || (CondLogicOr && Common == A))

3232 else

3233 return BinaryOperator::CreateOr(Common, InnerSel);

3234 };

3235

3236 if (A == C)

3237 return OrFactorization(A, B, D);

3238 if (A == D)

3239 return OrFactorization(A, B, C);

3240 if (B == C)

3241 return OrFactorization(B, A, D);

3242 if (B == D)

3243 return OrFactorization(B, A, C, CondLogicOr && TrueLogicOr);

3244 }

3245 }

3246

3247

3248

3249

3253 }

3254

3258 }

3259

3260

3261

3266

3267

3268

3273

3274

3278

3282

3283

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

3287

3288

3289 if (match(CondVal,

3293 }

3294

3299 }

3300 }

3301

3306 }

3307 }

3308

3309 if (match(CondVal,

3313 }

3314

3316 Use *Y = nullptr;

3320 auto *FI = new FreezeInst(*Y, (*Y)->getName() + ".fr");

3324 }

3325

3326 if (auto *V = foldBooleanAndOr(CondVal, Op1, SI, IsAnd,

3327 true))

3329 }

3330

3331

3332

3333

3337 if (Res && *Res == false)

3339 }

3343 if (Res && *Res == false)

3345 }

3346

3347

3348

3352 if (Res && *Res == true)

3354 }

3358 if (Res && *Res == true)

3360 }

3361

3364

3365

3366

3367

3368

3371 auto *SelCond = dyn_cast(CondVal);

3372 auto *SelFVal = dyn_cast(FalseVal);

3373 bool MayNeedFreeze = SelCond && SelFVal &&

3374 match(SelFVal->getTrueValue(),

3376 if (MayNeedFreeze)

3379 }

3380

3381

3382

3383

3384

3387 auto *SelCond = dyn_cast(CondVal);

3388 auto *SelFVal = dyn_cast(FalseVal);

3389 bool MayNeedFreeze = SelCond && SelFVal &&

3390 match(SelCond->getTrueValue(),

3392 if (MayNeedFreeze)

3395 }

3396 }

3397

3398 return nullptr;

3399}

3400

3401

3402

3406 bool &ShouldDropNUW) {

3407

3408

3409

3410

3411

3412

3413

3414

3415

3416

3417

3418

3419

3420

3421

3422

3423

3424

3425

3428

3429 ShouldDropNUW = false;

3430

3431

3432

3433

3434

3435 auto MatchForward = [&](Value *CommonAncestor) {

3436 const APInt *C = nullptr;

3437 if (CtlzOp == CommonAncestor)

3438 return true;

3440 CR = CR.add(*C);

3441 return true;

3442 }

3444 ShouldDropNUW = true;

3446 return true;

3447 }

3450 return true;

3451 }

3452 return false;

3453 };

3454

3455 const APInt *C = nullptr;

3456 Value *CommonAncestor;

3457 if (MatchForward(Cond0)) {

3458

3460 CR = CR.sub(*C);

3461 if (!MatchForward(CommonAncestor))

3462 return false;

3463

3464 } else {

3465 return false;

3466 }

3467

3468

3469

3470

3471

3475}

3476

3477

3478

3479

3480

3481

3482

3483

3484

3485

3486

3487

3488

3489

3490

3491

3492

3493

3494

3495

3496

3499 Type *SelType = SI.getType();

3501

3505 const APInt *Cond1;

3506 Value *Cond0, *Ctlz, *CtlzOp;

3508 return nullptr;

3509

3513 }

3514

3515 bool ShouldDropNUW;

3516

3521 match(Ctlz, m_IntrinsicIntrinsic::ctlz(m_Value(CtlzOp), m_Zero())) ||

3522 !isSafeToRemoveBitCeilSelect(Pred, Cond0, Cond1, CtlzOp, BitWidth,

3523 ShouldDropNUW))

3524 return nullptr;

3525

3526 if (ShouldDropNUW)

3527 cast(CtlzOp)->setHasNoUnsignedWrap(false);

3528

3529

3530

3531

3532

3533

3534

3535 cast(Ctlz)->dropPoisonGeneratingAnnotations();

3539 Builder.CreateAnd(Neg, ConstantInt::get(SelType, BitWidth - 1));

3542}

3543

3544

3545

3546

3547

3548

3549

3550

3552 Value *TV = SI.getTrueValue();

3553 Value *FV = SI.getFalseValue();

3554

3558 return nullptr;

3559

3561 return nullptr;

3562

3563

3564

3565

3566

3571 }

3573

3574 bool Replace = false;

3576

3577

3583 Replace = true;

3584

3585

3586

3592 Replace = true;

3593

3594

3596 const APInt *InnerTV, *InnerFV;

3602 FalseBranchSelectPredicate =

3605 }

3606

3607 if (!InnerTV->isOne()) {

3610 }

3611

3615 Replace = true;

3616 }

3617 }

3618

3619 Intrinsic::ID IID = IsSigned ? Intrinsic::scmp : Intrinsic::ucmp;

3620 if (Replace)

3623 return nullptr;

3624}

3625

3629

3632}

3633

3637 bool SelectIsNSZ) {

3641 FastMathFlags FMF = cast(TrueVal)->getFastMathFlags();

3642

3643

3646 }

3647

3648 return false;

3649}

3650

3651

3652

3654 unsigned Depth) {

3656 return false;

3657

3658

3659

3661 return true;

3662

3663 if (auto *I = dyn_cast(V)) {

3664 if (isa(I)) {

3666 return false;

3668 }

3670 return Op->getType()->isIntOrIntVectorTy() &&

3671 hasAffectedValue(Op, Affected, Depth + 1);

3672 });

3673 }

3674

3675 return false;

3676}

3677

3678

3679

3682

3683

3684 auto *SIFOp = dyn_cast(&SI);

3685 if (!SIFOp || !SIFOp->hasNoSignedZeros() || !SIFOp->hasNoNaNs())

3686 return nullptr;

3687

3688 auto TryFoldIntoAddConstant =

3691

3692

3694 return nullptr;

3695

3697 return nullptr;

3698

3700 Swapped ? X : Z, "", &SI);

3702

3705

3706

3711 cast(NewFAdd)->setFastMathFlags(NewFMF);

3712 cast(NewSelect)->setFastMathFlags(NewFMF);

3713

3714 return NewFAdd;

3715 };

3716

3717

3718

3719

3720

3725

3726

3727

3728

3731 return TryFoldIntoAddConstant(Pred, X, Z, FAdd, C, false);

3732

3735 return TryFoldIntoAddConstant(Pred, X, Z, FAdd, C, true);

3736

3737 return nullptr;

3738}

3739

3741 Value *CondVal = SI.getCondition();

3744 Type *SelType = SI.getType();

3745

3749

3750 if (Instruction *I = canonicalizeSelectToShuffle(SI))

3751 return I;

3752

3753 if (Instruction *I = canonicalizeScalarSelectOfVecs(SI, *this))

3754 return I;

3755

3756

3757

3758

3764 true))

3766

3769 true))

3771

3776 return &SI;

3777 }

3778

3780 return R;

3781

3782

3783

3784

3785

3786

3787

3788

3789

3790

3793

3795 return new ZExtInst(CondVal, SelType);

3796

3797

3799 return new SExtInst(CondVal, SelType);

3800

3801

3804 return new ZExtInst(NotCond, SelType);

3805 }

3806

3807

3810 return new SExtInst(NotCond, SelType);

3811 }

3812 }

3813

3814 auto *SIFPOp = dyn_cast(&SI);

3815

3816 if (auto *FCmp = dyn_cast(CondVal)) {

3818 Value *Cmp0 = FCmp->getOperand(0), *Cmp1 = FCmp->getOperand(1);

3819

3820 if ((Cmp0 == TrueVal && Cmp1 == FalseVal) ||

3821 (Cmp0 == FalseVal && Cmp1 == TrueVal)) {

3822

3823

3824

3825

3826

3829

3831 FCmp->getName() + ".inv");

3835 }

3836 }

3837

3838 if (SIFPOp) {

3839

3840

3841

3842

3843

3844

3845

3846

3847

3848

3849

3850

3851

3852 Value *MatchCmp0 = nullptr;

3853 Value *MatchCmp1 = nullptr;

3854

3855

3856

3863 }

3864

3865 if (Cmp0 == MatchCmp0 &&

3866 matchFMulByZeroIfResultEqZero(*this, Cmp0, Cmp1, MatchCmp1, MatchCmp0,

3867 SI, SIFPOp->hasNoSignedZeros()))

3869 }

3870 }

3871

3872 if (SIFPOp) {

3873

3874

3875 auto *FCmp = dyn_cast(CondVal);

3876

3877

3878

3879 if (SIFPOp->hasNoNaNs() && SIFPOp->hasNoSignedZeros()) {

3882 Value *BinIntr =

3884 if (auto *BinIntrInst = dyn_cast(BinIntr))

3885 BinIntrInst->setHasNoNaNs(FCmp->hasNoNaNs());

3887 }

3888

3890 Value *BinIntr =

3892 if (auto *BinIntrInst = dyn_cast(BinIntr))

3893 BinIntrInst->setHasNoNaNs(FCmp->hasNoNaNs());

3895 }

3896 }

3897 }

3898

3899

3900 if (Instruction *Fabs = foldSelectWithFCmpToFabs(SI, *this))

3901 return Fabs;

3902

3903

3904 if (CmpInst *CI = dyn_cast(CondVal))

3906 return NewSel;

3907

3908 if (ICmpInst *ICI = dyn_cast(CondVal))

3911

3913 return Add;

3915 return Add;

3917 return Or;

3919 return Mul;

3920

3921

3922 auto *TI = dyn_cast(TrueVal);

3923 auto *FI = dyn_cast(FalseVal);

3924 if (TI && FI && TI->getOpcode() == FI->getOpcode())

3926 return IV;

3927

3929 return I;

3930

3932 return I;

3933

3934

3935

3941 return nullptr;

3943 if (isa(CondVal->getType()) && !isa(Idx->getType()))

3944 return nullptr;

3948 if (Swap)

3954 };

3955 if (auto *TrueGep = dyn_cast(TrueVal))

3956 if (auto *NewGep = SelectGepWithBase(TrueGep, FalseVal, false))

3957 return NewGep;

3958 if (auto *FalseGep = dyn_cast(FalseVal))

3959 if (auto *NewGep = SelectGepWithBase(FalseGep, TrueVal, true))

3960 return NewGep;

3961

3962

3965 return FoldI;

3966

3970 auto SPF = SPR.Flavor;

3971 if (SPF) {

3972 Value *LHS2, *RHS2;

3975 RHS2, SI, SPF, RHS))

3976 return R;

3979 RHS2, SI, SPF, LHS))

3980 return R;

3981 }

3982

3984

3985

3986

3987

3988 bool IsCastNeeded = LHS->getType() != SelType;

3989 Value *CmpLHS = cast(CondVal)->getOperand(0);

3990 Value *CmpRHS = cast(CondVal)->getOperand(1);

3991 if (IsCastNeeded ||

3993 ((CmpLHS != LHS && CmpLHS != RHS) ||

3994 (CmpRHS != LHS && CmpRHS != RHS)))) {

3996

4000 else

4002 cast(SI.getCondition()));

4003

4005 if (!IsCastNeeded)

4007

4010 }

4011 }

4012 }

4013

4014

4015 if (auto *PN = dyn_cast(SI.getCondition()))

4017 return NV;

4018

4019 if (SelectInst *TrueSI = dyn_cast(TrueVal)) {

4020 if (TrueSI->getCondition()->getType() == CondVal->getType()) {

4021

4022

4023 if (Value *V = simplifyNestedSelectsUsingImpliedCond(

4024 *TrueSI, CondVal, true, DL))

4026

4027

4028

4029

4030

4031 if (TrueSI->getFalseValue() == FalseVal && TrueSI->hasOneUse()) {

4035 return &SI;

4036 }

4037 }

4038 }

4039 if (SelectInst *FalseSI = dyn_cast(FalseVal)) {

4040 if (FalseSI->getCondition()->getType() == CondVal->getType()) {

4041

4042

4043 if (Value *V = simplifyNestedSelectsUsingImpliedCond(

4044 *FalseSI, CondVal, false, DL))

4046

4047

4048 if (FalseSI->getTrueValue() == TrueVal && FalseSI->hasOneUse()) {

4052 return &SI;

4053 }

4054 }

4055 }

4056

4057

4058

4059

4060

4061

4062

4065 if (auto *TrueBOSI = dyn_cast(TrueBO->getOperand(0))) {

4066 if (TrueBOSI->getCondition() == CondVal) {

4067 replaceOperand(*TrueBO, 0, TrueBOSI->getTrueValue());

4069 return &SI;

4070 }

4071 }

4072 if (auto *TrueBOSI = dyn_cast(TrueBO->getOperand(1))) {

4073 if (TrueBOSI->getCondition() == CondVal) {

4074 replaceOperand(*TrueBO, 1, TrueBOSI->getTrueValue());

4076 return &SI;

4077 }

4078 }

4079 }

4080

4081

4084 if (auto *FalseBOSI = dyn_cast(FalseBO->getOperand(0))) {

4085 if (FalseBOSI->getCondition() == CondVal) {

4086 replaceOperand(*FalseBO, 0, FalseBOSI->getFalseValue());

4088 return &SI;

4089 }

4090 }

4091 if (auto *FalseBOSI = dyn_cast(FalseBO->getOperand(1))) {

4092 if (FalseBOSI->getCondition() == CondVal) {

4093 replaceOperand(*FalseBO, 1, FalseBOSI->getFalseValue());

4095 return &SI;

4096 }

4097 }

4098 }

4099

4104 SI.swapValues();

4105 SI.swapProfMetadata();

4106 return &SI;

4107 }

4108

4110 return I;

4111

4112

4113

4114

4115

4116

4120 if (Known.One.isOne())

4122 if (Known.Zero.isOne())

4124 }

4125

4127 return BitCastSel;

4128

4129

4130 if (Value *V = foldSelectCmpXchg(SI))

4132

4135

4137 return Funnel;

4138

4140 return Copysign;

4141

4144

4145 if (Value *Fr = foldSelectWithFrozenICmp(SI, Builder))

4147

4148 if (Value *V = foldRoundUpIntegerWithPow2Alignment(SI, Builder))

4150

4151 if (Value *V = foldSelectIntoAddConstant(SI, Builder))

4153

4154

4155

4161 auto *MaskedInst = cast(TrueVal);

4162 if (isa(MaskedInst->getArgOperand(3)))

4163 MaskedInst->setArgOperand(3, FalseVal );

4165 }

4166

4173 (CondVal->getType() == Mask->getType())) {

4174

4175

4176

4177

4178 bool CanMergeSelectIntoLoad = false;

4180 CanMergeSelectIntoLoad = match(V, m_Zero());

4181

4182 if (CanMergeSelectIntoLoad) {

4183 auto *MaskedInst = cast(FalseVal);

4184 if (isa(MaskedInst->getArgOperand(3)))

4185 MaskedInst->setArgOperand(3, TrueVal );

4187 }

4188 }

4189

4191 return I;

4192

4194 return I;

4195

4196

4197

4198

4199

4201 return &SI;

4202

4204 return I;

4205

4207 return I;

4208

4210 return I;

4211

4212

4213

4214

4215

4216

4217 auto FoldSelectWithAndOrCond = [&](bool IsAnd, Value *A,

4221 return SelectInst::Create(A, IsAnd ? V : TrueVal, IsAnd ? FalseVal : V);

4222

4223

4225 if (ICmpInst *Cmp = dyn_cast(B))

4226 if (Value *V = canonicalizeSPF(*Cmp, TrueVal, FalseVal, *this))

4228 IsAnd ? FalseVal : V);

4229 }

4230

4231 return nullptr;

4232 };

4233

4236 if (Instruction *I = FoldSelectWithAndOrCond( true, LHS, RHS))

4237 return I;

4238 if (Instruction *I = FoldSelectWithAndOrCond( true, RHS, LHS))

4239 return I;

4241 if (Instruction *I = FoldSelectWithAndOrCond( false, LHS, RHS))

4242 return I;

4243 if (Instruction *I = FoldSelectWithAndOrCond( false, RHS, LHS))

4244 return I;

4245 } else {

4246

4247

4249 if (Instruction *I = FoldSelectWithAndOrCond( true, LHS, RHS))

4250 return I;

4252 if (Instruction *I = FoldSelectWithAndOrCond( false, LHS, RHS))

4253 return I;

4254 }

4255 }

4256

4257

4259 return BinaryOperator::CreateXor(CondVal, FalseVal);

4260

4261

4262

4264 (!isa(TrueVal) || !isa(FalseVal))) {

4265

4268 CC.AffectedValues.insert(V);

4269 });

4271 if (CC.AffectedValues.empty()) {

4272 if (!isa(TrueVal) &&

4273 hasAffectedValue(TrueVal, CC.AffectedValues, 0)) {

4277 ConstantInt::get(SelType, Known.getConstant()));

4278 }

4279

4280 CC.Invert = true;

4281 if (!isa(FalseVal) &&

4282 hasAffectedValue(FalseVal, CC.AffectedValues, 0)) {

4286 ConstantInt::get(SelType, Known.getConstant()));

4287 }

4288 }

4289 }

4290

4291

4292

4293

4294

4297 if (TrueVal == Trunc)

4299 if (FalseVal == Trunc)

4301 }

4303 if (TrueVal == Trunc)

4306 if (FalseVal == Trunc)

4308 }

4309

4310 return nullptr;

4311}

SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn

AMDGPU Register Bank Select

This file implements a class to represent arbitrary precision integral constant values and operations...

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

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

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

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

This file contains the declarations for the subclasses of Constant, which represent the different fla...

Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx

static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")

const HexagonInstrInfo * TII

This file provides internal interfaces used to implement the InstCombine.

static Value * canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal, InstCombiner::BuilderTy &Builder)

static Instruction * foldSetClearBits(SelectInst &Sel, InstCombiner::BuilderTy &Builder)

Canonicalize a set or clear of a masked set of constant bits to select-of-constants form.

static Instruction * foldSelectICmpAndAnd(Type *SelType, const ICmpInst *Cmp, Value *TVal, Value *FVal, InstCombiner::BuilderTy &Builder)

We want to turn: (select (icmp eq (and X, Y), 0), (and (lshr X, Z), 1), 1) into: zext (icmp ne i32 (a...

static unsigned getSelectFoldableOperands(BinaryOperator *I)

We want to turn code that looks like this: C = or A, B D = select cond, C, A into: C = select cond,...

static Instruction * foldSelectZeroOrMul(SelectInst &SI, InstCombinerImpl &IC)

static Value * canonicalizeSaturatedSubtract(const ICmpInst *ICI, const Value *TrueVal, const Value *FalseVal, InstCombiner::BuilderTy &Builder)

Transform patterns such as (a > b) ? a - b : 0 into usub.sat(a, b).

static Value * foldAbsDiff(ICmpInst *Cmp, Value *TVal, Value *FVal, InstCombiner::BuilderTy &Builder)

Try to match patterns with select and subtract as absolute difference.

static Instruction * foldSelectBinOpIdentity(SelectInst &Sel, const TargetLibraryInfo &TLI, InstCombinerImpl &IC)

Replace a select operand based on an equality comparison with the identity constant of a binop.

static Value * foldSelectICmpAndZeroShl(const ICmpInst *Cmp, Value *TVal, Value *FVal, InstCombiner::BuilderTy &Builder)

We want to turn: (select (icmp eq (and X, C1), 0), 0, (shl [nsw/nuw] X, C2)); iff C1 is a mask and th...

static Value * foldSelectICmpAndBinOp(const ICmpInst *IC, Value *TrueVal, Value *FalseVal, InstCombiner::BuilderTy &Builder)

We want to turn: (select (icmp eq (and X, C1), 0), Y, (BinOp Y, C2)) into: IF C2 u>= C1 (BinOp Y,...

static Value * foldSelectICmpLshrAshr(const ICmpInst *IC, Value *TrueVal, Value *FalseVal, InstCombiner::BuilderTy &Builder)

We want to turn: (select (icmp sgt x, C), lshr (X, Y), ashr (X, Y)); iff C s>= -1 (select (icmp slt x...

static bool isSelect01(const APInt &C1I, const APInt &C2I)

static Value * foldSelectICmpAnd(SelectInst &Sel, ICmpInst *Cmp, InstCombiner::BuilderTy &Builder)

This folds: select (icmp eq (and X, C1)), TC, FC iff C1 is a power 2 and the difference between TC an...

This file provides the interface for the instcombine pass implementation.

uint64_t IntrinsicInst * II

static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")

const SmallVectorImpl< MachineOperand > & Cond

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file defines the SmallVector class.

static const uint32_t IV[8]

bool bitwiseIsEqual(const APFloat &RHS) const

Class for arbitrary precision integers.

static APInt getAllOnes(unsigned numBits)

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

static APInt getSignMask(unsigned BitWidth)

Get the SignMask for a specific bit width.

bool isMinSignedValue() const

Determine if this is the smallest signed value.

uint64_t getZExtValue() const

Get zero extended value.

bool isAllOnes() const

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

bool isZero() const

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

unsigned getBitWidth() const

Return the number of bits in the APInt.

static APInt getSignedMaxValue(unsigned numBits)

Gets maximum signed value of APInt for a specific bit width.

bool isMinValue() const

Determine if this is the smallest unsigned value.

static APInt getSignedMinValue(unsigned numBits)

Gets minimum signed value of APInt for a specific bit width.

unsigned countLeadingZeros() const

unsigned logBase2() const

bool isMask(unsigned numBits) const

bool isMaxSignedValue() const

Determine if this is the largest signed value.

bool isNonNegative() const

Determine if this APInt Value is non-negative (>= 0)

bool isPowerOf2() const

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

static APInt getZero(unsigned numBits)

Get the '0' value for the specified bit-width.

bool isOne() const

Determine if this is a value of 1.

static APInt getOneBitSet(unsigned numBits, unsigned BitNo)

Return an APInt with exactly one bit set in the result.

bool isMaxValue() const

Determine if this is the largest unsigned value.

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

MutableArrayRef< ResultElem > assumptions()

Access the list of assumption handles currently tracked for this function.

An instruction that atomically checks whether a specified value is in a memory location,...

LLVM Basic Block Representation.

iterator begin()

Instruction iterator methods.

const Instruction * getTerminator() const LLVM_READONLY

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

BinaryOps getOpcode() const

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

static 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.

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

This class represents a function call, abstracting a target machine's calling convention.

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

static 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 ...

This class is the base class for the comparison instructions.

Predicate

This enumeration lists the possible predicates for CmpInst subclasses.

@ FCMP_OEQ

0 0 0 1 True if ordered and equal

@ 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

@ FCMP_OGT

0 0 1 0 True if ordered and greater than

@ FCMP_OGE

0 0 1 1 True if ordered and greater 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

@ FCMP_ONE

0 1 1 0 True if ordered and operands are unequal

@ FCMP_UEQ

1 0 0 1 True if unordered or equal

@ ICMP_ULT

unsigned less than

@ FCMP_UGT

1 0 1 0 True if unordered or greater than

@ FCMP_OLE

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

@ ICMP_SGE

signed greater or equal

@ FCMP_UNE

1 1 1 0 True if unordered or not equal

@ ICMP_ULE

unsigned less or equal

@ FCMP_UGE

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

Predicate getSwappedPredicate() const

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

bool isFPPredicate() const

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 bool isUnordered(Predicate predicate)

Determine if the predicate is an unordered operation.

Predicate getFlippedStrictnessPredicate() const

For predicate of kind "is X or equal to 0" returns the predicate "is X".

bool isIntPredicate() const

bool isRelational() const

Return true if the predicate is relational (not EQ or NE).

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

static std::optional< CmpPredicate > getMatching(CmpPredicate A, CmpPredicate B)

Compares two CmpPredicates taking samesign into account and returns the canonicalized CmpPredicate if...

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

static Constant * getBinOpIdentity(unsigned Opcode, Type *Ty, bool AllowRHSConstant=false, bool NSZ=false)

Return the identity constant for a binary opcode.

static Constant * getNeg(Constant *C, bool HasNSW=false)

static ConstantInt * getTrue(LLVMContext &Context)

static ConstantInt * getFalse(LLVMContext &Context)

This class represents a range of values.

ConstantRange add(const ConstantRange &Other) const

Return a new range representing the possible values resulting from an addition of a value in this ran...

bool icmp(CmpInst::Predicate Pred, const ConstantRange &Other) const

Does the predicate Pred hold between ranges this and Other? NOTE: false does not mean that inverse pr...

static 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...

ConstantRange binaryNot() const

Return a new range representing the possible values resulting from a binary-xor of a value in this ra...

ConstantRange binaryOp(Instruction::BinaryOps BinOp, const ConstantRange &Other) const

Return a new range representing the possible values resulting from an application of the specified bi...

ConstantRange sub(const ConstantRange &Other) const

Return a new range representing the possible values resulting from a subtraction of a value in this r...

This is an important base class in LLVM.

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

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

static Constant * getAllOnesValue(Type *Ty)

bool isOneValue() const

Returns true if the value is one.

static Constant * getNullValue(Type *Ty)

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

Constant * getAggregateElement(unsigned Elt) const

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

bool isNullValue() const

Return true if this is the value that would be returned by getNullValue.

This class represents an Operation in the Expression.

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

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

bool dominates(const BasicBlock *BB, const Use &U) const

Return true if the (end of the) basic block BB dominates the use U.

Tagged union holding either a T or a Error.

Utility class for floating point operations which can have information about relaxed accuracy require...

FastMathFlags getFastMathFlags() const

Convenience function for getting all the fast-math flags.

Convenience struct for specifying and reasoning about fast-math flags.

static FastMathFlags intersectRewrite(FastMathFlags LHS, FastMathFlags RHS)

Intersect rewrite-based flags.

bool noSignedZeros() const

static FastMathFlags unionValue(FastMathFlags LHS, FastMathFlags RHS)

Union value flags.

void setNoSignedZeros(bool B=true)

This class represents a freeze function that returns random concrete value if an operand is either a ...

an instruction for type-safe pointer arithmetic to access elements of arrays and structs

Value * getPointerOperand()

static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

Type * getSourceElementType() const

GEPNoWrapFlags getNoWrapFlags() const

Get the nowrap flags for the GEP instruction.

uint64_t getType(const MachineInstr &MI) const

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

CmpPredicate getSwappedCmpPredicate() const

static bool isLT(Predicate P)

Return true if the predicate is SLT or ULT.

CmpPredicate getInverseCmpPredicate() const

static bool isGT(Predicate P)

Return true if the predicate is SGT or UGT.

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.

bool isRelational() const

Return true if the predicate is relational (not EQ or NE).

Common base class shared among various IRBuilders.

Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")

Create a ZExt or Trunc from the integer value V to DestTy.

Value * CreateFAdd(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)

Value * CreateSelectFMF(Value *C, Value *True, Value *False, FMFSource FMFSource, const Twine &Name="", Instruction *MDFrom=nullptr)

Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")

Return a vector value that contains.

ConstantInt * getTrue()

Get the constant value for i1 true.

Value * CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name="")

Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)

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

Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)

Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})

Value * CreateFCmpFMF(CmpInst::Predicate P, Value *LHS, Value *RHS, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)

Value * CreateNeg(Value *V, const Twine &Name="", bool HasNSW=false)

Value * CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, FMFSource FMFSource={}, const Twine &Name="")

Create a call to intrinsic ID with 2 operands which is mangled on the first type.

CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")

Create a call to intrinsic ID with Args, mangled using Types.

PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")

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

Value * CreateIsNeg(Value *Arg, const Twine &Name="")

Return a boolean value testing if Arg < 0.

CallInst * CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V, FMFSource FMFSource={}, const Twine &Name="")

Create a call to intrinsic ID with 1 operand which is mangled on its type.

Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)

Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)

Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")

Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)

Value * CreateIsNotNull(Value *Arg, const Twine &Name="")

Return a boolean value testing if Arg != 0.

Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)

Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")

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

Value * CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name="")

Value * CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name="")

void SetInsertPoint(BasicBlock *TheBB)

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

Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)

Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")

Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")

Value * CreateLogicalOr(Value *Cond1, Value *Cond2, const Twine &Name="")

Value * CreateFNeg(Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)

Instruction * foldSelectToCmp(SelectInst &SI)

bool fmulByZeroIsZero(Value *MulVal, FastMathFlags FMF, const Instruction *CtxI) const

Check if fmul MulVal, +0.0 will yield +0.0 (or signed zero is ignorable).

KnownFPClass computeKnownFPClass(Value *Val, FastMathFlags FMF, FPClassTest Interested=fcAllFlags, const Instruction *CtxI=nullptr, unsigned Depth=0) const

Instruction * foldSelectEqualityTest(SelectInst &SI)

Instruction * foldSelectValueEquivalence(SelectInst &SI, CmpInst &CI)

Instruction * foldOpIntoPhi(Instruction &I, PHINode *PN, bool AllowMultipleUses=false)

Given a binary operator, cast instruction, or select which has a PHI node as operand #0,...

Instruction * foldVectorSelect(SelectInst &Sel)

Value * SimplifyDemandedVectorElts(Value *V, APInt DemandedElts, APInt &PoisonElts, unsigned Depth=0, bool AllowMultipleUsers=false) override

The specified value produces a vector with any number of elements.

Instruction * foldSPFofSPF(Instruction *Inner, SelectPatternFlavor SPF1, Value *A, Value *B, Instruction &Outer, SelectPatternFlavor SPF2, Value *C)

Instruction * foldSelectOpOp(SelectInst &SI, Instruction *TI, Instruction *FI)

We have (select c, TI, FI), and we know that TI and FI have the same opcode.

bool replaceInInstruction(Value *V, Value *Old, Value *New, unsigned Depth=0)

Instruction * foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI)

bool sinkNotIntoOtherHandOfLogicalOp(Instruction &I)

Constant * getLosslessTrunc(Constant *C, Type *TruncTy, unsigned ExtOp)

Instruction * foldSelectIntoOp(SelectInst &SI, Value *, Value *)

Try to fold the select into one of the operands to allow further optimization.

Instruction * visitSelectInst(SelectInst &SI)

Instruction * foldSelectOfBools(SelectInst &SI)

Instruction * foldSelectExtConst(SelectInst &Sel)

The core instruction combiner logic.

const DataLayout & getDataLayout() const

bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero=false, unsigned Depth=0, const Instruction *CxtI=nullptr)

Instruction * InsertNewInstBefore(Instruction *New, BasicBlock::iterator Old)

Inserts an instruction New before instruction Old.

Instruction * replaceInstUsesWith(Instruction &I, Value *V)

A combiner-aware RAUW-like routine.

static bool shouldAvoidAbsorbingNotIntoSelect(const SelectInst &SI)

void replaceUse(Use &U, Value *NewValue)

Replace use and add the previously used value to the worklist.

static bool isCanonicalPredicate(CmpPredicate Pred)

Predicate canonicalization reduces the number of patterns that need to be matched by other transforms...

InstructionWorklist & Worklist

A worklist of the instructions that need to be simplified.

void addToWorklist(Instruction *I)

Instruction * replaceOperand(Instruction &I, unsigned OpNum, Value *V)

Replace operand of instruction and add old operand to the worklist.

void computeKnownBits(const Value *V, KnownBits &Known, unsigned Depth, const Instruction *CxtI) const

Value * getFreelyInverted(Value *V, bool WillInvertAllUses, BuilderTy *Builder, bool &DoesConsume)

const SimplifyQuery & getSimplifyQuery() const

static Constant * AddOne(Constant *C)

Add one to a Constant.

void add(Instruction *I)

Add instruction to the worklist.

void push(Instruction *I)

Push the instruction onto the worklist stack.

bool hasNoNaNs() const LLVM_READONLY

Determine whether the no-NaNs flag is set.

bool hasNoInfs() const LLVM_READONLY

Determine whether the no-infs flag is set.

bool isSameOperationAs(const Instruction *I, unsigned flags=0) const LLVM_READONLY

This function determines if the specified instruction executes the same operation as the current one.

void setHasNoSignedZeros(bool B)

Set or clear the no-signed-zeros flag on this instruction, which must be an operator which supports t...

bool hasNoSignedZeros() const LLVM_READONLY

Determine whether the no-signed-zeros flag is set.

void copyIRFlags(const Value *V, bool IncludeWrapFlags=true)

Convenience method to copy supported exact, fast-math, and (optionally) wrapping flags from V to this...

const Module * getModule() const

Return the module owning the function this instruction belongs to or nullptr it the function does not...

void andIRFlags(const Value *V)

Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.

void setHasNoNaNs(bool B)

Set or clear the no-nans flag on this instruction, which must be an operator which supports this flag...

bool isCommutative() const LLVM_READONLY

Return true if the instruction is commutative:

void setFastMathFlags(FastMathFlags FMF)

Convenience function for setting multiple fast-math flags on this instruction, which must be an opera...

void swapProfMetadata()

If the instruction has "branch_weights" MD_prof metadata and the MDNode has three operands (including...

void setHasNoInfs(bool B)

Set or clear the no-infs flag on this instruction, which must be an operator which supports this flag...

FastMathFlags getFastMathFlags() const LLVM_READONLY

Convenience function for getting all the fast-math flags, which must be an operator which supports th...

unsigned getOpcode() const

Returns a member of one of the enums like Instruction::Add.

void dropPoisonGeneratingFlags()

Drops flags that may cause this instruction to evaluate to poison despite having non-poison inputs.

const DataLayout & getDataLayout() const

Get the data layout of the module this instruction belongs to.

A wrapper class for inspecting calls to intrinsic functions.

A Module instance is used to store all the information related to an LLVM module.

void addIncoming(Value *V, BasicBlock *BB)

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

This class represents a sign extension of integer types.

This class represents the LLVM 'select' instruction.

static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, Instruction *MDFrom=nullptr)

const Value * getFalseValue() const

void swapValues()

Swap the true and false values of the select instruction.

const Value * getCondition() const

const Value * getTrueValue() const

bool insert(const value_type &X)

Insert a new element into the SetVector.

This instruction constructs a fixed permutation of two input vectors.

A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...

bool contains(ConstPtrType Ptr) const

A SetVector that performs no allocations if smaller than a certain size.

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

Provides information about what library functions are available for the current target.

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

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.

static IntegerType * getInt1Ty(LLVMContext &C)

unsigned getScalarSizeInBits() const LLVM_READONLY

If this is a vector type, return the getPrimitiveSizeInBits value for the element type.

bool isPtrOrPtrVectorTy() const

Return true if this is a pointer type or a vector of pointer types.

bool isIntegerTy() const

True if this is an instance of IntegerType.

bool isFPOrFPVectorTy() const

Return true if this is a FP type or a vector of FP.

static UnaryOperator * CreateFNegFMF(Value *Op, Instruction *FMFSource, const Twine &Name="", InsertPosition InsertBefore=nullptr)

A Use represents the edge between a Value definition and its users.

Value * getOperand(unsigned i) const

unsigned getNumOperands() const

LLVM Value Representation.

Type * getType() const

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

const Value * DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB) const

Translate PHI node to its predecessor from the given basic block.

bool hasOneUse() const

Return true if there is exactly one use of this value.

StringRef getName() const

Return a constant reference to the value's name.

void takeName(Value *V)

Transfer the name from V to this value.

Represents an op.with.overflow intrinsic.

This class represents zero extension of integer types.

const ParentTy * getParent() const

self_iterator getIterator()

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

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.

int getMinValue(MCInstrInfo const &MCII, MCInst const &MCI)

Return the minimum value of an extendable operand.

int getMaxValue(MCInstrInfo const &MCII, MCInst const &MCI)

Return the maximum value of an extendable operand.

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

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

Predicate

Predicate - These are "(BI << 5) | BO" for various predicates.

cst_pred_ty< is_all_ones > m_AllOnes()

Match an integer or vector with all bits set.

BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)

BinaryOp_match< cst_pred_ty< is_all_ones, false >, ValTy, Instruction::Xor, true > m_NotForbidPoison(const ValTy &V)

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)

BinaryOp_match< LHS, RHS, Instruction::FMul, true > m_c_FMul(const LHS &L, const RHS &R)

Matches FMul with LHS and RHS in either order.

BinaryOp_match< LHS, RHS, Instruction::AShr > m_AShr(const LHS &L, const RHS &R)

BinaryOp_match< LHS, RHS, Instruction::FSub > m_FSub(const LHS &L, const RHS &R)

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)

class_match< Constant > m_Constant()

Match an arbitrary Constant and ignore it.

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)

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)

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.

constantexpr_match m_ConstantExpr()

Match a constant expression or a constant that contains a constant expression.

specific_intval< true > m_SpecificIntAllowPoison(const APInt &V)

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.

OverflowingBinaryOp_match< cst_pred_ty< is_zero_int >, ValTy, Instruction::Sub, OverflowingBinaryOperator::NoSignedWrap > m_NSWNeg(const ValTy &V)

Matches a 'Neg' as 'sub nsw 0, V'.

TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)

Matches ExtractElementInst.

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.

ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)

Matches SelectInst.

match_combine_or< MaxMin_match< FCmpInst, LHS, RHS, ofmin_pred_ty >, MaxMin_match< FCmpInst, LHS, RHS, ufmin_pred_ty > > m_OrdOrUnordFMin(const LHS &L, const RHS &R)

Match an 'ordered' or 'unordered' floating point minimum function.

BinOpPred_match< LHS, RHS, is_logical_shift_op > m_LogicalShift(const LHS &L, const RHS &R)

Matches logical shift operations.

match_combine_and< LTy, RTy > m_CombineAnd(const LTy &L, const RTy &R)

Combine two pattern matchers matching L && R.

MaxMin_match< ICmpInst, LHS, RHS, smin_pred_ty > m_SMin(const LHS &L, const RHS &R)

cst_pred_ty< is_any_apint > m_AnyIntegralConstant()

Match an integer or vector with any integral constant.

bind_ty< WithOverflowInst > m_WithOverflowInst(WithOverflowInst *&I)

Match a with overflow intrinsic, capturing it if we match.

BinaryOp_match< LHS, RHS, Instruction::FAdd > m_FAdd(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()...

cst_pred_ty< is_zero_int > m_ZeroInt()

Match an integer 0 or a vector with all elements equal to 0.

apint_match m_APIntAllowPoison(const APInt *&Res)

Match APInt while allowing poison in splat vector constants.

NoWrapTrunc_match< OpTy, TruncInst::NoSignedWrap > m_NSWTrunc(const OpTy &Op)

Matches trunc nsw.

OneUse_match< T > m_OneUse(const T &SubPattern)

auto m_LogicalOr()

Matches L || R where L and R are arbitrary values.

BinaryOp_match< cst_pred_ty< is_zero_int >, ValTy, Instruction::Sub > m_Neg(const ValTy &V)

Matches a 'Neg' as 'sub 0, V'.

TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)

Matches ShuffleVectorInst independently of mask value.

match_combine_and< class_match< Constant >, match_unless< constantexpr_match > > m_ImmConstant()

Match an arbitrary immediate Constant and ignore it.

m_Intrinsic_Ty< Opnd0, Opnd1, Opnd2, Opnd3 >::Ty m_MaskedLoad(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2, const Opnd3 &Op3)

Matches MaskedLoad Intrinsic.

SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)

apint_match m_APIntForbidPoison(const APInt *&Res)

Match APInt while forbidding poison in splat vector constants.

CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)

Matches ZExt.

MaxMin_match< ICmpInst, LHS, RHS, umax_pred_ty > m_UMax(const LHS &L, const RHS &R)

class_match< CmpInst > m_Cmp()

Matches any compare instruction and ignore it.

brc_match< Cond_t, bind_ty< BasicBlock >, bind_ty< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)

auto m_c_LogicalOp(const LHS &L, const RHS &R)

Matches either L && R or L || R with LHS and RHS in either order.

NoWrapTrunc_match< OpTy, TruncInst::NoUnsignedWrap > m_NUWTrunc(const OpTy &Op)

Matches trunc nuw.

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.

apfloat_match m_APFloatAllowPoison(const APFloat *&Res)

Match APFloat while allowing poison in splat vector constants.

match_combine_or< MaxMin_match< FCmpInst, LHS, RHS, ofmax_pred_ty >, MaxMin_match< FCmpInst, LHS, RHS, ufmax_pred_ty > > m_OrdOrUnordFMax(const LHS &L, const RHS &R)

Match an 'ordered' or 'unordered' floating point maximum function.

CastOperator_match< OpTy, Instruction::BitCast > m_BitCast(const OpTy &Op)

Matches BitCast.

MaxMin_match< ICmpInst, LHS, RHS, smax_pred_ty > m_SMax(const LHS &L, const RHS &R)

apint_match m_APInt(const APInt *&Res)

Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.

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)

FNeg_match< OpTy > m_FNeg(const OpTy &X)

Match 'fneg X' as 'fsub -0.0, X'.

cstfp_pred_ty< is_pos_zero_fp > m_PosZeroFP()

Match a floating-point positive zero.

LogicalOp_match< LHS, RHS, Instruction::And, true > m_c_LogicalAnd(const LHS &L, const RHS &R)

Matches L && R with LHS and RHS in either order.

BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)

m_Intrinsic_Ty< Opnd0 >::Ty m_VecReverse(const Opnd0 &Op0)

auto m_LogicalAnd()

Matches L && R where L and R are arbitrary values.

match_combine_or< match_combine_or< MaxMin_match< ICmpInst, LHS, RHS, smax_pred_ty >, MaxMin_match< ICmpInst, LHS, RHS, smin_pred_ty > >, match_combine_or< MaxMin_match< ICmpInst, LHS, RHS, umax_pred_ty >, MaxMin_match< ICmpInst, LHS, RHS, umin_pred_ty > > > m_MaxOrMin(const LHS &L, const RHS &R)

class_match< BasicBlock > m_BasicBlock()

Match an arbitrary basic block value and ignore it.

BinaryOp_match< LHS, RHS, Instruction::SRem > m_SRem(const LHS &L, const RHS &R)

auto m_Undef()

Match an arbitrary undef constant.

BinaryOp_match< cst_pred_ty< is_all_ones >, ValTy, Instruction::Xor, true > m_Not(const ValTy &V)

Matches a 'Not' as 'xor V, -1' or 'xor -1, V'.

BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(const LHS &L, const RHS &R)

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.

LogicalOp_match< LHS, RHS, Instruction::Or, true > m_c_LogicalOr(const LHS &L, const RHS &R)

Matches L || R with LHS and RHS in either order.

SpecificCmpClass_match< LHS, RHS, ICmpInst, true > m_c_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)

ElementWiseBitCast_match< OpTy > m_ElementWiseBitCast(const OpTy &Op)

BinaryOp_match< LHS, RHS, Instruction::Mul, true > m_c_Mul(const LHS &L, const RHS &R)

Matches a Mul with LHS and RHS in either order.

BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)

MaxMin_match< ICmpInst, LHS, RHS, umin_pred_ty > m_UMin(const LHS &L, const RHS &R)

m_Intrinsic_Ty< Opnd0, Opnd1, Opnd2, Opnd3 >::Ty m_MaskedGather(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2, const Opnd3 &Op3)

Matches MaskedGather Intrinsic.

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.

ElementType

The element type of an SRV or UAV resource.

DiagnosticInfoOptimizationBase::Argument NV

This is an optimization pass for GlobalISel generic memory operations.

bool isSafeToSpeculativelyExecuteWithVariableReplaced(const Instruction *I)

Don't use information from its non-constant operands.

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.

APFloat abs(APFloat X)

Returns the absolute value of the argument.

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.

CmpInst::Predicate getMinMaxPred(SelectPatternFlavor SPF, bool Ordered=false)

Return the canonical comparison predicate for the specified minimum/maximum flavor.

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.

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)

Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...

constexpr unsigned MaxAnalysisRecursionDepth

SelectPatternFlavor

Specific patterns of select instructions we can match.

@ SPF_ABS

Floating point maxnum.

@ SPF_NABS

Absolute value.

constexpr bool isPowerOf2_32(uint32_t Value)

Return true if the argument is a power of two > 0.

bool impliesPoison(const Value *ValAssumedPoison, const Value *V)

Return true if V is poison given that ValAssumedPoison is already poison.

SelectPatternResult getSelectPattern(CmpInst::Predicate Pred, SelectPatternNaNBehavior NaNBehavior=SPNB_NA, bool Ordered=false)

Determine the pattern for predicate X Pred Y ? X : Y.

SelectPatternResult matchSelectPattern(Value *V, Value *&LHS, Value *&RHS, Instruction::CastOps *CastOp=nullptr, unsigned Depth=0)

Pattern match integer [SU]MIN, [SU]MAX and ABS idioms, returning the kind and providing the out param...

bool none_of(R &&Range, UnaryPredicate P)

Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.

Constant * ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy, const DataLayout &DL)

Attempt to constant fold a cast with the specified operand.

Value * simplifyAndInst(Value *LHS, Value *RHS, const SimplifyQuery &Q)

Given operands for an And, fold the result or return null.

bool isKnownInversion(const Value *X, const Value *Y)

Return true iff:

bool isNotCrossLaneOperation(const Instruction *I)

Return true if the instruction doesn't potentially cross vector lanes.

Constant * ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS, Constant *RHS, const DataLayout &DL)

Attempt to constant fold a binary operation with the specified operands.

constexpr int PoisonMaskElem

Intrinsic::ID getMinMaxIntrinsic(SelectPatternFlavor SPF)

Convert given SPF to equivalent min/max intrinsic.

@ Or

Bitwise or logical OR of integers.

@ Mul

Product of integers.

@ Xor

Bitwise or logical XOR of integers.

@ And

Bitwise or logical AND of integers.

std::optional< DecomposedBitTest > decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate Pred, bool LookThroughTrunc=true, bool AllowNonZeroC=false)

Decompose an icmp into the form ((X & Mask) pred C) if possible.

void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true)

Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...

DWARFExpression::Operation Op

constexpr unsigned BitWidth

SelectPatternResult matchDecomposedSelectPattern(CmpInst *CmpI, Value *TrueVal, Value *FalseVal, Value *&LHS, Value *&RHS, Instruction::CastOps *CastOp=nullptr, unsigned Depth=0)

Determine the pattern that a select with the given compare as its predicate and given values as its t...

Value * simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, const SimplifyQuery &Q, bool AllowRefinement, SmallVectorImpl< Instruction * > *DropFlags=nullptr)

See if V simplifies when its operand Op is replaced with RepOp.

auto predecessors(const MachineBasicBlock *BB)

std::optional< std::pair< CmpPredicate, Constant * > > getFlippedStrictnessPredicateAndConstant(CmpPredicate Pred, Constant *C)

Convert an integer comparison with a constant RHS into an equivalent form with the strictness flipped...

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

Returns true if Element is found in Range.

bool cannotBeNegativeZero(const Value *V, unsigned Depth, const SimplifyQuery &SQ)

Return true if we can prove that the specified FP value is never equal to -0.0.

bool isKnownNeverNaN(const Value *V, unsigned Depth, const SimplifyQuery &SQ)

Return true if the floating-point scalar value is not a NaN or if the floating-point vector value has...

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.

bool isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd, Use *&Y)

Match one of the patterns up to the select/logic op: Op0 = icmp ne i4 X, 0 Agg = call { i4,...

Value * simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, const SimplifyQuery &Q)

Given operands for a SelectInst, fold the result or return null.

std::optional< bool > isImpliedCondition(const Value *LHS, const Value *RHS, const DataLayout &DL, bool LHSIsTrue=true, unsigned Depth=0)

Return true if RHS is known to be implied true by LHS.

void findValuesAffectedByCondition(Value *Cond, bool IsAssume, function_ref< void(Value *)> InsertAffected)

Call InsertAffected on all Values whose known bits / value may be affected by the condition Cond.

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.

Evaluate query assuming this condition holds.

Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...

bool isConstant() const

Returns true if we know the value of all bits.

const APInt & getConstant() const

Returns the value when all bits have a known value.

bool isKnownNeverInfinity() const

Return true if it's known this can never be an infinity.

bool isKnownNeverNaN() const

Return true if it's known this can never be a nan.

bool signBitIsZeroOrNaN() const

Return true if the sign bit must be 0, ignoring the sign of nans.

SelectPatternFlavor Flavor

bool Ordered

Only applicable if Flavor is SPF_FMINNUM or SPF_FMAXNUM.

static bool isMinOrMax(SelectPatternFlavor SPF)

When implementing this min/max pattern as fcmp; select, does the fcmp have to be ordered?

SimplifyQuery getWithCondContext(const CondContext &CC) const

SimplifyQuery getWithInstruction(const Instruction *I) const