[llvm] 1aece0e - Revert "[GVN] Support address translation through select instructions"

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 28 10:18:53 PST 2023


Hi,

When reverting a change, please make sure to include the reason for the revert.

Cheers,
Florian

> On 27 Feb 2023, at 10:58, Sergey Kachkov via llvm-commits <llvm-commits at lists.llvm.org> wrote:
> 
> 
> Author: Sergey Kachkov
> Date: 2023-02-27T12:57:59+03:00
> New Revision: 1aece0e5edf8d4fef1b5e226825a245dce5c382e
> 
> URL: https://github.com/llvm/llvm-project/commit/1aece0e5edf8d4fef1b5e226825a245dce5c382e
> DIFF: https://github.com/llvm/llvm-project/commit/1aece0e5edf8d4fef1b5e226825a245dce5c382e.diff
> 
> LOG: Revert "[GVN] Support address translation through select instructions"
> 
> This reverts commit b5bf6f6392a3408be1b7b7e036eb69358c5a2c29.
> 
> Added: 
> 
> 
> Modified: 
>    llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
>    llvm/include/llvm/Analysis/PHITransAddr.h
>    llvm/include/llvm/Transforms/Scalar/GVN.h
>    llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
>    llvm/lib/Analysis/PHITransAddr.cpp
>    llvm/lib/Transforms/Scalar/GVN.cpp
>    llvm/test/Transforms/GVN/PRE/pre-load-through-select.ll
>    llvm/test/Transforms/GVN/PRE/pre-loop-load-through-select.ll
>    llvm/test/Transforms/GVN/opaque-ptr.ll
> 
> Removed: 
> 
> 
> 
> ################################################################################
> diff  --git a/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h b/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
> index 3306ee5ab1440..27185aa9942e4 100644
> --- a/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
> +++ b/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
> @@ -19,7 +19,6 @@
> #include "llvm/ADT/PointerSumType.h"
> #include "llvm/ADT/SmallPtrSet.h"
> #include "llvm/Analysis/MemoryLocation.h"
> -#include "llvm/Analysis/PHITransAddr.h"
> #include "llvm/IR/PassManager.h"
> #include "llvm/IR/PredIteratorCache.h"
> #include "llvm/IR/ValueHandle.h"
> @@ -32,6 +31,7 @@ class AAResults;
> class AssumptionCache;
> class BatchAAResults;
> class DominatorTree;
> +class PHITransAddr;
> 
> /// A memory dependence query can return one of three 
> diff erent answers.
> class MemDepResult {
> @@ -77,6 +77,11 @@ class MemDepResult {
>     ///      calls or memory use intrinsics with identical callees and no
>     ///      intervening clobbers.  No validation is done that the operands to
>     ///      the calls are the same.
> +    ///   4. For loads and stores, this could be a select instruction that
> +    ///      defines pointer to this memory location. In this case, users can
> +    ///      find non-clobbered Defs for both select values that are reaching
> +    //       the desired memory location (there is still a guarantee that there
> +    //       are no clobbers between analyzed memory location and select).
>     Def,
> 
>     /// This marker indicates that the query has no known dependency in the
> @@ -98,8 +103,6 @@ class MemDepResult {
>     /// This marker indicates that the query has no dependency in the specified
>     /// function.
>     NonFuncLocal,
> -    /// This marker indicates that the query depends from select instruction.
> -    Select,
>     /// This marker indicates that the query dependency is unknown.
>     Unknown
>   };
> @@ -132,9 +135,6 @@ class MemDepResult {
>   static MemDepResult getNonFuncLocal() {
>     return MemDepResult(ValueTy::create<Other>(NonFuncLocal));
>   }
> -  static MemDepResult getSelect() {
> -    return MemDepResult(ValueTy::create<Other>(Select));
> -  }
>   static MemDepResult getUnknown() {
>     return MemDepResult(ValueTy::create<Other>(Unknown));
>   }
> @@ -162,12 +162,6 @@ class MemDepResult {
>     return Value.is<Other>() && Value.cast<Other>() == NonFuncLocal;
>   }
> 
> -  /// Tests if this MemDepResult represents a query that has a dependency from
> -  /// the select instruction.
> -  bool isSelect() const {
> -    return Value.is<Other>() && Value.cast<Other>() == Select;
> -  }
> -
>   /// Tests if this MemDepResult represents a query which cannot and/or will
>   /// not be computed.
>   bool isUnknown() const {
> @@ -236,11 +230,10 @@ class NonLocalDepEntry {
> /// (potentially phi translated) address that was live in the block.
> class NonLocalDepResult {
>   NonLocalDepEntry Entry;
> -  SelectAddr Address;
> +  Value *Address;
> 
> public:
> -  NonLocalDepResult(BasicBlock *BB, MemDepResult Result,
> -                    const SelectAddr &Address)
> +  NonLocalDepResult(BasicBlock *BB, MemDepResult Result, Value *Address)
>       : Entry(BB, Result), Address(Address) {}
> 
>   // BB is the sort key, it can't be changed.
> @@ -261,7 +254,7 @@ class NonLocalDepResult {
>   /// a cached result and that address was deleted.
>   ///
>   /// The address is always null for a non-local 'call' dependence.
> -  SelectAddr getAddress() const { return Address; }
> +  Value *getAddress() const { return Address; }
> };
> 
> /// Provides a lazy, caching interface for making common memory aliasing
> 
> diff  --git a/llvm/include/llvm/Analysis/PHITransAddr.h b/llvm/include/llvm/Analysis/PHITransAddr.h
> index 5942e761e1895..de9c3c4fd2921 100644
> --- a/llvm/include/llvm/Analysis/PHITransAddr.h
> +++ b/llvm/include/llvm/Analysis/PHITransAddr.h
> @@ -15,7 +15,6 @@
> 
> #include "llvm/ADT/SmallVector.h"
> #include "llvm/IR/Instruction.h"
> -#include "llvm/IR/Instructions.h"
> 
> namespace llvm {
> class AssumptionCache;
> @@ -23,40 +22,6 @@ class DominatorTree;
> class DataLayout;
> class TargetLibraryInfo;
> 
> -// SelectAddr - storage of normal Value address or Condition value and pair of
> -// addresses for true and false variant of select dependency. If Addrs are not
> -// present (both values are nullptr), V is a normal address; otherwise, V is a
> -// select condition and SelectAddrs are "true" and "false" addresses.
> -class SelectAddr {
> -public:
> -  using SelectAddrs = std::pair<Value *, Value *>;
> -
> -  SelectAddr(Value *Addr) : V(Addr), Addrs(nullptr, nullptr) {}
> -  SelectAddr(Value *Cond, SelectAddrs Addrs) : V(Cond), Addrs(Addrs) {
> -    assert(Cond && "Condition must be present");
> -    assert(hasSelectAddrs() && "Addrs must be present");
> -  };
> -  Value *getAddr() const {
> -    assert(!hasSelectAddrs());
> -    return V;
> -  }
> -  std::pair<Value *, SelectAddrs> getSelectCondAndAddrs() const {
> -    // If Addrs is present, return it.
> -    if (hasSelectAddrs())
> -      return {V, Addrs};
> -    // Otherwise V must be SelectInst; return condition and both addresses from
> -    // its operands.
> -    auto *SI = cast<SelectInst>(V);
> -    return {SI->getCondition(), {SI->getTrueValue(), SI->getFalseValue()}};
> -  }
> -
> -private:
> -  Value *V;
> -  SelectAddrs Addrs;
> -
> -  bool hasSelectAddrs() const { return Addrs.first && Addrs.second; }
> -};
> -
> /// PHITransAddr - An address value which tracks and handles phi translation.
> /// As we walk "up" the CFG through predecessors, we need to ensure that the
> /// address we're tracking is kept up to date.  For example, if we're analyzing
> @@ -92,15 +57,6 @@ class PHITransAddr {
> 
>   Value *getAddr() const { return Addr; }
> 
> -  /// getSelectCondition - if address has select input, return its condition
> -  /// (otherwise nullptr).
> -  Value *getSelectCondition() const {
> -    for (auto *I : InstInputs)
> -      if (auto *SI = dyn_cast<SelectInst>(I))
> -        return SI->getCondition();
> -    return nullptr;
> -  }
> -
>   /// needsPHITranslationFromBlock - Return true if moving from the specified
>   /// BasicBlock to its predecessors requires PHI translation.
>   bool needsPHITranslationFromBlock(BasicBlock *BB) const {
> @@ -122,12 +78,6 @@ class PHITransAddr {
>   Value *translateValue(BasicBlock *CurBB, BasicBlock *PredBB,
>                         const DominatorTree *DT, bool MustDominate);
> 
> -  /// translateValue - PHI translate the current address from \p CurBB to \p
> -  /// PredBB, and if the resulted address depends on select instructions with \p
> -  /// Cond predicate, translate both cases of this selects.
> -  SelectAddr::SelectAddrs translateValue(BasicBlock *CurBB, BasicBlock *PredBB,
> -                                         const DominatorTree *DT, Value *Cond);
> -
>   /// translateWithInsertion - PHI translate this value into the specified
>   /// predecessor block, inserting a computation of the value if it is
>   /// unavailable.
> @@ -147,13 +97,8 @@ class PHITransAddr {
>   bool verify() const;
> 
> private:
> -  /// translateSubExpr - recursively translate value \p V from \p CurBB to \p
> -  /// PredBB, and if value depends from selects with \p Cond condition, also
> -  /// translate it through these selects with \p CondVal predicate. Return
> -  /// nullptr on failure.
>   Value *translateSubExpr(Value *V, BasicBlock *CurBB, BasicBlock *PredBB,
> -                          const DominatorTree *DT, Value *Cond = nullptr,
> -                          bool CondVal = false);
> +                          const DominatorTree *DT);
> 
>   /// insertTranslatedSubExpr - Insert a computation of the PHI translated
>   /// version of 'V' for the edge PredBB->CurBB into the end of the PredBB
> 
> diff  --git a/llvm/include/llvm/Transforms/Scalar/GVN.h b/llvm/include/llvm/Transforms/Scalar/GVN.h
> index b8708f920aa34..4666a53156163 100644
> --- a/llvm/include/llvm/Transforms/Scalar/GVN.h
> +++ b/llvm/include/llvm/Transforms/Scalar/GVN.h
> @@ -52,7 +52,6 @@ class MemorySSAUpdater;
> class NonLocalDepResult;
> class OptimizationRemarkEmitter;
> class PHINode;
> -class SelectAddr;
> class TargetLibraryInfo;
> class Value;
> /// A private "module" namespace for types and utilities used by GVN. These
> @@ -318,12 +317,6 @@ class GVNPass : public PassInfoMixin<GVNPass> {
>   bool processNonLocalLoad(LoadInst *L);
>   bool processAssumeIntrinsic(AssumeInst *II);
> 
> -  /// Given a load with Select dependency, determine if its value is available
> -  /// for both sides of select (true and false values).
> -  std::optional<gvn::AvailableValue>
> -  AnalyzeSelectAvailability(LoadInst *Load, const SelectAddr &Addr,
> -                            Instruction *From);
> -
>   /// Given a local dependency (Def or Clobber) determine if a value is
>   /// available for the load.
>   std::optional<gvn::AvailableValue>
> 
> diff  --git a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
> index 4c19ac48fc190..071ecdba8a54a 100644
> --- a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
> +++ b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
> @@ -23,6 +23,7 @@
> #include "llvm/Analysis/AssumptionCache.h"
> #include "llvm/Analysis/MemoryBuiltins.h"
> #include "llvm/Analysis/MemoryLocation.h"
> +#include "llvm/Analysis/PHITransAddr.h"
> #include "llvm/Analysis/TargetLibraryInfo.h"
> #include "llvm/Analysis/ValueTracking.h"
> #include "llvm/IR/BasicBlock.h"
> @@ -591,10 +592,10 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
>         return MemDepResult::getDef(Inst);
>     }
> 
> -    // If we found a select instruction for MemLoc pointer, return it as Select
> +    // If we found a select instruction for MemLoc pointer, return it as Def
>     // dependency.
>     if (isa<SelectInst>(Inst) && MemLoc.Ptr == Inst)
> -      return MemDepResult::getSelect();
> +      return MemDepResult::getDef(Inst);
> 
>     if (isInvariantLoad)
>       continue;
> @@ -1345,20 +1346,8 @@ bool MemoryDependenceResults::getNonLocalPointerDepFromBB(
>       // predecessor, then we have to assume that the pointer is clobbered in
>       // that predecessor.  We can still do PRE of the load, which would insert
>       // a computation of the pointer in this predecessor.
> -      if (!PredPtrVal) {
> -        // If we have translation failure, but there is a select input in
> -        // address, try to translate both sides of it.
> -        if (Value *Cond = PredPointer.getSelectCondition()) {
> -          auto SelectAddrs =
> -              PHITransAddr(Pointer).translateValue(BB, Pred, &DT, Cond);
> -          if (SelectAddrs.first && SelectAddrs.second) {
> -            Result.push_back(NonLocalDepResult(Pred, MemDepResult::getSelect(),
> -                                               SelectAddr(Cond, SelectAddrs)));
> -            continue;
> -          }
> -        }
> +      if (!PredPtrVal)
>         CanTranslate = false;
> -      }
> 
>       // FIXME: it is entirely possible that PHI translating will end up with
>       // the same value.  Consider PHI translating something like:
> 
> diff  --git a/llvm/lib/Analysis/PHITransAddr.cpp b/llvm/lib/Analysis/PHITransAddr.cpp
> index f256efd2bb473..5700fd664a4cd 100644
> --- a/llvm/lib/Analysis/PHITransAddr.cpp
> +++ b/llvm/lib/Analysis/PHITransAddr.cpp
> @@ -16,6 +16,7 @@
> #include "llvm/Config/llvm-config.h"
> #include "llvm/IR/Constants.h"
> #include "llvm/IR/Dominators.h"
> +#include "llvm/IR/Instructions.h"
> #include "llvm/Support/ErrorHandling.h"
> #include "llvm/Support/raw_ostream.h"
> using namespace llvm;
> @@ -125,14 +126,9 @@ static void RemoveInstInputs(Value *V,
>       RemoveInstInputs(OpInst, InstInputs);
> }
> 
> -/// translateSubExpr - recursively translate value \p V from \p CurBB to \p
> -/// PredBB, and if value depends from selects with \p Cond condition, also
> -/// translate it through these selects with \p CondVal predicate. Return nullptr
> -/// on failure.
> Value *PHITransAddr::translateSubExpr(Value *V, BasicBlock *CurBB,
>                                       BasicBlock *PredBB,
> -                                      const DominatorTree *DT, Value *Cond,
> -                                      bool CondVal) {
> +                                      const DominatorTree *DT) {
>   // If this is a non-instruction value, it can't require PHI translation.
>   Instruction *Inst = dyn_cast<Instruction>(V);
>   if (!Inst) return V;
> @@ -155,13 +151,8 @@ Value *PHITransAddr::translateSubExpr(Value *V, BasicBlock *CurBB,
>     InstInputs.erase(find(InstInputs, Inst));
> 
>     // If this is a PHI, go ahead and translate it.
> -    if (PHINode *PN = dyn_cast<PHINode>(Inst)) {
> -      auto *V = PN->getIncomingValueForBlock(PredBB);
> -      if (auto *SI = dyn_cast<SelectInst>(V))
> -        if (SI->getCondition() == Cond)
> -          return addAsInput(CondVal ? SI->getTrueValue() : SI->getFalseValue());
> -      return addAsInput(V);
> -    }
> +    if (PHINode *PN = dyn_cast<PHINode>(Inst))
> +      return addAsInput(PN->getIncomingValueForBlock(PredBB));
> 
>     // If this is a non-phi value, and it is analyzable, we can incorporate it
>     // into the expression by making all instruction operands be inputs.
> @@ -179,8 +170,7 @@ Value *PHITransAddr::translateSubExpr(Value *V, BasicBlock *CurBB,
>   // operands need to be phi translated, and if so, reconstruct it.
> 
>   if (CastInst *Cast = dyn_cast<CastInst>(Inst)) {
> -    Value *PHIIn =
> -        translateSubExpr(Cast->getOperand(0), CurBB, PredBB, DT, Cond, CondVal);
> +    Value *PHIIn = translateSubExpr(Cast->getOperand(0), CurBB, PredBB, DT);
>     if (!PHIIn) return nullptr;
>     if (PHIIn == Cast->getOperand(0))
>       return Cast;
> @@ -211,7 +201,7 @@ Value *PHITransAddr::translateSubExpr(Value *V, BasicBlock *CurBB,
>     SmallVector<Value*, 8> GEPOps;
>     bool AnyChanged = false;
>     for (Value *Op : GEP->operands()) {
> -      Value *GEPOp = translateSubExpr(Op, CurBB, PredBB, DT, Cond, CondVal);
> +      Value *GEPOp = translateSubExpr(Op, CurBB, PredBB, DT);
>       if (!GEPOp) return nullptr;
> 
>       AnyChanged |= GEPOp != Op;
> @@ -255,8 +245,7 @@ Value *PHITransAddr::translateSubExpr(Value *V, BasicBlock *CurBB,
>     bool isNSW = cast<BinaryOperator>(Inst)->hasNoSignedWrap();
>     bool isNUW = cast<BinaryOperator>(Inst)->hasNoUnsignedWrap();
> 
> -    Value *LHS =
> -        translateSubExpr(Inst->getOperand(0), CurBB, PredBB, DT, Cond, CondVal);
> +    Value *LHS = translateSubExpr(Inst->getOperand(0), CurBB, PredBB, DT);
>     if (!LHS) return nullptr;
> 
>     // If the PHI translated LHS is an add of a constant, fold the immediates.
> @@ -326,20 +315,6 @@ Value *PHITransAddr::translateValue(BasicBlock *CurBB, BasicBlock *PredBB,
>   return Addr;
> }
> 
> -/// translateValue - PHI translate the current address from \p CurBB to \p
> -/// PredBB, and if the resulted address depends on select instructions with \p
> -/// Cond predicate, translate both cases of this selects.
> -SelectAddr::SelectAddrs PHITransAddr::translateValue(BasicBlock *CurBB,
> -                                                     BasicBlock *PredBB,
> -                                                     const DominatorTree *DT,
> -                                                     Value *Cond) {
> -  Value *TrueAddr =
> -      PHITransAddr(*this).translateSubExpr(Addr, CurBB, PredBB, DT, Cond, true);
> -  Value *FalseAddr = PHITransAddr(*this).translateSubExpr(Addr, CurBB, PredBB,
> -                                                          DT, Cond, false);
> -  return {TrueAddr, FalseAddr};
> -}
> -
> /// PHITranslateWithInsertion - PHI translate this value into the specified
> /// predecessor block, inserting a computation of the value if it is
> /// unavailable.
> 
> diff  --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
> index ef13b187f9c2f..28b1f455459f8 100644
> --- a/llvm/lib/Transforms/Scalar/GVN.cpp
> +++ b/llvm/lib/Transforms/Scalar/GVN.cpp
> @@ -200,8 +200,6 @@ struct llvm::gvn::AvailableValue {
>   unsigned Offset = 0;
>   /// V1, V2 - The dominating non-clobbered values of SelectVal.
>   Value *V1 = nullptr, *V2 = nullptr;
> -  /// InsertPt - The position for select materialization.
> -  Instruction *InsertPt = nullptr;
> 
>   static AvailableValue get(Value *V, unsigned Offset = 0) {
>     AvailableValue Res;
> @@ -235,15 +233,13 @@ struct llvm::gvn::AvailableValue {
>     return Res;
>   }
> 
> -  static AvailableValue getSelect(Value *Cond, Value *V1, Value *V2,
> -                                  Instruction *InsertPt) {
> +  static AvailableValue getSelect(SelectInst *Sel, Value *V1, Value *V2) {
>     AvailableValue Res;
> -    Res.Val = Cond;
> +    Res.Val = Sel;
>     Res.Kind = ValType::SelectVal;
>     Res.Offset = 0;
>     Res.V1 = V1;
>     Res.V2 = V2;
> -    Res.InsertPt = InsertPt;
>     return Res;
>   }
> 
> @@ -268,6 +264,11 @@ struct llvm::gvn::AvailableValue {
>     return cast<MemIntrinsic>(Val);
>   }
> 
> +  SelectInst *getSelectValue() const {
> +    assert(isSelectValue() && "Wrong accessor");
> +    return cast<SelectInst>(Val);
> +  }
> +
>   /// Emit code at the specified insertion point to adjust the value defined
>   /// here to the specified type. This handles various coercion cases.
>   Value *MaterializeAdjustedValue(LoadInst *Load, Instruction *InsertPt,
> @@ -299,6 +300,11 @@ struct llvm::gvn::AvailableValueInBlock {
>     return get(BB, AvailableValue::getUndef());
>   }
> 
> +  static AvailableValueInBlock getSelect(BasicBlock *BB, SelectInst *Sel,
> +                                         Value *V1, Value *V2) {
> +    return get(BB, AvailableValue::getSelect(Sel, V1, V2));
> +  }
> +
>   /// Emit code at the end of this block to adjust the value defined here to
>   /// the specified type. This handles various coercion cases.
>   Value *MaterializeAdjustedValue(LoadInst *Load, GVNPass &gvn) const {
> @@ -1013,8 +1019,9 @@ Value *AvailableValue::MaterializeAdjustedValue(LoadInst *Load,
>                       << "\n\n\n");
>   } else if (isSelectValue()) {
>     // Introduce a new value select for a load from an eligible pointer select.
> +    SelectInst *Sel = getSelectValue();
>     assert(V1 && V2 && "both value operands of the select must be present");
> -    Res = SelectInst::Create(Val, V1, V2, "", InsertPt);
> +    Res = SelectInst::Create(Sel->getCondition(), V1, V2, "", Sel);
>   } else {
>     llvm_unreachable("Should not materialize value from dead block");
>   }
> @@ -1125,32 +1132,6 @@ static Value *findDominatingValue(const MemoryLocation &Loc, Type *LoadTy,
>   return nullptr;
> }
> 
> -// Check if load with Addr dependent from select can be converted to select
> -// between load values. There must be no clobbers between the found loads and
> -// From instruction.
> -std::optional<AvailableValue>
> -GVNPass::AnalyzeSelectAvailability(LoadInst *Load, const SelectAddr &Addr,
> -                                   Instruction *From) {
> -  auto [Cond, SelectAddrs] = Addr.getSelectCondAndAddrs();
> -  auto [TrueAddr, FalseAddr] = SelectAddrs;
> -  assert(TrueAddr && "Missing address of true side of select dependency");
> -  assert(TrueAddr->getType() == Load->getPointerOperandType() &&
> -         "Invalid address type of true side of select dependency");
> -  assert(FalseAddr && "Missing address of false side of select dependency");
> -  assert(FalseAddr->getType() == Load->getPointerOperandType() &&
> -         "Invalid address type of false side of select dependency");
> -  auto Loc = MemoryLocation::get(Load);
> -  Value *V1 = findDominatingValue(Loc.getWithNewPtr(TrueAddr), Load->getType(),
> -                                  From, getAliasAnalysis());
> -  if (!V1)
> -    return std::nullopt;
> -  Value *V2 = findDominatingValue(Loc.getWithNewPtr(FalseAddr), Load->getType(),
> -                                  From, getAliasAnalysis());
> -  if (!V2)
> -    return std::nullopt;
> -  return AvailableValue::getSelect(Cond, V1, V2, From);
> -}
> -
> std::optional<AvailableValue>
> GVNPass::AnalyzeLoadAvailability(LoadInst *Load, MemDepResult DepInfo,
>                                  Value *Address) {
> @@ -1265,6 +1246,25 @@ GVNPass::AnalyzeLoadAvailability(LoadInst *Load, MemDepResult DepInfo,
>     return AvailableValue::getLoad(LD);
>   }
> 
> +  // Check if load with Addr dependent from select can be converted to select
> +  // between load values. There must be no instructions between the found
> +  // loads and DepInst that may clobber the loads.
> +  if (auto *Sel = dyn_cast<SelectInst>(DepInst)) {
> +    assert(Sel->getType() == Load->getPointerOperandType());
> +    auto Loc = MemoryLocation::get(Load);
> +    Value *V1 =
> +        findDominatingValue(Loc.getWithNewPtr(Sel->getTrueValue()),
> +                            Load->getType(), DepInst, getAliasAnalysis());
> +    if (!V1)
> +      return std::nullopt;
> +    Value *V2 =
> +        findDominatingValue(Loc.getWithNewPtr(Sel->getFalseValue()),
> +                            Load->getType(), DepInst, getAliasAnalysis());
> +    if (!V2)
> +      return std::nullopt;
> +    return AvailableValue::getSelect(Sel, V1, V2);
> +  }
> +
>   // Unknown def - must be conservative
>   LLVM_DEBUG(
>       // fast print dep, using operator<< on instruction is too slow.
> @@ -1283,7 +1283,6 @@ void GVNPass::AnalyzeLoadAvailability(LoadInst *Load, LoadDepVect &Deps,
>   for (const auto &Dep : Deps) {
>     BasicBlock *DepBB = Dep.getBB();
>     MemDepResult DepInfo = Dep.getResult();
> -    SelectAddr Addr = Dep.getAddress();
> 
>     if (DeadBlocks.count(DepBB)) {
>       // Dead dependent mem-op disguise as a load evaluating the same value
> @@ -1293,13 +1292,6 @@ void GVNPass::AnalyzeLoadAvailability(LoadInst *Load, LoadDepVect &Deps,
>     }
> 
>     if (!DepInfo.isLocal()) {
> -      if (DepInfo.isSelect())
> -        if (auto AV =
> -                AnalyzeSelectAvailability(Load, Addr, DepBB->getTerminator())) {
> -          ValuesPerBlock.push_back(
> -              AvailableValueInBlock::get(DepBB, std::move(*AV)));
> -          continue;
> -        }
>       UnavailableBlocks.push_back(DepBB);
>       continue;
>     }
> @@ -1307,7 +1299,7 @@ void GVNPass::AnalyzeLoadAvailability(LoadInst *Load, LoadDepVect &Deps,
>     // The address being loaded in this non-local block may not be the same as
>     // the pointer operand of the load if PHI translation occurs.  Make sure
>     // to consider the right address.
> -    if (auto AV = AnalyzeLoadAvailability(Load, DepInfo, Addr.getAddr())) {
> +    if (auto AV = AnalyzeLoadAvailability(Load, DepInfo, Dep.getAddress())) {
>       // subtlety: because we know this was a non-local dependency, we know
>       // it's safe to materialize anywhere between the instruction within
>       // DepInfo and the end of it's block.
> @@ -1746,7 +1738,7 @@ bool GVNPass::processNonLocalLoad(LoadInst *Load) {
>   // If we had a phi translation failure, we'll have a single entry which is a
>   // clobber in the current block.  Reject this early.
>   if (NumDeps == 1 &&
> -      !Deps[0].getResult().isLocal() && !Deps[0].getResult().isSelect()) {
> +      !Deps[0].getResult().isDef() && !Deps[0].getResult().isClobber()) {
>     LLVM_DEBUG(dbgs() << "GVN: non-local load "; Load->printAsOperand(dbgs());
>                dbgs() << " has unknown dependencies\n";);
>     return false;
> @@ -2036,12 +2028,8 @@ bool GVNPass::processLoad(LoadInst *L) {
>   if (Dep.isNonLocal())
>     return processNonLocalLoad(L);
> 
> -  std::optional<AvailableValue> AV;
> -  if (Dep.isLocal())
> -    AV = AnalyzeLoadAvailability(L, Dep, L->getPointerOperand());
> -  else if (Dep.isSelect())
> -    AV = AnalyzeSelectAvailability(L, L->getPointerOperand(), L);
> -  else {
> +  // Only handle the local case below
> +  if (!Dep.isLocal()) {
>     // This might be a NonFuncLocal or an Unknown
>     LLVM_DEBUG(
>         // fast print dep, using operator<< on instruction is too slow.
> @@ -2050,6 +2038,7 @@ bool GVNPass::processLoad(LoadInst *L) {
>     return false;
>   }
> 
> +  auto AV = AnalyzeLoadAvailability(L, Dep, L->getPointerOperand());
>   if (!AV)
>     return false;
> 
> 
> diff  --git a/llvm/test/Transforms/GVN/PRE/pre-load-through-select.ll b/llvm/test/Transforms/GVN/PRE/pre-load-through-select.ll
> index d439735fba5b8..4de69cc94e37a 100644
> --- a/llvm/test/Transforms/GVN/PRE/pre-load-through-select.ll
> +++ b/llvm/test/Transforms/GVN/PRE/pre-load-through-select.ll
> @@ -9,8 +9,8 @@ define i32 @test_pointer_phi_select_simp_1(ptr %a, ptr %b, i1 %cond)  {
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[A:%.*]], align 4
> ; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[B:%.*]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> -; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> +; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    br label [[EXIT:%.*]]
> ; CHECK:       else:
> ; CHECK-NEXT:    [[RES_2_PRE:%.*]] = load i32, ptr [[A]], align 4
> @@ -48,8 +48,8 @@ define i32 @test_pointer_phi_select_simp_non_local(ptr %a, ptr %b, ptr %c)  {
> ; CHECK:       then:
> ; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[B:%.*]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> -; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> +; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    br label [[EXIT:%.*]]
> ; CHECK:       else:
> ; CHECK-NEXT:    [[RES_2_PRE:%.*]] = load i32, ptr [[C:%.*]], align 4
> @@ -200,8 +200,8 @@ define i32 @test_pointer_phi_select_simp_store_noclobber(ptr %a, ptr %b, ptr noa
> ; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[B:%.*]], align 4
> ; CHECK-NEXT:    store i32 99, ptr [[C:%.*]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> -; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> +; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    br label [[EXIT:%.*]]
> ; CHECK:       else:
> ; CHECK-NEXT:    [[RES_2_PRE:%.*]] = load i32, ptr [[A]], align 4
> @@ -316,8 +316,8 @@ define i32 @test_pointer_phi_select_simp_store_clobber_3(ptr %a, ptr %b, ptr %c,
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[A:%.*]], align 4
> ; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[B:%.*]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> -; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> +; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    br label [[EXIT:%.*]]
> ; CHECK:       else:
> ; CHECK-NEXT:    [[RES_2_PRE:%.*]] = load i32, ptr [[A]], align 4
> @@ -734,8 +734,8 @@ define i32 @test_pointer_phi_select_single_block_store(ptr %a, ptr %b)  {
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[A:%.*]], align 4
> ; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[B:%.*]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> -; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> +; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    ret i32 [[TMP0]]
> ;
> entry:
> @@ -816,8 +816,8 @@ define i32 @test_pointer_phi_select_single_block_store_after(ptr %a, ptr %b, ptr
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[A:%.*]], align 4
> ; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[B:%.*]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> -; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> +; CHECK-NEXT:    [[MIN_SELECT:%.*]] = select i1 [[CMP_I_I_I]], ptr [[A]], ptr [[B]]
> ; CHECK-NEXT:    store i32 99, ptr [[C:%.*]], align 4
> ; CHECK-NEXT:    ret i32 [[TMP0]]
> ;
> @@ -835,15 +835,10 @@ define i32 @test_phi_select_index_non_local(ptr %A, i32 %N, i32 %i)  {
> ; CHECK-LABEL: @test_phi_select_index_non_local(
> ; CHECK-NEXT:  entry:
> ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I:%.*]], [[N:%.*]]
> -; CHECK-NEXT:    br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[ENTRY_IF_END_CRIT_EDGE:%.*]]
> -; CHECK:       entry.if.end_crit_edge:
> -; CHECK-NEXT:    [[IDXPROM5_PHI_TRANS_INSERT:%.*]] = sext i32 [[I]] to i64
> -; CHECK-NEXT:    [[ARRAYIDX6_PHI_TRANS_INSERT:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM5_PHI_TRANS_INSERT]]
> -; CHECK-NEXT:    [[DOTPRE:%.*]] = load i32, ptr [[ARRAYIDX6_PHI_TRANS_INSERT]], align 4
> -; CHECK-NEXT:    br label [[IF_END:%.*]]
> +; CHECK-NEXT:    br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[IF_END:%.*]]
> ; CHECK:       land.lhs.true:
> ; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[I]] to i64
> -; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM]]
> +; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM]]
> ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
> ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[I]], 1
> ; CHECK-NEXT:    [[IDXPROM1:%.*]] = sext i32 [[ADD]] to i64
> @@ -851,15 +846,13 @@ define i32 @test_phi_select_index_non_local(ptr %A, i32 %N, i32 %i)  {
> ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX2]], align 4
> ; CHECK-NEXT:    [[CMP3:%.*]] = icmp slt i32 [[TMP0]], [[TMP1]]
> ; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[CMP3]], i32 [[ADD]], i32 [[I]]
> -; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[CMP3]], i32 [[TMP1]], i32 [[TMP0]]
> -; CHECK-NEXT:    [[DOTPRE1:%.*]] = sext i32 [[SPEC_SELECT]] to i64
> ; CHECK-NEXT:    br label [[IF_END]]
> ; CHECK:       if.end:
> -; CHECK-NEXT:    [[IDXPROM5_PRE_PHI:%.*]] = phi i64 [ [[IDXPROM5_PHI_TRANS_INSERT]], [[ENTRY_IF_END_CRIT_EDGE]] ], [ [[DOTPRE1]], [[LAND_LHS_TRUE]] ]
> -; CHECK-NEXT:    [[TMP3:%.*]] = phi i32 [ [[DOTPRE]], [[ENTRY_IF_END_CRIT_EDGE]] ], [ [[TMP2]], [[LAND_LHS_TRUE]] ]
> -; CHECK-NEXT:    [[I_ADDR_0:%.*]] = phi i32 [ [[I]], [[ENTRY_IF_END_CRIT_EDGE]] ], [ [[SPEC_SELECT]], [[LAND_LHS_TRUE]] ]
> -; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM5_PRE_PHI]]
> -; CHECK-NEXT:    ret i32 [[TMP3]]
> +; CHECK-NEXT:    [[I_ADDR_0:%.*]] = phi i32 [ [[I]], [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[LAND_LHS_TRUE]] ]
> +; CHECK-NEXT:    [[IDXPROM5:%.*]] = sext i32 [[I_ADDR_0]] to i64
> +; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM5]]
> +; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX6]], align 4
> +; CHECK-NEXT:    ret i32 [[TMP2]]
> ;
> entry:
>   %cmp = icmp slt i32 %i, %N
> @@ -891,22 +884,20 @@ define i32 @test_phi_select_index_loop(ptr %A, i32 %N)  {
> ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 1
> ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
> ; CHECK:       for.body.preheader:
> -; CHECK-NEXT:    [[DOTPRE:%.*]] = load i32, ptr [[A:%.*]], align 4
> ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
> ; CHECK:       for.body:
> -; CHECK-NEXT:    [[TMP0:%.*]] = phi i32 [ [[TMP2:%.*]], [[FOR_BODY]] ], [ [[DOTPRE]], [[FOR_BODY_PREHEADER]] ]
> ; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[FOR_BODY]] ], [ 1, [[FOR_BODY_PREHEADER]] ]
> ; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[SPEC_SELECT:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
> ; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64
> -; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM]]
> -; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
> +; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM]]
> +; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
> ; CHECK-NEXT:    [[IDXPROM1:%.*]] = sext i32 [[RES]] to i64
> ; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM1]]
> -; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[TMP1]], [[TMP0]]
> +; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX1]], align 4
> +; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[TMP0]], [[TMP1]]
> ; CHECK-NEXT:    [[SPEC_SELECT]] = select i1 [[CMP1]], i32 [[IDX]], i32 [[RES]]
> ; CHECK-NEXT:    [[IDX_NEXT]] = add nsw i32 [[IDX]], 1
> ; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IDX_NEXT]], [[N]]
> -; CHECK-NEXT:    [[TMP2]] = select i1 [[CMP1]], i32 [[TMP1]], i32 [[TMP0]]
> ; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]]
> ; CHECK:       for.cond.cleanup.loopexit:
> ; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
> 
> diff  --git a/llvm/test/Transforms/GVN/PRE/pre-loop-load-through-select.ll b/llvm/test/Transforms/GVN/PRE/pre-loop-load-through-select.ll
> index 0803968a96e9b..dc128a4b1e631 100644
> --- a/llvm/test/Transforms/GVN/PRE/pre-loop-load-through-select.ll
> +++ b/llvm/test/Transforms/GVN/PRE/pre-loop-load-through-select.ll
> @@ -13,10 +13,10 @@ define i32 @test_pointer_phi_select_same_object(ptr %ptr, ptr %end)  {
> ; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
> ; CHECK:       exit:
> ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
> @@ -54,10 +54,10 @@ define i32 @test_pointer_phi_select_same_object_lcssa(ptr %ptr, ptr %end)  {
> ; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
> ; CHECK:       exit:
> ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
> @@ -95,10 +95,10 @@ define i32 @test_pointer_phi_select_
> diff erent_objects(ptr %A, ptr %B, ptr %end)
> ; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[B]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
> ; CHECK:       exit:
> ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
> @@ -130,15 +130,15 @@ define i32 @test_pointer_phi_select_same_object_multiple_loads_1(ptr %ptr, ptr %
> ; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
> ; CHECK-NEXT:    br label [[LOOP:%.*]]
> ; CHECK:       loop:
> -; CHECK-NEXT:    [[L_3:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
> +; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> -; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_3]]
> +; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_3]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
> ; CHECK:       exit:
> ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
> @@ -177,10 +177,10 @@ define i32 @test_pointer_phi_select_same_object_multiple_loads_2(ptr %ptr, ptr %
> ; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
> ; CHECK:       exit:
> ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
> @@ -260,10 +260,10 @@ define i32 @test_pointer_phi_select_same_object_split_edge(ptr %ptr, ptr %end, i
> ; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[MIN_SELECT:%.*]], [[LOOP]] ], [ [[PTR]], [[LOOP_PREHEADER]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[LOOP_EXIT:%.*]], label [[LOOP]]
> ; CHECK:       loop.exit:
> ; CHECK-NEXT:    br label [[EXIT]]
> @@ -311,10 +311,10 @@ define i32 @test_pointer_phi_select_load_may_not_execute_1(ptr %A, ptr %B, ptr %
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
> ; CHECK:       exit:
> ; CHECK-NEXT:    ret i32 [[TMP0]]
> @@ -350,10 +350,10 @@ define i32 @test_pointer_phi_select_load_may_not_execute_2(ptr %A, ptr %B, ptr %
> ; CHECK-NEXT:    call void @may_throw()
> ; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
> ; CHECK:       exit:
> ; CHECK-NEXT:    ret i32 [[TMP0]]
> @@ -514,10 +514,10 @@ define i32 @test_pointer_phi_select_same_object_may_write_call_1(ptr %ptr, ptr %
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[L_2:%.*]] = load i32, ptr [[MIN_PTR]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
> ; CHECK:       exit:
> ; CHECK-NEXT:    ret i32 [[TMP0]]
> @@ -681,10 +681,10 @@ define i32 @test_pointer_phi_select_same_object_ptr_use_cycle(ptr %ptr, ptr %end
> ; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT_PREHEADER:%.*]], label [[LOOP]]
> ; CHECK:       exit.preheader:
> ; CHECK-NEXT:    br label [[EXIT:%.*]]
> @@ -728,10 +728,10 @@ define i32 @test_pointer_phi_select_same_object_maybe_clobbered_in_exit(ptr %ptr
> ; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
> ; CHECK:       exit:
> ; CHECK-NEXT:    store i32 0, ptr [[START_PTR]], align 4
> @@ -771,10 +771,10 @@ define i32 @test_pointer_phi_select_same_object_maybe_clobbered_in_exit_2(ptr %p
> ; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT_1:%.*]], label [[LOOP]]
> ; CHECK:       exit.1:
> ; CHECK-NEXT:    store i32 0, ptr [[START_PTR]], align 4
> @@ -820,10 +820,10 @@ define i32 @test_pointer_phi_select_same_object_invoke_in_chain(ptr %ptr, ptr %e
> ; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i64 1
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT_1:%.*]], label [[LOOP]]
> ; CHECK:       exit.1:
> ; CHECK-NEXT:    store i32 0, ptr [[START_PTR]], align 4
> @@ -916,16 +916,20 @@ define i32 @test_pointer_phi_used_by_others_in_loop_1(ptr %ptr, ptr %end)  {
> ; CHECK-NEXT:    [[L_2_PRE:%.*]] = load i32, ptr [[PTR]], align 4
> ; CHECK-NEXT:    br label [[LOOP:%.*]]
> ; CHECK:       loop:
> -; CHECK-NEXT:    [[L_3:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
> -; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
> -; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
> +; CHECK-NEXT:    [[L_3:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[L_3_PRE:%.*]], [[LOOP_LOOP_CRIT_EDGE:%.*]] ]
> +; CHECK-NEXT:    [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY]] ], [ [[TMP0:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ]
> +; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ]
> +; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> -; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_3]]
> +; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i32 [[L_3]]
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_3]]
> -; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
> +; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_LOOP_CRIT_EDGE]]
> +; CHECK:       loop.loop_crit_edge:
> +; CHECK-NEXT:    [[L_3_PRE]] = load i32, ptr [[MIN_SELECT]], align 4
> +; CHECK-NEXT:    br label [[LOOP]]
> ; CHECK:       exit:
> ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
> ; CHECK-NEXT:    ret i32 [[RES]]
> @@ -963,12 +967,12 @@ define i32 @test_pointer_phi_used_by_others_in_loop_2(ptr %ptr, ptr %end)  {
> ; CHECK-NEXT:    [[MIN_PTR:%.*]] = phi ptr [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
> ; CHECK-NEXT:    [[L_1:%.*]] = load i32, ptr [[PTR_IV]], align 4
> ; CHECK-NEXT:    [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
> +; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], ptr [[PTR_IV]], ptr [[MIN_PTR]]
> ; CHECK-NEXT:    [[GEP_MIN_PTR:%.*]] = getelementptr inbounds i32, ptr [[MIN_PTR]], i32 1
> ; CHECK-NEXT:    [[L_3:%.*]] = load i32, ptr [[GEP_MIN_PTR]], align 4
> ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i32 [[L_3]]
> ; CHECK-NEXT:    [[EC:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END:%.*]]
> -; CHECK-NEXT:    [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
> ; CHECK-NEXT:    br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
> ; CHECK:       exit:
> ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[MIN_SELECT]], align 4
> 
> diff  --git a/llvm/test/Transforms/GVN/opaque-ptr.ll b/llvm/test/Transforms/GVN/opaque-ptr.ll
> index ca75b608c19b4..b9f6f6dd5b405 100644
> --- a/llvm/test/Transforms/GVN/opaque-ptr.ll
> +++ b/llvm/test/Transforms/GVN/opaque-ptr.ll
> @@ -179,8 +179,8 @@ define i32 @select_pre(ptr %px, ptr %py) {
> ; CHECK-NEXT:    [[T2:%.*]] = load i32, ptr [[PY:%.*]], align 4
> ; CHECK-NEXT:    [[T3:%.*]] = load i32, ptr [[PX:%.*]], align 4
> ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[T2]], [[T3]]
> -; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], ptr [[PX]], ptr [[PY]]
> ; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[CMP]], i32 [[T3]], i32 [[T2]]
> +; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], ptr [[PX]], ptr [[PY]]
> ; CHECK-NEXT:    ret i32 [[TMP1]]
> ;
>   %t2 = load i32, ptr %py, align 4
> 
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list