|
21 | 21 | #include "llvm/IR/IntrinsicInst.h"
|
22 | 22 | #include "llvm/IR/PatternMatch.h"
|
23 | 23 | #include "llvm/Target/TargetLibraryInfo.h"
|
| 24 | + |
24 | 25 | using namespace llvm;
|
25 | 26 | using namespace PatternMatch;
|
26 | 27 |
|
@@ -2429,6 +2430,128 @@ static bool swapMayExposeCSEOpportunities(const Value * Op0,
|
2429 | 2430 | return GlobalSwapBenefits > 0;
|
2430 | 2431 | }
|
2431 | 2432 |
|
| 2433 | +/// \brief Check that one use is in the same block as the definition and all |
| 2434 | +/// other uses are in blocks dominated by a given block |
| 2435 | +/// |
| 2436 | +/// \param DI Definition |
| 2437 | +/// \param UI Use |
| 2438 | +/// \param DB Block that must dominate all uses of \p DI outside |
| 2439 | +/// the parent block |
| 2440 | +/// \return true when \p UI is the only use of \p DI in the parent block |
| 2441 | +/// and all other uses of \p DI are in blocks dominated by \p DB. |
| 2442 | +/// |
| 2443 | +bool InstCombiner::dominatesAllUses(const Instruction *DI, |
| 2444 | + const Instruction *UI, |
| 2445 | + const BasicBlock *DB) const { |
| 2446 | + assert(DI && UI && "Instruction not defined\n"); |
| 2447 | + if (DI->getParent() != UI->getParent()) |
| 2448 | + return false; |
| 2449 | + // DominatorTree available? |
| 2450 | + if (!DT) |
| 2451 | + return false; |
| 2452 | + for (const User *U : DI->users()) { |
| 2453 | + auto *Usr = cast<Instruction>(U); |
| 2454 | + if (Usr != UI && !DT->dominates(DB, Usr->getParent())) |
| 2455 | + return false; |
| 2456 | + } |
| 2457 | + return true; |
| 2458 | +} |
| 2459 | + |
| 2460 | +/// |
| 2461 | +/// true when the instruction sequence within a block is select-cmp-br. |
| 2462 | +/// |
| 2463 | +static bool isChainSelectCmpBranch(const SelectInst *SI) { |
| 2464 | + const BasicBlock *BB = SI->getParent(); |
| 2465 | + if (!BB) |
| 2466 | + return false; |
| 2467 | + auto *BI = dyn_cast_or_null<BranchInst>(BB->getTerminator()); |
| 2468 | + if (!BI || BI->getNumSuccessors() != 2) |
| 2469 | + return false; |
| 2470 | + auto *IC = dyn_cast<ICmpInst>(BI->getCondition()); |
| 2471 | + if (!IC || (IC->getOperand(0) != SI && IC->getOperand(1) != SI)) |
| 2472 | + return false; |
| 2473 | + return true; |
| 2474 | +} |
| 2475 | + |
| 2476 | +/// |
| 2477 | +/// \brief True when a select result is replaced by one of its operands |
| 2478 | +/// in select-icmp sequence. This will eventually result in the elimination |
| 2479 | +/// of the select. |
| 2480 | +/// |
| 2481 | +/// \param SI Select instruction |
| 2482 | +/// \param Icmp Compare instruction |
| 2483 | +/// \param CI1 'true' when first select operand is equal to RHSC of Icmp |
| 2484 | +/// \param CI2 'true' when second select operand is equal to RHSC of Icmp |
| 2485 | +/// |
| 2486 | +/// Notes: |
| 2487 | +/// - The replacement is global and requires dominator information |
| 2488 | +/// - The caller is responsible for the actual replacement |
| 2489 | +/// |
| 2490 | +/// Example: |
| 2491 | +/// |
| 2492 | +/// entry: |
| 2493 | +/// %4 = select i1 %3, %C* %0, %C* null |
| 2494 | +/// %5 = icmp eq %C* %4, null |
| 2495 | +/// br i1 %5, label %9, label %7 |
| 2496 | +/// ... |
| 2497 | +/// ; <label>:7 ; preds = %entry |
| 2498 | +/// %8 = getelementptr inbounds %C* %4, i64 0, i32 0 |
| 2499 | +/// ... |
| 2500 | +/// |
| 2501 | +/// can be transformed to |
| 2502 | +/// |
| 2503 | +/// %5 = icmp eq %C* %0, null |
| 2504 | +/// %6 = select i1 %3, i1 %5, i1 true |
| 2505 | +/// br i1 %6, label %9, label %7 |
| 2506 | +/// ... |
| 2507 | +/// ; <label>:7 ; preds = %entry |
| 2508 | +/// %8 = getelementptr inbounds %C* %0, i64 0, i32 0 // replace by %0! |
| 2509 | +/// |
| 2510 | +/// Similar when the first operand of the select is a constant or/and |
| 2511 | +/// the compare is for not equal rather than equal. |
| 2512 | +/// |
| 2513 | +/// FIXME: Currently the function considers equal compares only. It should be |
| 2514 | +/// possbile to extend it to not equal compares also. |
| 2515 | +/// |
| 2516 | +bool InstCombiner::replacedSelectWithOperand(SelectInst *SI, |
| 2517 | + const ICmpInst *Icmp, |
| 2518 | + const ConstantInt *CI1, |
| 2519 | + const ConstantInt *CI2) { |
| 2520 | + if (isChainSelectCmpBranch(SI) && Icmp->isEquality()) { |
| 2521 | + // Code sequence is select - icmp.[eq|ne] - br |
| 2522 | + unsigned ReplaceWithOpd = 0; |
| 2523 | + if (CI1 && !CI1->isZero()) |
| 2524 | + // The first constant operand of the select and the RHS of |
| 2525 | + // the compare match, so try to substitute |
| 2526 | + // the select results with its second operand |
| 2527 | + // Example: |
| 2528 | + // %4 = select i1 %3, %C* null, %C* %0 |
| 2529 | + // %5 = icmp eq %C* %4, null |
| 2530 | + // ==> could replace select with second operand |
| 2531 | + ReplaceWithOpd = 2; |
| 2532 | + else if (CI2 && !CI2->isZero()) |
| 2533 | + // Similar when the second operand of the select is a constant |
| 2534 | + // Example: |
| 2535 | + // %4 = select i1 %3, %C* %0, %C* null |
| 2536 | + // %5 = icmp eq %C* %4, null |
| 2537 | + // ==> could replace select with first operand |
| 2538 | + ReplaceWithOpd = 1; |
| 2539 | + if (ReplaceWithOpd) { |
| 2540 | + // Replace select with operand on else path for EQ compares. |
| 2541 | + // Replace select with operand on then path for NE compares. |
| 2542 | + BasicBlock *Succ = |
| 2543 | + Icmp->getPredicate() == ICmpInst::ICMP_EQ |
| 2544 | + ? SI->getParent()->getTerminator()->getSuccessor(1) |
| 2545 | + : SI->getParent()->getTerminator()->getSuccessor(0); |
| 2546 | + if (InstCombiner::dominatesAllUses(SI, Icmp, Succ)) { |
| 2547 | + SI->replaceAllUsesWith(SI->getOperand(ReplaceWithOpd)); |
| 2548 | + return true; |
| 2549 | + } |
| 2550 | + } |
| 2551 | + } |
| 2552 | + return false; |
| 2553 | +} |
| 2554 | + |
2432 | 2555 | Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
2433 | 2556 | bool Changed = false;
|
2434 | 2557 | Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
@@ -2885,8 +3008,21 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
2885 | 3008 | // fold to a constant (in which case the icmp is replaced with a select
|
2886 | 3009 | // which will usually simplify) or this is the only user of the
|
2887 | 3010 | // select (in which case we are trading a select+icmp for a simpler
|
2888 |
| - // select+icmp). |
2889 |
| - if ((Op1 && Op2) || (LHSI->hasOneUse() && (Op1 || Op2))) { |
| 3011 | + // select+icmp) or all uses of the select can be replaced based on |
| 3012 | + // dominance information ("Global cases"). |
| 3013 | + bool Transform = false; |
| 3014 | + if (Op1 && Op2) |
| 3015 | + Transform = true; |
| 3016 | + else if (Op1 || Op2) { |
| 3017 | + if (LHSI->hasOneUse()) |
| 3018 | + Transform = true; |
| 3019 | + else |
| 3020 | + // Global cases |
| 3021 | + Transform = replacedSelectWithOperand( |
| 3022 | + cast<SelectInst>(LHSI), &I, dyn_cast_or_null<ConstantInt>(Op1), |
| 3023 | + dyn_cast_or_null<ConstantInt>(Op2)); |
| 3024 | + } |
| 3025 | + if (Transform) { |
2890 | 3026 | if (!Op1)
|
2891 | 3027 | Op1 = Builder->CreateICmp(I.getPredicate(), LHSI->getOperand(1),
|
2892 | 3028 | RHSC, I.getName());
|
|
0 commit comments