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

1

2

3

4

5

6

7

8

9

10

11

12

27using namespace llvm;

28using namespace PatternMatch;

29

30#define DEBUG_TYPE "instcombine"

31

32STATISTIC(NumDeadStore, "Number of dead stores eliminated");

33STATISTIC(NumGlobalCopies, "Number of allocas copied from constant global");

34

36 "instcombine-max-copied-from-constant-users", cl::init(300),

37 cl::desc("Maximum users to visit in copy from constant transform"),

39

40

41

42

43

44

45

46

47static bool

51

52

53

54

59 while (!Worklist.empty()) {

60 ValueAndIsOffset Elem = Worklist.pop_back_val();

61 if (!Visited.insert(Elem).second)

62 continue;

64 return false;

65

66 const auto [Value, IsOffset] = Elem;

68 auto *I = cast(U.getUser());

69

70 if (auto *LI = dyn_cast(I)) {

71

72 if (!LI->isSimple()) return false;

73 continue;

74 }

75

76 if (isa<PHINode, SelectInst>(I)) {

77

78

79

81 continue;

82 }

83 if (isa<BitCastInst, AddrSpaceCastInst>(I)) {

84

86 continue;

87 }

88 if (auto *GEP = dyn_cast(I)) {

89

90

91 Worklist.emplace_back(I, IsOffset || GEP->hasAllZeroIndices());

92 continue;

93 }

94

95 if (auto *Call = dyn_cast(I)) {

96

97

98 if (Call->isCallee(&U))

99 continue;

100

101 unsigned DataOpNo = Call->getDataOperandNo(&U);

102 bool IsArgOperand = Call->isArgOperand(&U);

103

104

105 if (IsArgOperand && Call->isInAllocaArgument(DataOpNo))

106 return false;

107

108

109

110

111 bool NoCapture = Call->doesNotCapture(DataOpNo);

112 if ((Call->onlyReadsMemory() && (Call->use_empty() || NoCapture)) ||

113 (Call->onlyReadsMemory(DataOpNo) && NoCapture))

114 continue;

115 }

116

117

118 if (I->isLifetimeStartOrEnd()) {

119 assert(I->use_empty() && "Lifetime markers have no result to use!");

121 continue;

122 }

123

124

125

127 if (MI)

128 return false;

129

130

131 if (MI->isVolatile())

132 return false;

133

134

135

136 if (U.getOperandNo() == 1)

137 continue;

138

139

140 if (TheCopy) return false;

141

142

143

144 if (IsOffset) return false;

145

146

147 if (U.getOperandNo() != 0) return false;

148

149

151 return false;

152

153

154 TheCopy = MI;

155 }

156 }

157 return true;

158}

159

160

161

162

163

170 return TheCopy;

171 return nullptr;

172}

173

174

178 return false;

180 if (!AllocaSize)

181 return false;

183 APInt(64, AllocaSize), DL);

184}

185

188

190

192 return nullptr;

193

194

196 }

197

198

200 if (C->getValue().getActiveBits() <= 64) {

204 New->setAlignment(AI.getAlign());

206

209 }

210 }

211

214

215

216

217

222 }

223

224 return nullptr;

225}

226

227namespace {

228

229

230

231

232

233

234

235

236

237

238class PointerReplacer {

239public:

241 : IC(IC), Root(Root), FromAS(SrcAS) {}

242

243 bool collectUsers();

244 void replacePointer(Value *V);

245

246private:

251 return I == &Root || Worklist.contains(I);

252 }

253

254 bool isEqualOrValidAddrSpaceCast(const Instruction *I,

255 unsigned FromAS) const {

256 const auto *ASC = dyn_cast(I);

257 if (!ASC)

258 return false;

259 unsigned ToAS = ASC->getDestAddressSpace();

260 return (FromAS == ToAS) || IC.isValidAddrSpaceCast(FromAS, ToAS);

261 }

262

268 unsigned FromAS;

269};

270}

271

272bool PointerReplacer::collectUsers() {

273 if (!collectUsersRecursive(Root))

274 return false;

275

276

277

278

280}

281

282bool PointerReplacer::collectUsersRecursive(Instruction &I) {

283 for (auto *U : I.users()) {

284 auto *Inst = cast(&*U);

285 if (auto *Load = dyn_cast(Inst)) {

286 if (Load->isVolatile())

287 return false;

288 Worklist.insert(Load);

289 } else if (auto *PHI = dyn_cast(Inst)) {

290

291 if (any_of(PHI->incoming_values(),

292 [](Value *V) { return !isa(V); }))

293 return false;

294

295

296

297

298 if (any_of(PHI->incoming_values(), [this](Value *V) {

299 return !isAvailable(cast(V));

300 })) {

301 ValuesToRevisit.insert(Inst);

302 continue;

303 }

304

305 Worklist.insert(PHI);

306 if (!collectUsersRecursive(*PHI))

307 return false;

308 } else if (auto *SI = dyn_cast(Inst)) {

309 if (!isa(SI->getTrueValue()) ||

310 !isa(SI->getFalseValue()))

311 return false;

312

313 if (isAvailable(cast(SI->getTrueValue())) ||

314 isAvailable(cast(SI->getFalseValue()))) {

315 ValuesToRevisit.insert(Inst);

316 continue;

317 }

318 Worklist.insert(SI);

319 if (!collectUsersRecursive(*SI))

320 return false;

321 } else if (isa(Inst)) {

322 Worklist.insert(Inst);

323 if (!collectUsersRecursive(*Inst))

324 return false;

325 } else if (auto *MI = dyn_cast(Inst)) {

326 if (MI->isVolatile())

327 return false;

328 Worklist.insert(Inst);

329 } else if (isEqualOrValidAddrSpaceCast(Inst, FromAS)) {

330 Worklist.insert(Inst);

331 if (!collectUsersRecursive(*Inst))

332 return false;

333 } else if (Inst->isLifetimeStartOrEnd()) {

334 continue;

335 } else {

336

337

338 LLVM_DEBUG(dbgs() << "Cannot handle pointer user: " << *U << '\n');

339 return false;

340 }

341 }

342

343 return true;

344}

