TruncInstCombine.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. //===- TruncInstCombine.cpp -----------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // TruncInstCombine - looks for expression graphs post-dominated by TruncInst
  10. // and for each eligible graph, it will create a reduced bit-width expression,
  11. // replace the old expression with this new one and remove the old expression.
  12. // Eligible expression graph is such that:
  13. // 1. Contains only supported instructions.
  14. // 2. Supported leaves: ZExtInst, SExtInst, TruncInst and Constant value.
  15. // 3. Can be evaluated into type with reduced legal bit-width.
  16. // 4. All instructions in the graph must not have users outside the graph.
  17. // The only exception is for {ZExt, SExt}Inst with operand type equal to
  18. // the new reduced type evaluated in (3).
  19. //
  20. // The motivation for this optimization is that evaluating and expression using
  21. // smaller bit-width is preferable, especially for vectorization where we can
  22. // fit more values in one vectorized instruction. In addition, this optimization
  23. // may decrease the number of cast instructions, but will not increase it.
  24. //
  25. //===----------------------------------------------------------------------===//
  26. #include "AggressiveInstCombineInternal.h"
  27. #include "llvm/ADT/STLExtras.h"
  28. #include "llvm/ADT/Statistic.h"
  29. #include "llvm/Analysis/ConstantFolding.h"
  30. #include "llvm/IR/DataLayout.h"
  31. #include "llvm/IR/Dominators.h"
  32. #include "llvm/IR/IRBuilder.h"
  33. #include "llvm/IR/Instruction.h"
  34. #include "llvm/Support/KnownBits.h"
  35. using namespace llvm;
  36. #define DEBUG_TYPE "aggressive-instcombine"
  37. STATISTIC(NumExprsReduced, "Number of truncations eliminated by reducing bit "
  38. "width of expression graph");
  39. STATISTIC(NumInstrsReduced,
  40. "Number of instructions whose bit width was reduced");
  41. /// Given an instruction and a container, it fills all the relevant operands of
  42. /// that instruction, with respect to the Trunc expression graph optimizaton.
  43. static void getRelevantOperands(Instruction *I, SmallVectorImpl<Value *> &Ops) {
  44. unsigned Opc = I->getOpcode();
  45. switch (Opc) {
  46. case Instruction::Trunc:
  47. case Instruction::ZExt:
  48. case Instruction::SExt:
  49. // These CastInst are considered leaves of the evaluated expression, thus,
  50. // their operands are not relevent.
  51. break;
  52. case Instruction::Add:
  53. case Instruction::Sub:
  54. case Instruction::Mul:
  55. case Instruction::And:
  56. case Instruction::Or:
  57. case Instruction::Xor:
  58. case Instruction::Shl:
  59. case Instruction::LShr:
  60. case Instruction::AShr:
  61. case Instruction::UDiv:
  62. case Instruction::URem:
  63. case Instruction::InsertElement:
  64. Ops.push_back(I->getOperand(0));
  65. Ops.push_back(I->getOperand(1));
  66. break;
  67. case Instruction::ExtractElement:
  68. Ops.push_back(I->getOperand(0));
  69. break;
  70. case Instruction::Select:
  71. Ops.push_back(I->getOperand(1));
  72. Ops.push_back(I->getOperand(2));
  73. break;
  74. case Instruction::PHI:
  75. for (Value *V : cast<PHINode>(I)->incoming_values())
  76. Ops.push_back(V);
  77. break;
  78. default:
  79. llvm_unreachable("Unreachable!");
  80. }
  81. }
  82. bool TruncInstCombine::buildTruncExpressionGraph() {
  83. SmallVector<Value *, 8> Worklist;
  84. SmallVector<Instruction *, 8> Stack;
  85. // Clear old instructions info.
  86. InstInfoMap.clear();
  87. Worklist.push_back(CurrentTruncInst->getOperand(0));
  88. while (!Worklist.empty()) {
  89. Value *Curr = Worklist.back();
  90. if (isa<Constant>(Curr)) {
  91. Worklist.pop_back();
  92. continue;
  93. }
  94. auto *I = dyn_cast<Instruction>(Curr);
  95. if (!I)
  96. return false;
  97. if (!Stack.empty() && Stack.back() == I) {
  98. // Already handled all instruction operands, can remove it from both the
  99. // Worklist and the Stack, and add it to the instruction info map.
  100. Worklist.pop_back();
  101. Stack.pop_back();
  102. // Insert I to the Info map.
  103. InstInfoMap.insert(std::make_pair(I, Info()));
  104. continue;
  105. }
  106. if (InstInfoMap.count(I)) {
  107. Worklist.pop_back();
  108. continue;
  109. }
  110. // Add the instruction to the stack before start handling its operands.
  111. Stack.push_back(I);
  112. unsigned Opc = I->getOpcode();
  113. switch (Opc) {
  114. case Instruction::Trunc:
  115. case Instruction::ZExt:
  116. case Instruction::SExt:
  117. // trunc(trunc(x)) -> trunc(x)
  118. // trunc(ext(x)) -> ext(x) if the source type is smaller than the new dest
  119. // trunc(ext(x)) -> trunc(x) if the source type is larger than the new
  120. // dest
  121. break;
  122. case Instruction::Add:
  123. case Instruction::Sub:
  124. case Instruction::Mul:
  125. case Instruction::And:
  126. case Instruction::Or:
  127. case Instruction::Xor:
  128. case Instruction::Shl:
  129. case Instruction::LShr:
  130. case Instruction::AShr:
  131. case Instruction::UDiv:
  132. case Instruction::URem:
  133. case Instruction::InsertElement:
  134. case Instruction::ExtractElement:
  135. case Instruction::Select: {
  136. SmallVector<Value *, 2> Operands;
  137. getRelevantOperands(I, Operands);
  138. append_range(Worklist, Operands);
  139. break;
  140. }
  141. case Instruction::PHI: {
  142. SmallVector<Value *, 2> Operands;
  143. getRelevantOperands(I, Operands);
  144. // Add only operands not in Stack to prevent cycle
  145. for (auto *Op : Operands)
  146. if (!llvm::is_contained(Stack, Op))
  147. Worklist.push_back(Op);
  148. break;
  149. }
  150. default:
  151. // TODO: Can handle more cases here:
  152. // 1. shufflevector
  153. // 2. sdiv, srem
  154. // ...
  155. return false;
  156. }
  157. }
  158. return true;
  159. }
  160. unsigned TruncInstCombine::getMinBitWidth() {
  161. SmallVector<Value *, 8> Worklist;
  162. SmallVector<Instruction *, 8> Stack;
  163. Value *Src = CurrentTruncInst->getOperand(0);
  164. Type *DstTy = CurrentTruncInst->getType();
  165. unsigned TruncBitWidth = DstTy->getScalarSizeInBits();
  166. unsigned OrigBitWidth =
  167. CurrentTruncInst->getOperand(0)->getType()->getScalarSizeInBits();
  168. if (isa<Constant>(Src))
  169. return TruncBitWidth;
  170. Worklist.push_back(Src);
  171. InstInfoMap[cast<Instruction>(Src)].ValidBitWidth = TruncBitWidth;
  172. while (!Worklist.empty()) {
  173. Value *Curr = Worklist.back();
  174. if (isa<Constant>(Curr)) {
  175. Worklist.pop_back();
  176. continue;
  177. }
  178. // Otherwise, it must be an instruction.
  179. auto *I = cast<Instruction>(Curr);
  180. auto &Info = InstInfoMap[I];
  181. SmallVector<Value *, 2> Operands;
  182. getRelevantOperands(I, Operands);
  183. if (!Stack.empty() && Stack.back() == I) {
  184. // Already handled all instruction operands, can remove it from both, the
  185. // Worklist and the Stack, and update MinBitWidth.
  186. Worklist.pop_back();
  187. Stack.pop_back();
  188. for (auto *Operand : Operands)
  189. if (auto *IOp = dyn_cast<Instruction>(Operand))
  190. Info.MinBitWidth =
  191. std::max(Info.MinBitWidth, InstInfoMap[IOp].MinBitWidth);
  192. continue;
  193. }
  194. // Add the instruction to the stack before start handling its operands.
  195. Stack.push_back(I);
  196. unsigned ValidBitWidth = Info.ValidBitWidth;
  197. // Update minimum bit-width before handling its operands. This is required
  198. // when the instruction is part of a loop.
  199. Info.MinBitWidth = std::max(Info.MinBitWidth, Info.ValidBitWidth);
  200. for (auto *Operand : Operands)
  201. if (auto *IOp = dyn_cast<Instruction>(Operand)) {
  202. // If we already calculated the minimum bit-width for this valid
  203. // bit-width, or for a smaller valid bit-width, then just keep the
  204. // answer we already calculated.
  205. unsigned IOpBitwidth = InstInfoMap.lookup(IOp).ValidBitWidth;
  206. if (IOpBitwidth >= ValidBitWidth)
  207. continue;
  208. InstInfoMap[IOp].ValidBitWidth = ValidBitWidth;
  209. Worklist.push_back(IOp);
  210. }
  211. }
  212. unsigned MinBitWidth = InstInfoMap.lookup(cast<Instruction>(Src)).MinBitWidth;
  213. assert(MinBitWidth >= TruncBitWidth);
  214. if (MinBitWidth > TruncBitWidth) {
  215. // In this case reducing expression with vector type might generate a new
  216. // vector type, which is not preferable as it might result in generating
  217. // sub-optimal code.
  218. if (DstTy->isVectorTy())
  219. return OrigBitWidth;
  220. // Use the smallest integer type in the range [MinBitWidth, OrigBitWidth).
  221. Type *Ty = DL.getSmallestLegalIntType(DstTy->getContext(), MinBitWidth);
  222. // Update minimum bit-width with the new destination type bit-width if
  223. // succeeded to find such, otherwise, with original bit-width.
  224. MinBitWidth = Ty ? Ty->getScalarSizeInBits() : OrigBitWidth;
  225. } else { // MinBitWidth == TruncBitWidth
  226. // In this case the expression can be evaluated with the trunc instruction
  227. // destination type, and trunc instruction can be omitted. However, we
  228. // should not perform the evaluation if the original type is a legal scalar
  229. // type and the target type is illegal.
  230. bool FromLegal = MinBitWidth == 1 || DL.isLegalInteger(OrigBitWidth);
  231. bool ToLegal = MinBitWidth == 1 || DL.isLegalInteger(MinBitWidth);
  232. if (!DstTy->isVectorTy() && FromLegal && !ToLegal)
  233. return OrigBitWidth;
  234. }
  235. return MinBitWidth;
  236. }
  237. Type *TruncInstCombine::getBestTruncatedType() {
  238. if (!buildTruncExpressionGraph())
  239. return nullptr;
  240. // We don't want to duplicate instructions, which isn't profitable. Thus, we
  241. // can't shrink something that has multiple users, unless all users are
  242. // post-dominated by the trunc instruction, i.e., were visited during the
  243. // expression evaluation.
  244. unsigned DesiredBitWidth = 0;
  245. for (auto Itr : InstInfoMap) {
  246. Instruction *I = Itr.first;
  247. if (I->hasOneUse())
  248. continue;
  249. bool IsExtInst = (isa<ZExtInst>(I) || isa<SExtInst>(I));
  250. for (auto *U : I->users())
  251. if (auto *UI = dyn_cast<Instruction>(U))
  252. if (UI != CurrentTruncInst && !InstInfoMap.count(UI)) {
  253. if (!IsExtInst)
  254. return nullptr;
  255. // If this is an extension from the dest type, we can eliminate it,
  256. // even if it has multiple users. Thus, update the DesiredBitWidth and
  257. // validate all extension instructions agrees on same DesiredBitWidth.
  258. unsigned ExtInstBitWidth =
  259. I->getOperand(0)->getType()->getScalarSizeInBits();
  260. if (DesiredBitWidth && DesiredBitWidth != ExtInstBitWidth)
  261. return nullptr;
  262. DesiredBitWidth = ExtInstBitWidth;
  263. }
  264. }
  265. unsigned OrigBitWidth =
  266. CurrentTruncInst->getOperand(0)->getType()->getScalarSizeInBits();
  267. // Initialize MinBitWidth for shift instructions with the minimum number
  268. // that is greater than shift amount (i.e. shift amount + 1).
  269. // For `lshr` adjust MinBitWidth so that all potentially truncated
  270. // bits of the value-to-be-shifted are zeros.
  271. // For `ashr` adjust MinBitWidth so that all potentially truncated
  272. // bits of the value-to-be-shifted are sign bits (all zeros or ones)
  273. // and even one (first) untruncated bit is sign bit.
  274. // Exit early if MinBitWidth is not less than original bitwidth.
  275. for (auto &Itr : InstInfoMap) {
  276. Instruction *I = Itr.first;
  277. if (I->isShift()) {
  278. KnownBits KnownRHS = computeKnownBits(I->getOperand(1));
  279. unsigned MinBitWidth = KnownRHS.getMaxValue()
  280. .uadd_sat(APInt(OrigBitWidth, 1))
  281. .getLimitedValue(OrigBitWidth);
  282. if (MinBitWidth == OrigBitWidth)
  283. return nullptr;
  284. if (I->getOpcode() == Instruction::LShr) {
  285. KnownBits KnownLHS = computeKnownBits(I->getOperand(0));
  286. MinBitWidth =
  287. std::max(MinBitWidth, KnownLHS.getMaxValue().getActiveBits());
  288. }
  289. if (I->getOpcode() == Instruction::AShr) {
  290. unsigned NumSignBits = ComputeNumSignBits(I->getOperand(0));
  291. MinBitWidth = std::max(MinBitWidth, OrigBitWidth - NumSignBits + 1);
  292. }
  293. if (MinBitWidth >= OrigBitWidth)
  294. return nullptr;
  295. Itr.second.MinBitWidth = MinBitWidth;
  296. }
  297. if (I->getOpcode() == Instruction::UDiv ||
  298. I->getOpcode() == Instruction::URem) {
  299. unsigned MinBitWidth = 0;
  300. for (const auto &Op : I->operands()) {
  301. KnownBits Known = computeKnownBits(Op);
  302. MinBitWidth =
  303. std::max(Known.getMaxValue().getActiveBits(), MinBitWidth);
  304. if (MinBitWidth >= OrigBitWidth)
  305. return nullptr;
  306. }
  307. Itr.second.MinBitWidth = MinBitWidth;
  308. }
  309. }
  310. // Calculate minimum allowed bit-width allowed for shrinking the currently
  311. // visited truncate's operand.
  312. unsigned MinBitWidth = getMinBitWidth();
  313. // Check that we can shrink to smaller bit-width than original one and that
  314. // it is similar to the DesiredBitWidth is such exists.
  315. if (MinBitWidth >= OrigBitWidth ||
  316. (DesiredBitWidth && DesiredBitWidth != MinBitWidth))
  317. return nullptr;
  318. return IntegerType::get(CurrentTruncInst->getContext(), MinBitWidth);
  319. }
  320. /// Given a reduced scalar type \p Ty and a \p V value, return a reduced type
  321. /// for \p V, according to its type, if it vector type, return the vector
  322. /// version of \p Ty, otherwise return \p Ty.
  323. static Type *getReducedType(Value *V, Type *Ty) {
  324. assert(Ty && !Ty->isVectorTy() && "Expect Scalar Type");
  325. if (auto *VTy = dyn_cast<VectorType>(V->getType()))
  326. return VectorType::get(Ty, VTy->getElementCount());
  327. return Ty;
  328. }
  329. Value *TruncInstCombine::getReducedOperand(Value *V, Type *SclTy) {
  330. Type *Ty = getReducedType(V, SclTy);
  331. if (auto *C = dyn_cast<Constant>(V)) {
  332. C = ConstantExpr::getIntegerCast(C, Ty, false);
  333. // If we got a constantexpr back, try to simplify it with DL info.
  334. return ConstantFoldConstant(C, DL, &TLI);
  335. }
  336. auto *I = cast<Instruction>(V);
  337. Info Entry = InstInfoMap.lookup(I);
  338. assert(Entry.NewValue);
  339. return Entry.NewValue;
  340. }
  341. void TruncInstCombine::ReduceExpressionGraph(Type *SclTy) {
  342. NumInstrsReduced += InstInfoMap.size();
  343. // Pairs of old and new phi-nodes
  344. SmallVector<std::pair<PHINode *, PHINode *>, 2> OldNewPHINodes;
  345. for (auto &Itr : InstInfoMap) { // Forward
  346. Instruction *I = Itr.first;
  347. TruncInstCombine::Info &NodeInfo = Itr.second;
  348. assert(!NodeInfo.NewValue && "Instruction has been evaluated");
  349. IRBuilder<> Builder(I);
  350. Value *Res = nullptr;
  351. unsigned Opc = I->getOpcode();
  352. switch (Opc) {
  353. case Instruction::Trunc:
  354. case Instruction::ZExt:
  355. case Instruction::SExt: {
  356. Type *Ty = getReducedType(I, SclTy);
  357. // If the source type of the cast is the type we're trying for then we can
  358. // just return the source. There's no need to insert it because it is not
  359. // new.
  360. if (I->getOperand(0)->getType() == Ty) {
  361. assert(!isa<TruncInst>(I) && "Cannot reach here with TruncInst");
  362. NodeInfo.NewValue = I->getOperand(0);
  363. continue;
  364. }
  365. // Otherwise, must be the same type of cast, so just reinsert a new one.
  366. // This also handles the case of zext(trunc(x)) -> zext(x).
  367. Res = Builder.CreateIntCast(I->getOperand(0), Ty,
  368. Opc == Instruction::SExt);
  369. // Update Worklist entries with new value if needed.
  370. // There are three possible changes to the Worklist:
  371. // 1. Update Old-TruncInst -> New-TruncInst.
  372. // 2. Remove Old-TruncInst (if New node is not TruncInst).
  373. // 3. Add New-TruncInst (if Old node was not TruncInst).
  374. auto *Entry = find(Worklist, I);
  375. if (Entry != Worklist.end()) {
  376. if (auto *NewCI = dyn_cast<TruncInst>(Res))
  377. *Entry = NewCI;
  378. else
  379. Worklist.erase(Entry);
  380. } else if (auto *NewCI = dyn_cast<TruncInst>(Res))
  381. Worklist.push_back(NewCI);
  382. break;
  383. }
  384. case Instruction::Add:
  385. case Instruction::Sub:
  386. case Instruction::Mul:
  387. case Instruction::And:
  388. case Instruction::Or:
  389. case Instruction::Xor:
  390. case Instruction::Shl:
  391. case Instruction::LShr:
  392. case Instruction::AShr:
  393. case Instruction::UDiv:
  394. case Instruction::URem: {
  395. Value *LHS = getReducedOperand(I->getOperand(0), SclTy);
  396. Value *RHS = getReducedOperand(I->getOperand(1), SclTy);
  397. Res = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS);
  398. // Preserve `exact` flag since truncation doesn't change exactness
  399. if (auto *PEO = dyn_cast<PossiblyExactOperator>(I))
  400. if (auto *ResI = dyn_cast<Instruction>(Res))
  401. ResI->setIsExact(PEO->isExact());
  402. break;
  403. }
  404. case Instruction::ExtractElement: {
  405. Value *Vec = getReducedOperand(I->getOperand(0), SclTy);
  406. Value *Idx = I->getOperand(1);
  407. Res = Builder.CreateExtractElement(Vec, Idx);
  408. break;
  409. }
  410. case Instruction::InsertElement: {
  411. Value *Vec = getReducedOperand(I->getOperand(0), SclTy);
  412. Value *NewElt = getReducedOperand(I->getOperand(1), SclTy);
  413. Value *Idx = I->getOperand(2);
  414. Res = Builder.CreateInsertElement(Vec, NewElt, Idx);
  415. break;
  416. }
  417. case Instruction::Select: {
  418. Value *Op0 = I->getOperand(0);
  419. Value *LHS = getReducedOperand(I->getOperand(1), SclTy);
  420. Value *RHS = getReducedOperand(I->getOperand(2), SclTy);
  421. Res = Builder.CreateSelect(Op0, LHS, RHS);
  422. break;
  423. }
  424. case Instruction::PHI: {
  425. Res = Builder.CreatePHI(getReducedType(I, SclTy), I->getNumOperands());
  426. OldNewPHINodes.push_back(
  427. std::make_pair(cast<PHINode>(I), cast<PHINode>(Res)));
  428. break;
  429. }
  430. default:
  431. llvm_unreachable("Unhandled instruction");
  432. }
  433. NodeInfo.NewValue = Res;
  434. if (auto *ResI = dyn_cast<Instruction>(Res))
  435. ResI->takeName(I);
  436. }
  437. for (auto &Node : OldNewPHINodes) {
  438. PHINode *OldPN = Node.first;
  439. PHINode *NewPN = Node.second;
  440. for (auto Incoming : zip(OldPN->incoming_values(), OldPN->blocks()))
  441. NewPN->addIncoming(getReducedOperand(std::get<0>(Incoming), SclTy),
  442. std::get<1>(Incoming));
  443. }
  444. Value *Res = getReducedOperand(CurrentTruncInst->getOperand(0), SclTy);
  445. Type *DstTy = CurrentTruncInst->getType();
  446. if (Res->getType() != DstTy) {
  447. IRBuilder<> Builder(CurrentTruncInst);
  448. Res = Builder.CreateIntCast(Res, DstTy, false);
  449. if (auto *ResI = dyn_cast<Instruction>(Res))
  450. ResI->takeName(CurrentTruncInst);
  451. }
  452. CurrentTruncInst->replaceAllUsesWith(Res);
  453. // Erase old expression graph, which was replaced by the reduced expression
  454. // graph.
  455. CurrentTruncInst->eraseFromParent();
  456. // First, erase old phi-nodes and its uses
  457. for (auto &Node : OldNewPHINodes) {
  458. PHINode *OldPN = Node.first;
  459. OldPN->replaceAllUsesWith(PoisonValue::get(OldPN->getType()));
  460. InstInfoMap.erase(OldPN);
  461. OldPN->eraseFromParent();
  462. }
  463. // Now we have expression graph turned into dag.
  464. // We iterate backward, which means we visit the instruction before we
  465. // visit any of its operands, this way, when we get to the operand, we already
  466. // removed the instructions (from the expression dag) that uses it.
  467. for (auto &I : llvm::reverse(InstInfoMap)) {
  468. // We still need to check that the instruction has no users before we erase
  469. // it, because {SExt, ZExt}Inst Instruction might have other users that was
  470. // not reduced, in such case, we need to keep that instruction.
  471. if (I.first->use_empty())
  472. I.first->eraseFromParent();
  473. else
  474. assert((isa<SExtInst>(I.first) || isa<ZExtInst>(I.first)) &&
  475. "Only {SExt, ZExt}Inst might have unreduced users");
  476. }
  477. }
  478. bool TruncInstCombine::run(Function &F) {
  479. bool MadeIRChange = false;
  480. // Collect all TruncInst in the function into the Worklist for evaluating.
  481. for (auto &BB : F) {
  482. // Ignore unreachable basic block.
  483. if (!DT.isReachableFromEntry(&BB))
  484. continue;
  485. for (auto &I : BB)
  486. if (auto *CI = dyn_cast<TruncInst>(&I))
  487. Worklist.push_back(CI);
  488. }
  489. // Process all TruncInst in the Worklist, for each instruction:
  490. // 1. Check if it dominates an eligible expression graph to be reduced.
  491. // 2. Create a reduced expression graph and replace the old one with it.
  492. while (!Worklist.empty()) {
  493. CurrentTruncInst = Worklist.pop_back_val();
  494. if (Type *NewDstSclTy = getBestTruncatedType()) {
  495. LLVM_DEBUG(
  496. dbgs() << "ICE: TruncInstCombine reducing type of expression graph "
  497. "dominated by: "
  498. << CurrentTruncInst << '\n');
  499. ReduceExpressionGraph(NewDstSclTy);
  500. ++NumExprsReduced;
  501. MadeIRChange = true;
  502. }
  503. }
  504. return MadeIRChange;
  505. }