@@ -2084,13 +2084,6 @@ bool GVNPass::processNonLocalLoad(LoadInst *Load) {
2084
2084
return Changed;
2085
2085
}
2086
2086
2087
- static bool hasUsersIn (Value *V, BasicBlock *BB) {
2088
- return any_of (V->users (), [BB](User *U) {
2089
- auto *I = dyn_cast<Instruction>(U);
2090
- return I && I->getParent () == BB;
2091
- });
2092
- }
2093
-
2094
2087
bool GVNPass::processAssumeIntrinsic (AssumeInst *IntrinsicI) {
2095
2088
Value *V = IntrinsicI->getArgOperand (0 );
2096
2089
@@ -2149,85 +2142,7 @@ bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
2149
2142
}
2150
2143
2151
2144
Constant *True = ConstantInt::getTrue (V->getContext ());
2152
- bool Changed = false ;
2153
-
2154
- for (BasicBlock *Successor : successors (IntrinsicI->getParent ())) {
2155
- BasicBlockEdge Edge (IntrinsicI->getParent (), Successor);
2156
-
2157
- // This property is only true in dominated successors, propagateEquality
2158
- // will check dominance for us.
2159
- Changed |= propagateEquality (V, True, Edge, false );
2160
- }
2161
-
2162
- // We can replace assume value with true, which covers cases like this:
2163
- // call void @llvm.assume(i1 %cmp)
2164
- // br i1 %cmp, label %bb1, label %bb2 ; will change %cmp to true
2165
- ReplaceOperandsWithMap[V] = True;
2166
-
2167
- // Similarly, after assume(!NotV) we know that NotV == false.
2168
- Value *NotV;
2169
- if (match (V, m_Not (m_Value (NotV))))
2170
- ReplaceOperandsWithMap[NotV] = ConstantInt::getFalse (V->getContext ());
2171
-
2172
- // If we find an equality fact, canonicalize all dominated uses in this block
2173
- // to one of the two values. We heuristically choice the "oldest" of the
2174
- // two where age is determined by value number. (Note that propagateEquality
2175
- // above handles the cross block case.)
2176
- //
2177
- // Key case to cover are:
2178
- // 1)
2179
- // %cmp = fcmp oeq float 3.000000e+00, %0 ; const on lhs could happen
2180
- // call void @llvm.assume(i1 %cmp)
2181
- // ret float %0 ; will change it to ret float 3.000000e+00
2182
- // 2)
2183
- // %load = load float, float* %addr
2184
- // %cmp = fcmp oeq float %load, %0
2185
- // call void @llvm.assume(i1 %cmp)
2186
- // ret float %load ; will change it to ret float %0
2187
- if (auto *CmpI = dyn_cast<CmpInst>(V)) {
2188
- if (CmpI->isEquivalence ()) {
2189
- Value *CmpLHS = CmpI->getOperand (0 );
2190
- Value *CmpRHS = CmpI->getOperand (1 );
2191
- // Heuristically pick the better replacement -- the choice of heuristic
2192
- // isn't terribly important here, but the fact we canonicalize on some
2193
- // replacement is for exposing other simplifications.
2194
- // TODO: pull this out as a helper function and reuse w/ existing
2195
- // (slightly different) logic.
2196
- if (isa<Constant>(CmpLHS) && !isa<Constant>(CmpRHS))
2197
- std::swap (CmpLHS, CmpRHS);
2198
- if (!isa<Instruction>(CmpLHS) && isa<Instruction>(CmpRHS))
2199
- std::swap (CmpLHS, CmpRHS);
2200
- if ((isa<Argument>(CmpLHS) && isa<Argument>(CmpRHS)) ||
2201
- (isa<Instruction>(CmpLHS) && isa<Instruction>(CmpRHS))) {
2202
- // Move the 'oldest' value to the right-hand side, using the value
2203
- // number as a proxy for age.
2204
- uint32_t LVN = VN.lookupOrAdd (CmpLHS);
2205
- uint32_t RVN = VN.lookupOrAdd (CmpRHS);
2206
- if (LVN < RVN)
2207
- std::swap (CmpLHS, CmpRHS);
2208
- }
2209
-
2210
- // Handle degenerate case where we either haven't pruned a dead path or a
2211
- // removed a trivial assume yet.
2212
- if (isa<Constant>(CmpLHS) && isa<Constant>(CmpRHS))
2213
- return Changed;
2214
-
2215
- LLVM_DEBUG (dbgs () << " Replacing dominated uses of "
2216
- << *CmpLHS << " with "
2217
- << *CmpRHS << " in block "
2218
- << IntrinsicI->getParent ()->getName () << " \n " );
2219
-
2220
- // Setup the replacement map - this handles uses within the same block.
2221
- if (hasUsersIn (CmpLHS, IntrinsicI->getParent ()))
2222
- ReplaceOperandsWithMap[CmpLHS] = CmpRHS;
2223
-
2224
- // NOTE: The non-block local cases are handled by the call to
2225
- // propagateEquality above; this block is just about handling the block
2226
- // local cases. TODO: There's a bunch of logic in propagateEqualiy which
2227
- // isn't duplicated for the block local case, can we share it somehow?
2228
- }
2229
- }
2230
- return Changed;
2145
+ return propagateEquality (V, True, IntrinsicI);
2231
2146
}
2232
2147
2233
2148
static void patchAndReplaceAllUsesWith (Instruction *I, Value *Repl) {
@@ -2526,39 +2441,28 @@ void GVNPass::assignBlockRPONumber(Function &F) {
2526
2441
InvalidBlockRPONumbers = false ;
2527
2442
}
2528
2443
2529
- bool GVNPass::replaceOperandsForInBlockEquality (Instruction *Instr) const {
2530
- bool Changed = false ;
2531
- for (unsigned OpNum = 0 ; OpNum < Instr->getNumOperands (); ++OpNum) {
2532
- Use &Operand = Instr->getOperandUse (OpNum);
2533
- auto It = ReplaceOperandsWithMap.find (Operand.get ());
2534
- if (It != ReplaceOperandsWithMap.end ()) {
2535
- const DataLayout &DL = Instr->getDataLayout ();
2536
- if (!canReplacePointersInUseIfEqual (Operand, It->second , DL))
2537
- continue ;
2538
-
2539
- LLVM_DEBUG (dbgs () << " GVN replacing: " << *Operand << " with "
2540
- << *It->second << " in instruction " << *Instr << ' \n ' );
2541
- Instr->setOperand (OpNum, It->second );
2542
- Changed = true ;
2543
- }
2544
- }
2545
- return Changed;
2546
- }
2547
-
2548
- // / The given values are known to be equal in every block
2444
+ // / The given values are known to be equal in every use
2549
2445
// / dominated by 'Root'. Exploit this, for example by replacing 'LHS' with
2550
2446
// / 'RHS' everywhere in the scope. Returns whether a change was made.
2551
- // / If DominatesByEdge is false, then it means that we will propagate the RHS
2552
- // / value starting from the end of Root.Start .
2553
- bool GVNPass::propagateEquality (Value *LHS, Value *RHS,
2554
- const BasicBlockEdge &Root ,
2555
- bool DominatesByEdge ) {
2447
+ // / The Root may either be a basic block edge (for conditions) or an
2448
+ // / instruction (for assumes) .
2449
+ bool GVNPass::propagateEquality (
2450
+ Value *LHS, Value *RHS ,
2451
+ const std::variant<BasicBlockEdge, Instruction *> &Root ) {
2556
2452
SmallVector<std::pair<Value*, Value*>, 4 > Worklist;
2557
2453
Worklist.push_back (std::make_pair (LHS, RHS));
2558
2454
bool Changed = false ;
2559
- // For speed, compute a conservative fast approximation to
2560
- // DT->dominates(Root, Root.getEnd());
2561
- const bool RootDominatesEnd = isOnlyReachableViaThisEdge (Root, DT);
2455
+ SmallVector<const BasicBlock *> DominatedBlocks;
2456
+ if (const BasicBlockEdge *Edge = std::get_if<BasicBlockEdge>(&Root)) {
2457
+ // For speed, compute a conservative fast approximation to
2458
+ // DT->dominates(Root, Root.getEnd());
2459
+ if (isOnlyReachableViaThisEdge (*Edge, DT))
2460
+ DominatedBlocks.push_back (Edge->getEnd ());
2461
+ } else {
2462
+ Instruction *I = std::get<Instruction *>(Root);
2463
+ for (const auto *Node : DT->getNode (I->getParent ())->children ())
2464
+ DominatedBlocks.push_back (Node->getBlock ());
2465
+ }
2562
2466
2563
2467
while (!Worklist.empty ()) {
2564
2468
std::pair<Value*, Value*> Item = Worklist.pop_back_val ();
@@ -2606,9 +2510,9 @@ bool GVNPass::propagateEquality(Value *LHS, Value *RHS,
2606
2510
// using the leader table is about compiling faster, not optimizing better).
2607
2511
// The leader table only tracks basic blocks, not edges. Only add to if we
2608
2512
// have the simple case where the edge dominates the end.
2609
- if (RootDominatesEnd && !isa<Instruction>(RHS) &&
2610
- canReplacePointersIfEqual (LHS, RHS, DL) )
2611
- LeaderTable.insert (LVN, RHS, Root. getEnd () );
2513
+ if (!isa<Instruction>(RHS) && canReplacePointersIfEqual (LHS, RHS, DL))
2514
+ for ( const BasicBlock *BB : DominatedBlocks )
2515
+ LeaderTable.insert (LVN, RHS, BB );
2612
2516
2613
2517
// Replace all occurrences of 'LHS' with 'RHS' everywhere in the scope. As
2614
2518
// LHS always has at least one use that is not dominated by Root, this will
@@ -2618,12 +2522,14 @@ bool GVNPass::propagateEquality(Value *LHS, Value *RHS,
2618
2522
auto CanReplacePointersCallBack = [&DL](const Use &U, const Value *To) {
2619
2523
return canReplacePointersInUseIfEqual (U, To, DL);
2620
2524
};
2621
- unsigned NumReplacements =
2622
- DominatesByEdge
2623
- ? replaceDominatedUsesWithIf (LHS, RHS, *DT, Root,
2624
- CanReplacePointersCallBack)
2625
- : replaceDominatedUsesWithIf (LHS, RHS, *DT, Root.getStart (),
2626
- CanReplacePointersCallBack);
2525
+ unsigned NumReplacements;
2526
+ if (const BasicBlockEdge *Edge = std::get_if<BasicBlockEdge>(&Root))
2527
+ NumReplacements = replaceDominatedUsesWithIf (
2528
+ LHS, RHS, *DT, *Edge, CanReplacePointersCallBack);
2529
+ else
2530
+ NumReplacements = replaceDominatedUsesWithIf (
2531
+ LHS, RHS, *DT, std::get<Instruction *>(Root),
2532
+ CanReplacePointersCallBack);
2627
2533
2628
2534
if (NumReplacements > 0 ) {
2629
2535
Changed = true ;
@@ -2682,26 +2588,45 @@ bool GVNPass::propagateEquality(Value *LHS, Value *RHS,
2682
2588
// If the number we were assigned was brand new then there is no point in
2683
2589
// looking for an instruction realizing it: there cannot be one!
2684
2590
if (Num < NextNum) {
2685
- Value *NotCmp = findLeader (Root.getEnd (), Num);
2686
- if (NotCmp && isa<Instruction>(NotCmp)) {
2687
- unsigned NumReplacements =
2688
- DominatesByEdge
2689
- ? replaceDominatedUsesWith (NotCmp, NotVal, *DT, Root)
2690
- : replaceDominatedUsesWith (NotCmp, NotVal, *DT,
2691
- Root.getStart ());
2692
- Changed |= NumReplacements > 0 ;
2693
- NumGVNEqProp += NumReplacements;
2694
- // Cached information for anything that uses NotCmp will be invalid.
2695
- if (MD)
2696
- MD->invalidateCachedPointerInfo (NotCmp);
2591
+ for (const auto &Entry : LeaderTable.getLeaders (Num)) {
2592
+ // Only look at leaders that either dominate the start of the edge,
2593
+ // or are dominated by the end. This check is not necessary for
2594
+ // correctness, it only discards cases for which the following
2595
+ // use replacement will not work anyway.
2596
+ if (const BasicBlockEdge *Edge = std::get_if<BasicBlockEdge>(&Root)) {
2597
+ if (!DT->dominates (Entry.BB , Edge->getStart ()) &&
2598
+ !DT->dominates (Edge->getEnd (), Entry.BB ))
2599
+ continue ;
2600
+ } else {
2601
+ auto *InstBB = std::get<Instruction *>(Root)->getParent ();
2602
+ if (!DT->dominates (Entry.BB , InstBB) &&
2603
+ !DT->dominates (InstBB, Entry.BB ))
2604
+ continue ;
2605
+ }
2606
+
2607
+ Value *NotCmp = Entry.Val ;
2608
+ if (NotCmp && isa<Instruction>(NotCmp)) {
2609
+ unsigned NumReplacements;
2610
+ if (const BasicBlockEdge *Edge = std::get_if<BasicBlockEdge>(&Root))
2611
+ NumReplacements =
2612
+ replaceDominatedUsesWith (NotCmp, NotVal, *DT, *Edge);
2613
+ else
2614
+ NumReplacements = replaceDominatedUsesWith (
2615
+ NotCmp, NotVal, *DT, std::get<Instruction *>(Root));
2616
+ Changed |= NumReplacements > 0 ;
2617
+ NumGVNEqProp += NumReplacements;
2618
+ // Cached information for anything that uses NotCmp will be invalid.
2619
+ if (MD)
2620
+ MD->invalidateCachedPointerInfo (NotCmp);
2621
+ }
2697
2622
}
2698
2623
}
2699
2624
// Ensure that any instruction in scope that gets the "A < B" value number
2700
2625
// is replaced with false.
2701
2626
// The leader table only tracks basic blocks, not edges. Only add to if we
2702
2627
// have the simple case where the edge dominates the end.
2703
- if (RootDominatesEnd )
2704
- LeaderTable.insert (Num, NotVal, Root. getEnd () );
2628
+ for ( const BasicBlock *BB : DominatedBlocks )
2629
+ LeaderTable.insert (Num, NotVal, BB );
2705
2630
2706
2631
continue ;
2707
2632
}
@@ -2789,11 +2714,11 @@ bool GVNPass::processInstruction(Instruction *I) {
2789
2714
2790
2715
Value *TrueVal = ConstantInt::getTrue (TrueSucc->getContext ());
2791
2716
BasicBlockEdge TrueE (Parent, TrueSucc);
2792
- Changed |= propagateEquality (BranchCond, TrueVal, TrueE, true );
2717
+ Changed |= propagateEquality (BranchCond, TrueVal, TrueE);
2793
2718
2794
2719
Value *FalseVal = ConstantInt::getFalse (FalseSucc->getContext ());
2795
2720
BasicBlockEdge FalseE (Parent, FalseSucc);
2796
- Changed |= propagateEquality (BranchCond, FalseVal, FalseE, true );
2721
+ Changed |= propagateEquality (BranchCond, FalseVal, FalseE);
2797
2722
2798
2723
return Changed;
2799
2724
}
@@ -2814,7 +2739,7 @@ bool GVNPass::processInstruction(Instruction *I) {
2814
2739
// If there is only a single edge, propagate the case value into it.
2815
2740
if (SwitchEdges.lookup (Dst) == 1 ) {
2816
2741
BasicBlockEdge E (Parent, Dst);
2817
- Changed |= propagateEquality (SwitchCond, Case.getCaseValue (), E, true );
2742
+ Changed |= propagateEquality (SwitchCond, Case.getCaseValue (), E);
2818
2743
}
2819
2744
}
2820
2745
return Changed;
@@ -2942,8 +2867,6 @@ bool GVNPass::processBlock(BasicBlock *BB) {
2942
2867
if (DeadBlocks.count (BB))
2943
2868
return false ;
2944
2869
2945
- // Clearing map before every BB because it can be used only for single BB.
2946
- ReplaceOperandsWithMap.clear ();
2947
2870
bool ChangedFunction = false ;
2948
2871
2949
2872
// Since we may not have visited the input blocks of the phis, we can't
@@ -2955,11 +2878,8 @@ bool GVNPass::processBlock(BasicBlock *BB) {
2955
2878
for (PHINode *PN : PHINodesToRemove) {
2956
2879
removeInstruction (PN);
2957
2880
}
2958
- for (Instruction &Inst : make_early_inc_range (*BB)) {
2959
- if (!ReplaceOperandsWithMap.empty ())
2960
- ChangedFunction |= replaceOperandsForInBlockEquality (&Inst);
2881
+ for (Instruction &Inst : make_early_inc_range (*BB))
2961
2882
ChangedFunction |= processInstruction (&Inst);
2962
- }
2963
2883
return ChangedFunction;
2964
2884
}
2965
2885
0 commit comments