345

346Value *PointerReplacer::getReplacement(Value *V) { return WorkMap.lookup(V); }

347

348void PointerReplacer::replace(Instruction *I) {

349 if (getReplacement(I))

350 return;

351

352 if (auto *LT = dyn_cast(I)) {

353 auto *V = getReplacement(LT->getPointerOperand());

354 assert(V && "Operand not replaced");

355 auto *NewI = new LoadInst(LT->getType(), V, "", LT->isVolatile(),

356 LT->getAlign(), LT->getOrdering(),

357 LT->getSyncScopeID());

358 NewI->takeName(LT);

360

361 IC.InsertNewInstWith(NewI, LT->getIterator());

362 IC.replaceInstUsesWith(*LT, NewI);

363 WorkMap[LT] = NewI;

364 } else if (auto *PHI = dyn_cast(I)) {

365 Type *NewTy = getReplacement(PHI->getIncomingValue(0))->getType();

367 PHI->getName(), PHI->getIterator());

368 for (unsigned int I = 0; I < PHI->getNumIncomingValues(); ++I)

369 NewPHI->addIncoming(getReplacement(PHI->getIncomingValue(I)),

370 PHI->getIncomingBlock(I));

371 WorkMap[PHI] = NewPHI;

372 } else if (auto *GEP = dyn_cast(I)) {

373 auto *V = getReplacement(GEP->getPointerOperand());

374 assert(V && "Operand not replaced");

376 auto *NewI =

378 IC.InsertNewInstWith(NewI, GEP->getIterator());

379 NewI->takeName(GEP);

380 NewI->setNoWrapFlags(GEP->getNoWrapFlags());

381 WorkMap[GEP] = NewI;

382 } else if (auto *SI = dyn_cast(I)) {

383 Value *TrueValue = SI->getTrueValue();

384 Value *FalseValue = SI->getFalseValue();

385 if (Value *Replacement = getReplacement(TrueValue))

386 TrueValue = Replacement;

387 if (Value *Replacement = getReplacement(FalseValue))

388 FalseValue = Replacement;

390 SI->getName(), nullptr, SI);

391 IC.InsertNewInstWith(NewSI, SI->getIterator());

392 NewSI->takeName(SI);

393 WorkMap[SI] = NewSI;

394 } else if (auto *MemCpy = dyn_cast(I)) {

395 auto *DestV = MemCpy->getRawDest();

396 auto *SrcV = MemCpy->getRawSource();

397

398 if (auto *DestReplace = getReplacement(DestV))

399 DestV = DestReplace;

400 if (auto *SrcReplace = getReplacement(SrcV))

401 SrcV = SrcReplace;

402

403 IC.Builder.SetInsertPoint(MemCpy);

404 auto *NewI = IC.Builder.CreateMemTransferInst(

405 MemCpy->getIntrinsicID(), DestV, MemCpy->getDestAlign(), SrcV,

406 MemCpy->getSourceAlign(), MemCpy->getLength(), MemCpy->isVolatile());

407 AAMDNodes AAMD = MemCpy->getAAMetadata();

408 if (AAMD)

409 NewI->setAAMetadata(AAMD);

410

411 IC.eraseInstFromFunction(*MemCpy);

412 WorkMap[MemCpy] = NewI;

413 } else if (auto *ASC = dyn_cast(I)) {

414 auto *V = getReplacement(ASC->getPointerOperand());

415 assert(V && "Operand not replaced");

416 assert(isEqualOrValidAddrSpaceCast(

417 ASC, V->getType()->getPointerAddressSpace()) &&

418 "Invalid address space cast!");

419

420 if (V->getType()->getPointerAddressSpace() !=

421 ASC->getType()->getPointerAddressSpace()) {

423 NewI->takeName(ASC);

424 IC.InsertNewInstWith(NewI, ASC->getIterator());

425 WorkMap[ASC] = NewI;

426 } else {

427 WorkMap[ASC] = V;

428 }

429

430 } else {

432 }

433}

434

435void PointerReplacer::replacePointer(Value *V) {

436#ifndef NDEBUG

437 auto *PT = cast(Root.getType());

438 auto *NT = cast(V->getType());

439 assert(PT != NT && "Invalid usage");

440#endif

441 WorkMap[&Root] = V;

442

445}

446

449 return I;

450

452

453

454

456

457

458

462

463

466 if (FirstInst != &AI) {

467

468

469

470 AllocaInst *EntryAI = dyn_cast(FirstInst);

475 return &AI;

476 }

477

478

479

480

484 }

485 }

486 }

487

488

489

490

491

492

493

496 Value *TheSrc = Copy->getSource();

499 TheSrc, AllocaAlign, DL, &AI, &AC, &DT);

500 if (AllocaAlign <= SourceAlign &&

502 !isa(TheSrc)) {

503

504

505 LLVM_DEBUG(dbgs() << "Found alloca equal to global: " << AI << '\n');

511

514 ++NumGlobalCopies;

515 return NewI;

516 }

517

518 PointerReplacer PtrReplacer(*this, AI, SrcAddrSpace);

519 if (PtrReplacer.collectUsers()) {

522

523 PtrReplacer.replacePointer(TheSrc);

524 ++NumGlobalCopies;

525 }

526 }

527 }

528

529

530

532}

533

534

537}

538

539

540

541

542

543

544

545

546

547

549 const Twine &Suffix) {

551 "can't fold an atomic load to requested type");

552

558 return NewLoad;

559}

560

561

562

563

567 "can't fold an atomic store of requested type");

568

569 Value *Ptr = SI.getPointerOperand();

571 SI.getAllMetadata(MD);

572

575 NewStore->setAtomic(SI.getOrdering(), SI.getSyncScopeID());

576 for (const auto &MDPair : MD) {

577 unsigned ID = MDPair.first;

578 MDNode *N = MDPair.second;

579

580

581

582

583

584

585

586

587 switch (ID) {

588 case LLVMContext::MD_dbg:

589 case LLVMContext::MD_DIAssignID:

590 case LLVMContext::MD_tbaa:

591 case LLVMContext::MD_prof:

592 case LLVMContext::MD_fpmath:

593 case LLVMContext::MD_tbaa_struct:

594 case LLVMContext::MD_alias_scope:

595 case LLVMContext::MD_noalias:

596 case LLVMContext::MD_nontemporal:

597 case LLVMContext::MD_mem_parallel_loop_access:

598 case LLVMContext::MD_access_group:

599

601 break;

602 case LLVMContext::MD_invariant_load:

603 case LLVMContext::MD_nonnull:

604 case LLVMContext::MD_noundef:

605 case LLVMContext::MD_range:

606 case LLVMContext::MD_align:

607 case LLVMContext::MD_dereferenceable:

608 case LLVMContext::MD_dereferenceable_or_null:

609

610 break;

611 }

612 }

613

614 return NewStore;

615}

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

636

637

638 if (!Load.isUnordered())

639 return nullptr;

640

641 if (Load.use_empty())

642 return nullptr;

643

644

645 if (Load.getPointerOperand()->isSwiftError())

646 return nullptr;

647

648

649

650

651 if (Load.hasOneUse()) {

652

653

654 Type *LoadTy = Load.getType();

655 if (auto *BC = dyn_cast(Load.user_back())) {

656 assert(!LoadTy->isX86_AMXTy() && "Load from x86_amx* should not happen!");

657 if (BC->getType()->isX86_AMXTy())

658 return nullptr;

659 }

660

661 if (auto *CastUser = dyn_cast(Load.user_back())) {

662 Type *DestTy = CastUser->getDestTy();

669 return &Load;

670 }

671 }

672 }

673

674

675

676 return nullptr;

677}

678

680

681

683 return nullptr;

684

686 if (T->isAggregateType())

687 return nullptr;

688

690

691 if (auto *ST = dyn_cast(T)) {

692

693 auto NumElements = ST->getNumElements();

694 if (NumElements == 1) {

696 ".unpack");

700 }

701

702

703

705 auto *SL = DL.getStructLayout(ST);

706

707

708 if (SL->getSizeInBits().isScalable())

709 return nullptr;

710

711 if (SL->hasPadding())

712 return nullptr;

713

717 auto *Zero = ConstantInt::get(IdxType, 0);

718

720 for (unsigned i = 0; i < NumElements; i++) {

721 Value *Indices[2] = {

722 Zero,

723 ConstantInt::get(IdxType, i),

724 };

726 Name + ".elt");

728 ST->getElementType(i), Ptr,

730

733 }

734

735 V->setName(Name);

737 }

738

739 if (auto *AT = dyn_cast(T)) {

740 auto *ET = AT->getElementType();

741 auto NumElements = AT->getNumElements();

742 if (NumElements == 1) {

747 }

748

749

750

751

752

754 return nullptr;

755

757 TypeSize EltSize = DL.getTypeAllocSize(ET);

759

762 auto *Zero = ConstantInt::get(IdxType, 0);

763

766 for (uint64_t i = 0; i < NumElements; i++) {

767 Value *Indices[2] = {

768 Zero,

769 ConstantInt::get(IdxType, i),

770 };

772 Name + ".elt");

775 EltAlign, Name + ".unpack");

779 }

780

781 V->setName(Name);

783 }

784

785 return nullptr;

786}

787

788

789

790

791

792

793

798

799 do {

801 P = P->stripPointerCasts();

802

803 if (!Visited.insert(P).second)

804 continue;

805

806 if (SelectInst *SI = dyn_cast(P)) {

807 Worklist.push_back(SI->getTrueValue());

808 Worklist.push_back(SI->getFalseValue());

809 continue;

810 }

811

812 if (PHINode *PN = dyn_cast(P)) {

813 append_range(Worklist, PN->incoming_values());

814 continue;

815 }

816

817 if (GlobalAlias *GA = dyn_cast(P)) {

818 if (GA->isInterposable())

819 return false;

820 Worklist.push_back(GA->getAliasee());

821 continue;

822 }

823

824

825

826 if (AllocaInst *AI = dyn_cast(P)) {

827 if (!AI->getAllocatedType()->isSized())

828 return false;

829

830 ConstantInt *CS = dyn_cast(AI->getArraySize());

831 if (!CS)

832 return false;

833

834 TypeSize TS = DL.getTypeAllocSize(AI->getAllocatedType());

836 return false;

837

838

840 .ugt(MaxSize))

841 return false;

842 continue;

843 }

844

846 if (!GV->hasDefinitiveInitializer() || !GV->isConstant())

847 return false;

848

849 uint64_t InitSize = DL.getTypeAllocSize(GV->getValueType());

850 if (InitSize > MaxSize)

851 return false;

852 continue;

853 }

854

855 return false;

856 } while (!Worklist.empty());

857

858 return true;

859}

860

861

862

863

864

865

866

867

868

869

870

871

872

873

874

875

878 unsigned &Idx) {

880 return false;

881

882

883

885 unsigned I = 1;

888 if (const ConstantInt *CI = dyn_cast(V))

889 if (CI->isZero())

890 continue;

891

892 break;

893 }

894

895 return I;

896 };

897

898

899

900 Idx = FirstNZIdx(GEPI);

902 return false;

904 return false;

905

908

909

911 return false;

912

914 if (!AllocTy || !AllocTy->isSized())

915 return false;

917 uint64_t TyAllocSize = DL.getTypeAllocSize(AllocTy).getFixedValue();

918

919

920

921

922

923 auto IsAllNonNegative = [&]() {

924 for (unsigned i = Idx+1, e = GEPI->getNumOperands(); i != e; ++i) {

927 continue;

928 return false;

929 }

930

931 return true;

932 };

933

934

935

936

937

938

940 return false;

941

942

943

945 IsAllNonNegative();

946}

947

948

949

950

954 unsigned Idx;

958 ConstantInt::get(GEPI->getOperand(Idx)->getType(), 0));

960 return NewGEPI;

961 }

962 }

963

964 return nullptr;

965}

966

969 return false;

970

971 auto *Ptr = SI.getPointerOperand();

973 Ptr = GEPI->getOperand(0);

974 return (isa(Ptr) &&

976}

977

980 const Value *GEPI0 = GEPI->getOperand(0);

981 if (isa(GEPI0) &&

983 return true;

984 }

985 if (isa(Op) ||

986 (isa(Op) &&

988 return true;

989 return false;

990}

991

996

997

999 return Res;

1000

1001

1004

1006 return Res;

1007

1008

1009

1010

1011 bool IsLoadCSE = false;

1014 if (IsLoadCSE)

1016

1019 LI.getName() + ".cast"));

1020 }

1021

1022

1023

1025

1026

1027

1028

1032 }

1033

1034 if (Op->hasOneUse()) {

1035

1036

1037

1038

1039

1040

1041

1042

1043

1044

1045 if (SelectInst *SI = dyn_cast(Op)) {

1046

1049 Alignment, DL, SI) &&

1051 Alignment, DL, SI)) {

1054 SI->getOperand(1)->getName() + ".val");

1057 SI->getOperand(2)->getName() + ".val");

1061 V2->setAlignment(Alignment);

1063

1064

1068 }

1069

1070

1071 if (isa(SI->getOperand(1)) &&

1075

1076

1077 if (isa(SI->getOperand(2)) &&

1081 }

1082 }

1083 return nullptr;

1084}

1085

1086

1087

1088

1089

1090

1091

1092

1093

1094

1095

1096

1097

1098

1099

1101 Value *U = nullptr;

1102 while (auto *IV = dyn_cast(V)) {

1103 auto *E = dyn_cast(IV->getInsertedValueOperand());

1104 if (!E)

1105 return nullptr;

1106 auto *W = E->getVectorOperand();

1107 if (!U)

1108 U = W;

1109 else if (U != W)

1110 return nullptr;

1111 auto *CI = dyn_cast(E->getIndexOperand());

1112 if (!CI || IV->getNumIndices() != 1 || CI->getZExtValue() != *IV->idx_begin())

1113 return nullptr;

1114 V = IV->getAggregateOperand();

1115 }

1117 return nullptr;

1118

1119 auto *UT = cast(U->getType());

1120 auto *VT = V->getType();

1121

1123 if (DL.getTypeStoreSizeInBits(UT) != DL.getTypeStoreSizeInBits(VT)) {

1124 return nullptr;

1125 }

1126 if (auto *AT = dyn_cast(VT)) {

1127 if (AT->getNumElements() != cast(UT)->getNumElements())

1128 return nullptr;

1129 } else {

1130 auto *ST = cast(VT);

1131 if (ST->getNumElements() != cast(UT)->getNumElements())

1132 return nullptr;

1133 for (const auto *EltT : ST->elements()) {

1134 if (EltT != UT->getElementType())

1135 return nullptr;

1136 }

1137 }

1138 return U;

1139}

1140

1141

1142

1143

1144

1145

1146

1147

1148

1149

1150

1151

1152

1153

1154

1155

1156

1157

1158

1159

1160

1162

1163

1164 if (!SI.isUnordered())

1165 return false;

1166

1167

1168 if (SI.getPointerOperand()->isSwiftError())

1169 return false;

1170

1171 Value *V = SI.getValueOperand();

1172

1173

1174 if (auto *BC = dyn_cast(V)) {

1175 assert(!BC->getType()->isX86_AMXTy() &&

1176 "store to x86_amx* should not happen!");

1177 V = BC->getOperand(0);

1178

1179

1180 if (V->getType()->isX86_AMXTy())

1181 return false;

1184 return true;

1185 }

1186 }

1187

1191 return true;

1192 }

1193

1194

1195

1196 return false;

1197}

1198

1200

1201

1202 if (!SI.isSimple())

1203 return false;

1204

1205 Value *V = SI.getValueOperand();

1206 Type *T = V->getType();

1207

1208 if (T->isAggregateType())

1209 return false;

1210

1211 if (auto *ST = dyn_cast(T)) {

1212

1213 unsigned Count = ST->getNumElements();

1214 if (Count == 1) {

1217 return true;

1218 }

1219

1220

1221

1223 auto *SL = DL.getStructLayout(ST);

1224

1225

1226 if (SL->getSizeInBits().isScalable())

1227 return false;

1228

1229 if (SL->hasPadding())

1230 return false;

1231

1232 const auto Align = SI.getAlign();

1233

1235 EltName += ".elt";

1236 auto *Addr = SI.getPointerOperand();

1238 AddrName += ".repack";

1239

1241 auto *Zero = ConstantInt::get(IdxType, 0);

1242 for (unsigned i = 0; i < Count; i++) {

1243 Value *Indices[2] = {

1244 Zero,

1245 ConstantInt::get(IdxType, i),

1246 };

1247 auto *Ptr =

1253 }

1254

1255 return true;

1256 }

1257

1258 if (auto *AT = dyn_cast(T)) {

1259

1260 auto NumElements = AT->getNumElements();

1261 if (NumElements == 1) {

1264 return true;

1265 }

1266

1267

1268

1269

1270

1272 return false;

1273

1275 TypeSize EltSize = DL.getTypeAllocSize(AT->getElementType());

1276 const auto Align = SI.getAlign();

1277

1279 EltName += ".elt";

1280 auto *Addr = SI.getPointerOperand();

1282 AddrName += ".repack";

1283

1285 auto *Zero = ConstantInt::get(IdxType, 0);

1286

1288 for (uint64_t i = 0; i < NumElements; i++) {

1289 Value *Indices[2] = {

1290 Zero,

1291 ConstantInt::get(IdxType, i),

1292 };

1293 auto *Ptr =

1300 }

1301

1302 return true;

1303 }

1304

1305 return false;

1306}

1307

1308

1309

1310

1311

1312

1313

1314

1315

1317

1318 if (A == B) return true;

1319

1320

1321

1322

1323

1324

1325 if (isa(A) ||

1326 isa(A) ||

1327 isa(A) ||

1328 isa(A))

1329 if (Instruction *BI = dyn_cast(B))

1330 if (cast(A)->isIdenticalToWhenDefined(BI))

1331 return true;

1332

1333

1334 return false;

1335}

1336

1338 Value *Val = SI.getOperand(0);

1339 Value *Ptr = SI.getOperand(1);

1340

1341

1344

1345

1348

1349

1352

1353

1354

1355 if (!SI.isUnordered()) return nullptr;

1356

1357

1358

1359 if (Ptr->hasOneUse()) {

1360 if (isa(Ptr))

1363 if (isa(GEP->getOperand(0))) {

1364 if (GEP->getOperand(0)->hasOneUse())

1366 }

1367 }

1368 }

1369

1370

1371

1372

1375

1376

1377

1378

1380 for (unsigned ScanInsts = 6; BBI != SI.getParent()->begin() && ScanInsts;

1381 --ScanInsts) {

1382 --BBI;

1383

1384

1385 if (BBI->isDebugOrPseudoInst()) {

1386 ScanInsts++;

1387 continue;

1388 }

1389

1390 if (StoreInst *PrevSI = dyn_cast(BBI)) {

1391

1392 if (PrevSI->isUnordered() &&

1394 PrevSI->getValueOperand()->getType() ==

1395 SI.getValueOperand()->getType()) {

1396 ++NumDeadStore;

1397

1398

1399

1402 return nullptr;

1403 }

1404 break;

1405 }

1406

1407

1408

1409

1410 if (LoadInst *LI = dyn_cast(BBI)) {

1412 assert(SI.isUnordered() && "can't eliminate ordering operation");

1414 }

1415

1416

1417

1418 break;

1419 }

1420

1421

1422 if (BBI->mayWriteToMemory() || BBI->mayReadFromMemory() || BBI->mayThrow())

1423 break;

1424 }

1425

1426

1427

1429 if (!isa(Val))

1431 return nullptr;

1432 }

1433

1434

1435 if (isa(Ptr)) {

1436

1438 return &SI;

1439

1440

1441

1445 return nullptr;

1446 }

1447

1448

1449

1450

1451 if (isa(Val))

1453

1454 return nullptr;

1455}

1456

1457

1458

1459

1460

1461

1463 if (!SI.isUnordered())

1464 return false;

1465

1466

1467 BasicBlock *StoreBB = SI.getParent();

1470 return false;

1471

1472

1474 if (*PredIter == StoreBB)

1475 ++PredIter;

1477

1478

1479

1480 if (StoreBB == DestBB || OtherBB == DestBB)

1481 return false;

1482

1483

1485 BranchInst *OtherBr = dyn_cast(BBI);

1486 if (!OtherBr || BBI == OtherBB->begin())

1487 return false;

1488

1489 auto OtherStoreIsMergeable = [&](StoreInst *OtherStore) -> bool {

1490 if (!OtherStore ||

1491 OtherStore->getPointerOperand() != SI.getPointerOperand())

1492 return false;

1493

1494 auto *SIVTy = SI.getValueOperand()->getType();

1495 auto *OSVTy = OtherStore->getValueOperand()->getType();

1497 SI.hasSameSpecialState(OtherStore);

1498 };

1499

1500

1501

1502 StoreInst *OtherStore = nullptr;

1504 --BBI;

1505

1506 while (BBI->isDebugOrPseudoInst()) {

1507 if (BBI==OtherBB->begin())

1508 return false;

1509 --BBI;

1510 }

1511

1512

1513 OtherStore = dyn_cast(BBI);

1514 if (!OtherStoreIsMergeable(OtherStore))

1515 return false;

1516 } else {

1517

1518

1521 return false;

1522

1523

1524

1525

1526 for (;; --BBI) {

1527

1528 OtherStore = dyn_cast(BBI);

1529 if (OtherStoreIsMergeable(OtherStore))

1530 break;

1531

1532

1533

1534 if (BBI->mayReadFromMemory() || BBI->mayThrow() ||

1535 BBI->mayWriteToMemory() || BBI == OtherBB->begin())

1536 return false;

1537 }

1538

1539

1540

1542

1543 if (I->mayReadFromMemory() || I->mayThrow() || I->mayWriteToMemory())

1544 return false;

1545 }

1546 }

1547

1548

1550

1553 if (MergedVal != SI.getValueOperand()) {

1555 PHINode::Create(SI.getValueOperand()->getType(), 2, "storemerge");

1556 PN->addIncoming(SI.getValueOperand(), SI.getParent());

1559 OtherBB);

1562 }

1563

1564

1567 new StoreInst(MergedVal, SI.getOperand(1), SI.isVolatile(), SI.getAlign(),

1568 SI.getOrdering(), SI.getSyncScopeID());

1572

1573

1574 AAMDNodes AATags = SI.getAAMetadata();

1575 if (AATags)

1577

1578

1581 return true;

1582}

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")

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

This file provides internal interfaces used to implement the InstCombine.

static StoreInst * combineStoreToNewValue(InstCombinerImpl &IC, StoreInst &SI, Value *V)

Combine a store to a new type.

static Instruction * combineLoadToOperationType(InstCombinerImpl &IC, LoadInst &Load)

Combine loads to match the type of their uses' value after looking through intervening bitcasts.

static Instruction * replaceGEPIdxWithZero(InstCombinerImpl &IC, Value *Ptr, Instruction &MemI)

static Instruction * simplifyAllocaArraySize(InstCombinerImpl &IC, AllocaInst &AI, DominatorTree &DT)

static bool canSimplifyNullStoreOrGEP(StoreInst &SI)

static bool equivalentAddressValues(Value *A, Value *B)

equivalentAddressValues - Test if A and B will obviously have the same value.

static bool canReplaceGEPIdxWithZero(InstCombinerImpl &IC, GetElementPtrInst *GEPI, Instruction *MemI, unsigned &Idx)

static bool canSimplifyNullLoadOrGEP(LoadInst &LI, Value *Op)

static bool isSupportedAtomicType(Type *Ty)

static bool isDereferenceableForAllocaSize(const Value *V, const AllocaInst *AI, const DataLayout &DL)

Returns true if V is dereferenceable for size of alloca.

static Instruction * unpackLoadToAggregate(InstCombinerImpl &IC, LoadInst &LI)

static cl::opt< unsigned > MaxCopiedFromConstantUsers("instcombine-max-copied-from-constant-users", cl::init(300), cl::desc("Maximum users to visit in copy from constant transform"), cl::Hidden)

static bool combineStoreToValueType(InstCombinerImpl &IC, StoreInst &SI)

Combine stores to match the type of value being stored.

static bool unpackStoreToAggregate(InstCombinerImpl &IC, StoreInst &SI)

static Value * likeBitCastFromVector(InstCombinerImpl &IC, Value *V)

Look for extractelement/insertvalue sequence that acts like a bitcast.

static bool isOnlyCopiedFromConstantMemory(AAResults *AA, AllocaInst *V, MemTransferInst *&TheCopy, SmallVectorImpl< Instruction * > &ToDelete)

isOnlyCopiedFromConstantMemory - Recursively walk the uses of a (derived) pointer to an alloca.

static bool isObjectSizeLessThanOrEq(Value *V, uint64_t MaxSize, const DataLayout &DL)

This file provides the interface for the instcombine pass implementation.

This file implements a map that provides insertion order iteration.

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

This file defines generic set operations that may be used on set's of different types,...

This file defines the SmallString class.

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

#define STATISTIC(VARNAME, DESC)

static const uint32_t IV[8]

ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, bool IgnoreLocals=false)

Returns a bitmask that should be unconditionally applied to the ModRef info of a memory location.

Class for arbitrary precision integers.

APInt zext(unsigned width) const

Zero extend to a new width.

This class represents a conversion between pointers from one address space to another.

an instruction to allocate memory on the stack

Align getAlign() const

Return the alignment of the memory that is being allocated by the instruction.

PointerType * getType() const

Overload to return most specific pointer type.

Type * getAllocatedType() const

Return the type that is being allocated by the instruction.

bool isUsedWithInAlloca() const

Return true if this alloca is used as an inalloca argument to a call.

unsigned getAddressSpace() const

Return the address space for the allocation.

bool isArrayAllocation() const

Return true if there is an allocation size parameter to the allocation instruction that is not 1.

void setAlignment(Align Align)

const Value * getArraySize() const

Get the number of elements allocated.

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

LLVM Basic Block Representation.

iterator begin()

Instruction iterator methods.

const_iterator getFirstInsertionPt() const

Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...

bool hasNPredecessors(unsigned N) const

Return true if this block has exactly N predecessors.

const Instruction * getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const

Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...

InstListType::iterator iterator

Instruction iterators...

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

This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...

Conditional or Unconditional Branch instruction.

BasicBlock * getSuccessor(unsigned i) const

bool isUnconditional() const

static bool isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy, const DataLayout &DL)

Check whether a bitcast, inttoptr, or ptrtoint cast between these types is valid and a no-op.

This is the shared class of boolean and integer constants.

const APInt & getValue() const

Return the constant as an APInt value reference.

static Constant * getNullValue(Type *Ty)

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

static DILocation * getMergedLocation(DILocation *LocA, DILocation *LocB)

When two instructions are combined into a single instruction we also need to combine the original loc...

This class represents an Operation in the Expression.

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

IntegerType * getIndexType(LLVMContext &C, unsigned AddressSpace) const

Returns the type of a GEP index in AddressSpace.

TypeSize getTypeAllocSize(Type *Ty) const

Returns the offset in bytes between successive objects of the specified type, including alignment pad...

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

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

bool isInBounds() const

Determine whether the GEP has the inbounds flag.

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

static Type * getIndexedType(Type *Ty, ArrayRef< Value * > IdxList)

Returns the result type of a getelementptr with the given source element type and indexes.

Type * getSourceElementType() const

AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")

Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")

LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)

Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")

Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")

ConstantInt * getInt32(uint32_t C)

Get a constant 32-bit value.

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

LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)

Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...

Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")

void SetInsertPoint(BasicBlock *TheBB)

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

StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)

void handleUnreachableFrom(Instruction *I, SmallVectorImpl< BasicBlock * > &Worklist)

Instruction * visitLoadInst(LoadInst &LI)

void handlePotentiallyDeadBlocks(SmallVectorImpl< BasicBlock * > &Worklist)

Instruction * eraseInstFromFunction(Instruction &I) override

Combiner aware instruction erasure.

Instruction * visitStoreInst(StoreInst &SI)

bool mergeStoreIntoSuccessor(StoreInst &SI)

Try to transform: if () { *P = v1; } else { *P = v2 } or: *P = v1; if () { *P = v2; } into a phi node...

void CreateNonTerminatorUnreachable(Instruction *InsertAt)

Create and insert the idiom we use to indicate a block is unreachable without having to rewrite the C...

bool removeInstructionsBeforeUnreachable(Instruction &I)

LoadInst * combineLoadToNewType(LoadInst &LI, Type *NewTy, const Twine &Suffix="")

Helper to combine a load to a new type.

Instruction * visitAllocSite(Instruction &FI)

Instruction * visitAllocaInst(AllocaInst &AI)

const DataLayout & getDataLayout() const

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.

uint64_t MaxArraySizeForCombine

Maximum size of array considered when transforming.

InstructionWorklist & Worklist

A worklist of the instructions that need to be simplified.

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

void push(Instruction *I)

Push the instruction onto the worklist stack.

Instruction * clone() const

Create a copy of 'this' instruction that is identical in all ways except the following:

void mergeDIAssignID(ArrayRef< const Instruction * > SourceInstructions)

Merge the DIAssignID metadata from this instruction and those attached to instructions in SourceInstr...

const DebugLoc & getDebugLoc() const

Return the debug location for this node as a DebugLoc.

void setAAMetadata(const AAMDNodes &N)

Sets the AA metadata on this instruction from the AAMDNodes structure.

bool isAtomic() const LLVM_READONLY

Return true if this instruction has an AtomicOrdering of unordered or higher.

const Function * getFunction() const

Return the function this instruction belongs to.

BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY

Return the specified successor. This instruction must be a terminator.

void setMetadata(unsigned KindID, MDNode *Node)

Set the metadata of the specified kind to the specified node.

AAMDNodes getAAMetadata() const

Returns the AA metadata for this instruction.

void setDebugLoc(DebugLoc Loc)

Set the debug location information for this instruction.

void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())

Copy metadata from SrcInst to this instruction.

void moveBefore(Instruction *MovePos)

Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...

An instruction for reading from memory.

unsigned getPointerAddressSpace() const

Returns the address space of the pointer operand.

void setAlignment(Align Align)

Value * getPointerOperand()

bool isVolatile() const

Return true if this is a load from a volatile memory location.

void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)

Sets the ordering constraint and the synchronization scope ID of this load instruction.

AtomicOrdering getOrdering() const

Returns the ordering constraint of this load instruction.

SyncScope::ID getSyncScopeID() const

Returns the synchronization scope ID of this load instruction.

Align getAlign() const

Return the alignment of the access that is being performed.

This class implements a map that also provides access to all stored values in a deterministic order.

This class wraps the llvm.memcpy/memmove intrinsics.

void addIncoming(Value *V, BasicBlock *BB)

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

static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...

PointerIntPair - This class implements a pair of a pointer and small integer.

static PoisonValue * get(Type *T)

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

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)

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

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

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

reference emplace_back(ArgTypes &&... Args)

void push_back(const T &Elt)

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

An instruction for storing to memory.

Value * getValueOperand()

void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)

Sets the ordering constraint and the synchronization scope ID of this store instruction.

StringRef - Represent a constant reference to a string, i.e.

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

static constexpr TypeSize getZero()

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

unsigned getPointerAddressSpace() const

Get the address space of this pointer or pointer vector type.

bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const

Return true if it makes sense to take the size of this type.

bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const

Return true if this is a type whose size is a known multiple of vscale.

bool isFloatingPointTy() const

Return true if this is one of the floating-point types.

bool isPtrOrPtrVectorTy() const

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

bool isX86_AMXTy() const

Return true if this is X86 AMX.

bool isIntOrPtrTy() const

Return true if this is an integer type or a pointer type.

static IntegerType * getInt32Ty(LLVMContext &C)

static IntegerType * getInt64Ty(LLVMContext &C)

bool isIntegerTy() const

True if this is an instance of IntegerType.

void setOperand(unsigned i, Value *Val)

Value * getOperand(unsigned i) const

unsigned getNumOperands() const

LLVM Value Representation.

Type * getType() const

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

void replaceAllUsesWith(Value *V)

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

iterator_range< use_iterator > uses()

StringRef getName() const

Return a constant reference to the value's name.

constexpr ScalarTy getFixedValue() const

constexpr bool isScalable() const

Returns whether the quantity is scaled by a runtime quantity (vscale).

constexpr ScalarTy getKnownMinValue() const

Returns the minimum value this quantity can represent.

const ParentTy * getParent() const

self_iterator getIterator()

#define llvm_unreachable(msg)

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

@ C

The default llvm calling convention, compatible with C.

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

auto m_Undef()

Match an arbitrary undef constant.

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

bool isDereferenceableAndAlignedPointer(const Value *V, Type *Ty, Align Alignment, const DataLayout &DL, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr)

Returns true if V is always a dereferenceable pointer with alignment greater or equal than requested.

void copyMetadataForLoad(LoadInst &Dest, const LoadInst &Source)

Copy the metadata from the source instruction to the destination (the replacement for the source inst...

bool set_is_subset(const S1Ty &S1, const S2Ty &S2)

set_is_subset(A, B) - Return true iff A in B

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

Value * FindAvailableLoadedValue(LoadInst *Load, BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan=DefMaxInstsToScan, BatchAAResults *AA=nullptr, bool *IsLoadCSE=nullptr, unsigned *NumScanedInst=nullptr)

Scan backwards to see if we have the value of the given load available locally within a small number ...

bool any_of(R &&range, UnaryPredicate P)

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

Align getOrEnforceKnownAlignment(Value *V, MaybeAlign PrefAlign, const DataLayout &DL, const Instruction *CxtI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr)

Try to ensure that the alignment of V is at least PrefAlign bytes.

bool isModSet(const ModRefInfo MRI)

bool NullPointerIsDefined(const Function *F, unsigned AS=0)

Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...

bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const DataLayout &DL, Instruction *ScanFrom, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr)

Return true if we know that executing a load from this value cannot trap.

raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

bool replaceAllDbgUsesWith(Instruction &From, Value &To, Instruction &DomPoint, DominatorTree &DT)

Point debug users of From to To or salvage them.

Value * simplifyLoadInst(LoadInst *LI, Value *PtrOp, const SimplifyQuery &Q)

Given a load instruction and its pointer operand, fold the result or return null.

void combineMetadataForCSE(Instruction *K, const Instruction *J, bool DoesKMove)

Combine the metadata of two instructions so that K can replace J.

void replace(R &&Range, const T &OldValue, const T &NewValue)

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

auto pred_begin(const MachineBasicBlock *BB)

Align commonAlignment(Align A, uint64_t Offset)

Returns the alignment that satisfies both alignments.

A collection of metadata nodes that might be associated with a memory access used by the alias-analys...

AAMDNodes merge(const AAMDNodes &Other) const

Given two sets of AAMDNodes applying to potentially different locations, determine the best AAMDNodes...

This struct is a compact representation of a valid (non-zero power of two) alignment.

bool isNonNegative() const

Returns true if this value is known to be non-negative.

SimplifyQuery getWithInstruction(const Instruction *I) const