From 6377c86d718232fe60c548dfd7ab439f7ff84df7 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Thu, 5 Feb 2026 09:56:18 -0800 Subject: [PATCH] Revert "[SLP]Remove LoadCombine workaround after handling of the copyables" This reverts commit 8dbb9f66e8b14a8a06f1873a2c1b7dce366ed2d6 to fix buildbot issues https://lab.llvm.org/buildbot/#/builders/224/builds/2795 --- .../Transforms/Vectorize/SLPVectorizer.cpp | 241 +++++----- .../PhaseOrdering/X86/loadcombine.ll | 216 ++++++++- .../SLPVectorizer/X86/bad-reduction.ll | 416 ++++++++++++++++-- .../X86/load-merge-inseltpoison.ll | 21 +- .../SLPVectorizer/X86/load-merge.ll | 21 +- 5 files changed, 715 insertions(+), 200 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index e7e5fa76427f..7575cfb25051 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -2100,16 +2100,12 @@ public: VectorizableTree.front()->getVectorFactor()); } - /// Returns true if the tree results in one of the reduced bitcasts variants. + /// Returns the opcode of the root node, or 0, if the root node is gather. bool isReducedBitcastRoot() const { return VectorizableTree.front()->hasState() && (VectorizableTree.front()->CombinedOp == TreeEntry::ReducedBitcast || VectorizableTree.front()->CombinedOp == - TreeEntry::ReducedBitcastBSwap || - VectorizableTree.front()->CombinedOp == - TreeEntry::ReducedBitcastLoads || - VectorizableTree.front()->CombinedOp == - TreeEntry::ReducedBitcastBSwapLoads) && + TreeEntry::ReducedBitcastBSwap) && VectorizableTree.front()->State == TreeEntry::Vectorize; } @@ -2274,6 +2270,23 @@ public: /// effectively than the base graph. bool isTreeNotExtendable() const; + /// Assume that a legal-sized 'or'-reduction of shifted/zexted loaded values + /// can be load combined in the backend. Load combining may not be allowed in + /// the IR optimizer, so we do not want to alter the pattern. For example, + /// partially transforming a scalar bswap() pattern into vector code is + /// effectively impossible for the backend to undo. + /// TODO: If load combining is allowed in the IR optimizer, this analysis + /// may not be necessary. + bool isLoadCombineReductionCandidate(RecurKind RdxKind) const; + + /// Assume that a vector of stores of bitwise-or/shifted/zexted loaded values + /// can be load combined in the backend. Load combining may not be allowed in + /// the IR optimizer, so we do not want to alter the pattern. For example, + /// partially transforming a scalar bswap() pattern into vector code is + /// effectively impossible for the backend to undo. + /// TODO: If load combining is allowed in the IR optimizer, this analysis + /// may not be necessary. + bool isLoadCombineCandidate(ArrayRef Stores) const; bool isStridedLoad(ArrayRef PointerOps, Type *ScalarTy, Align Alignment, const int64_t Diff, const size_t Sz) const; @@ -3919,9 +3932,8 @@ private: /// .., 56))-like pattern. /// If the int shifts unique, also strided, but not ordered, sets \p Order. /// If the node can be represented as a bitcast + bswap, sets \p IsBSwap. - /// If the root nodes are loads, sets \p ForLoads to true. - bool matchesShlZExt(const TreeEntry &TE, OrdersType &Order, bool &IsBSwap, - bool &ForLoads) const; + bool matchesShlZExt(const TreeEntry &TE, OrdersType &Order, + bool &IsBSwap) const; class TreeEntry { public: @@ -4054,8 +4066,6 @@ private: FMulAdd, ReducedBitcast, ReducedBitcastBSwap, - ReducedBitcastLoads, - ReducedBitcastBSwapLoads, }; CombinedOpcode CombinedOp = NotCombinedOp; @@ -13343,11 +13353,10 @@ static InstructionCost canConvertToFMA(ArrayRef VL, } bool BoUpSLP::matchesShlZExt(const TreeEntry &TE, OrdersType &Order, - bool &IsBSwap, bool &ForLoads) const { + bool &IsBSwap) const { assert(TE.hasState() && TE.getOpcode() == Instruction::Shl && "Expected Shl node."); IsBSwap = false; - ForLoads = false; if (TE.State != TreeEntry::Vectorize || !TE.ReorderIndices.empty() || !TE.ReuseShuffleIndices.empty() || MinBWs.contains(&TE) || any_of(TE.Scalars, [](Value *V) { return !V->hasOneUse(); })) @@ -13454,44 +13463,6 @@ bool BoUpSLP::matchesShlZExt(const TreeEntry &TE, OrdersType &Order, if (BSwapCost <= BitcastCost) { BitcastCost = BSwapCost; IsBSwap = true; - Order.clear(); - // Check for loads in the ZExt node. - const TreeEntry *SrcTE = getOperandEntry(LhsTE, /*Idx=*/0); - if (SrcTE->State == TreeEntry::Vectorize && - SrcTE->ReorderIndices.empty() && SrcTE->ReuseShuffleIndices.empty() && - SrcTE->getOpcode() == Instruction::Load && !SrcTE->isAltShuffle() && - all_of(SrcTE->Scalars, [](Value *V) { return V->hasOneUse(); })) { - auto *LI = cast(SrcTE->getMainOp()); - IntrinsicCostAttributes CostAttrs(Intrinsic::bswap, ScalarTy, - {ScalarTy}); - InstructionCost BSwapCost = - TTI->getMemoryOpCost(Instruction::Load, ScalarTy, LI->getAlign(), - LI->getPointerAddressSpace(), CostKind) + - TTI->getIntrinsicInstrCost(CostAttrs, CostKind); - if (BSwapCost <= BitcastCost) { - VecCost += - TTI->getMemoryOpCost(Instruction::Load, SrcVecTy, LI->getAlign(), - LI->getPointerAddressSpace(), CostKind); - BitcastCost = BSwapCost; - ForLoads = true; - } - } - } - } else if (Order.empty() && DL->getTypeSizeInBits(SrcScalarTy) == ByteSize) { - // Check for loads in the ZExt node. - const TreeEntry *SrcTE = getOperandEntry(LhsTE, /*Idx=*/0); - if (SrcTE->State == TreeEntry::Vectorize && SrcTE->ReorderIndices.empty() && - SrcTE->ReuseShuffleIndices.empty() && - SrcTE->getOpcode() == Instruction::Load && !SrcTE->isAltShuffle() && - all_of(SrcTE->Scalars, [](Value *V) { return V->hasOneUse(); })) { - auto *LI = cast(SrcTE->getMainOp()); - BitcastCost = - TTI->getMemoryOpCost(Instruction::Load, ScalarTy, LI->getAlign(), - LI->getPointerAddressSpace(), CostKind); - VecCost += - TTI->getMemoryOpCost(Instruction::Load, SrcVecTy, LI->getAlign(), - LI->getPointerAddressSpace(), CostKind); - ForLoads = true; } } return BitcastCost < VecCost; @@ -13913,17 +13884,14 @@ void BoUpSLP::transformNodes() { break; OrdersType Order; bool IsBSwap; - bool ForLoads; - if (!matchesShlZExt(E, Order, IsBSwap, ForLoads)) + if (!matchesShlZExt(E, Order, IsBSwap)) break; // This node is a (reduced disjoint or) bitcast node. TreeEntry::CombinedOpcode Code = - IsBSwap ? (ForLoads ? TreeEntry::ReducedBitcastBSwapLoads - : TreeEntry::ReducedBitcastBSwap) - : (ForLoads ? TreeEntry::ReducedBitcastLoads - : TreeEntry::ReducedBitcast); + IsBSwap ? TreeEntry::ReducedBitcastBSwap : TreeEntry::ReducedBitcast; E.CombinedOp = Code; - E.ReorderIndices = std::move(Order); + if (!IsBSwap) + E.ReorderIndices = std::move(Order); TreeEntry *ZExtEntry = getOperandEntry(&E, 0); assert(ZExtEntry->UserTreeIndex && ZExtEntry->State == TreeEntry::Vectorize && @@ -13932,16 +13900,6 @@ void BoUpSLP::transformNodes() { // The ZExt node is part of the combined node. ZExtEntry->State = TreeEntry::CombinedVectorize; ZExtEntry->CombinedOp = Code; - if (ForLoads) { - TreeEntry *LoadsEntry = getOperandEntry(ZExtEntry, 0); - assert(LoadsEntry->UserTreeIndex && - LoadsEntry->State == TreeEntry::Vectorize && - LoadsEntry->getOpcode() == Instruction::Load && - "Expected Load node."); - // The Load node is part of the combined node. - LoadsEntry->State = TreeEntry::CombinedVectorize; - LoadsEntry->CombinedOp = Code; - } TreeEntry *ConstEntry = getOperandEntry(&E, 1); assert(ConstEntry->UserTreeIndex && ConstEntry->isGather() && "Expected ZExt node."); @@ -15601,44 +15559,6 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, }; return GetCostDiff(GetScalarCost, GetVectorCost); } - case TreeEntry::ReducedBitcastLoads: - case TreeEntry::ReducedBitcastBSwapLoads: { - auto GetScalarCost = [&, &TTI = *TTI](unsigned Idx) { - if (isa(UniqueValues[Idx])) - return InstructionCost(TTI::TCC_Free); - auto *Shl = dyn_cast(UniqueValues[Idx]); - if (!Shl) - return InstructionCost(TTI::TCC_Free); - InstructionCost ScalarCost = TTI.getInstructionCost(Shl, CostKind); - auto *ZExt = dyn_cast(Shl->getOperand(0)); - if (!ZExt) - return ScalarCost; - ScalarCost += TTI.getInstructionCost(ZExt, CostKind); - auto *Load = dyn_cast(ZExt->getOperand(0)); - if (!Load) - return ScalarCost; - ScalarCost += TTI.getInstructionCost(Load, CostKind); - return ScalarCost; - }; - auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) { - const TreeEntry *LhsTE = getOperandEntry(E, /*Idx=*/0); - const TreeEntry *LoadTE = getOperandEntry(LhsTE, /*Idx=*/0); - auto *LI0 = cast(LoadTE->getMainOp()); - auto *OrigScalarTy = E->getMainOp()->getType(); - InstructionCost LoadCost = - TTI.getMemoryOpCost(Instruction::Load, OrigScalarTy, LI0->getAlign(), - LI0->getPointerAddressSpace(), CostKind); - if (ShuffleOrOp == TreeEntry::ReducedBitcastBSwapLoads) { - IntrinsicCostAttributes CostAttrs(Intrinsic::bswap, OrigScalarTy, - {OrigScalarTy}); - InstructionCost IntrinsicCost = - TTI.getIntrinsicInstrCost(CostAttrs, CostKind); - LoadCost += IntrinsicCost; - } - return LoadCost + CommonCost; - }; - return GetCostDiff(GetScalarCost, GetVectorCost); - } case Instruction::FNeg: case Instruction::Add: case Instruction::FAdd: @@ -16123,6 +16043,69 @@ bool BoUpSLP::isFullyVectorizableTinyTree(bool ForReduction) const { return true; } +static bool isLoadCombineCandidateImpl(Value *Root, unsigned NumElts, + TargetTransformInfo *TTI, + bool MustMatchOrInst) { + // Look past the root to find a source value. Arbitrarily follow the + // path through operand 0 of any 'or'. Also, peek through optional + // shift-left-by-multiple-of-8-bits. + Value *ZextLoad = Root; + const APInt *ShAmtC; + bool FoundOr = false; + while (!isa(ZextLoad) && + (match(ZextLoad, m_Or(m_Value(), m_Value())) || + (match(ZextLoad, m_Shl(m_Value(), m_APInt(ShAmtC))) && + ShAmtC->urem(8) == 0))) { + auto *BinOp = cast(ZextLoad); + ZextLoad = BinOp->getOperand(0); + if (BinOp->getOpcode() == Instruction::Or) + FoundOr = true; + } + // Check if the input is an extended load of the required or/shift expression. + Value *Load; + if ((MustMatchOrInst && !FoundOr) || ZextLoad == Root || + !match(ZextLoad, m_ZExt(m_Value(Load))) || !isa(Load)) + return false; + + // Require that the total load bit width is a legal integer type. + // For example, <8 x i8> --> i64 is a legal integer on a 64-bit target. + // But <16 x i8> --> i128 is not, so the backend probably can't reduce it. + Type *SrcTy = Load->getType(); + unsigned LoadBitWidth = SrcTy->getIntegerBitWidth() * NumElts; + if (!TTI->isTypeLegal(IntegerType::get(Root->getContext(), LoadBitWidth))) + return false; + + // Everything matched - assume that we can fold the whole sequence using + // load combining. + LLVM_DEBUG(dbgs() << "SLP: Assume load combining for tree starting at " + << *(cast(Root)) << "\n"); + + return true; +} + +bool BoUpSLP::isLoadCombineReductionCandidate(RecurKind RdxKind) const { + if (RdxKind != RecurKind::Or) + return false; + + unsigned NumElts = VectorizableTree[0]->Scalars.size(); + Value *FirstReduced = VectorizableTree[0]->Scalars[0]; + return isLoadCombineCandidateImpl(FirstReduced, NumElts, TTI, + /* MatchOr */ false); +} + +bool BoUpSLP::isLoadCombineCandidate(ArrayRef Stores) const { + // Peek through a final sequence of stores and check if all operations are + // likely to be load-combined. + unsigned NumElts = Stores.size(); + for (Value *Scalar : Stores) { + Value *X; + if (!match(Scalar, m_Store(m_Value(X), m_Value())) || + !isLoadCombineCandidateImpl(X, NumElts, TTI, /* MatchOr */ true)) + return false; + } + return true; +} + bool BoUpSLP::isTreeTinyAndNotFullyVectorizable(bool ForReduction) const { if (!DebugCounter::shouldExecute(VectorizedGraphs)) return true; @@ -16351,9 +16334,7 @@ InstructionCost BoUpSLP::getSpillCost() { SmallPtrSet ScalarOrPseudoEntries; for (const auto &TEPtr : VectorizableTree) { if (TEPtr->CombinedOp == TreeEntry::ReducedBitcast || - TEPtr->CombinedOp == TreeEntry::ReducedBitcastBSwap || - TEPtr->CombinedOp == TreeEntry::ReducedBitcastLoads || - TEPtr->CombinedOp == TreeEntry::ReducedBitcastBSwapLoads) { + TEPtr->CombinedOp == TreeEntry::ReducedBitcastBSwap) { ScalarOrPseudoEntries.insert(TEPtr.get()); continue; } @@ -20288,8 +20269,6 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) { switch (E->CombinedOp) { case TreeEntry::ReducedBitcast: case TreeEntry::ReducedBitcastBSwap: - case TreeEntry::ReducedBitcastLoads: - case TreeEntry::ReducedBitcastBSwapLoads: ShuffleOrOp = E->CombinedOp; break; default: @@ -21257,31 +21236,6 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) { ++NumVectorInstructions; return V; } - case TreeEntry::ReducedBitcastLoads: - case TreeEntry::ReducedBitcastBSwapLoads: { - assert(UserIgnoreList && "Expected reduction operations only."); - setInsertPointAfterBundle(E); - TreeEntry *ZExt = getOperandEntry(E, /*Idx=*/0); - ZExt->VectorizedValue = PoisonValue::get(getWidenedType( - ZExt->getMainOp()->getType(), ZExt->getVectorFactor())); - TreeEntry *Const = getOperandEntry(E, /*Idx=*/1); - Const->VectorizedValue = PoisonValue::get(getWidenedType( - Const->Scalars.front()->getType(), Const->getVectorFactor())); - TreeEntry *Load = getOperandEntry(ZExt, /*Idx=*/0); - Load->VectorizedValue = PoisonValue::get(getWidenedType( - Load->getMainOp()->getType(), Load->getVectorFactor())); - LoadInst *LI = cast(Load->getMainOp()); - Value *PO = LI->getPointerOperand(); - Type *ScalarTy = ZExt->getMainOp()->getType(); - Value *V = Builder.CreateAlignedLoad(ScalarTy, PO, LI->getAlign()); - ++NumVectorInstructions; - if (ShuffleOrOp == TreeEntry::ReducedBitcastBSwapLoads) { - V = Builder.CreateUnaryIntrinsic(Intrinsic::bswap, V); - ++NumVectorInstructions; - } - E->VectorizedValue = V; - return V; - } default: llvm_unreachable("unknown inst"); } @@ -21309,9 +21263,7 @@ Value *BoUpSLP::vectorizeTree( if (TE->isGather() || DeletedNodes.contains(TE.get()) || (TE->State == TreeEntry::CombinedVectorize && (TE->CombinedOp == TreeEntry::ReducedBitcast || - TE->CombinedOp == TreeEntry::ReducedBitcastBSwap || - TE->CombinedOp == TreeEntry::ReducedBitcastLoads || - TE->CombinedOp == TreeEntry::ReducedBitcastBSwapLoads))) + TE->CombinedOp == TreeEntry::ReducedBitcastBSwap))) continue; (void)getLastInstructionInBundle(TE.get()); } @@ -21870,9 +21822,7 @@ Value *BoUpSLP::vectorizeTree( continue; if (Entry->CombinedOp == TreeEntry::ReducedBitcast || - Entry->CombinedOp == TreeEntry::ReducedBitcastBSwap || - Entry->CombinedOp == TreeEntry::ReducedBitcastLoads || - Entry->CombinedOp == TreeEntry::ReducedBitcastBSwapLoads) { + Entry->CombinedOp == TreeEntry::ReducedBitcastBSwap) { // Skip constant node if (!Entry->hasState()) { assert(allConstant(Entry->Scalars) && "Expected constants only."); @@ -24188,6 +24138,8 @@ SLPVectorizerPass::vectorizeStoreChain(ArrayRef Chain, BoUpSLP &R, return false; } } + if (R.isLoadCombineCandidate(Chain)) + return true; R.buildTree(Chain); // Check if tree tiny and store itself or its value is not vectorized. if (R.isTreeTinyAndNotFullyVectorizable()) { @@ -25792,6 +25744,11 @@ public: V.analyzedReductionVals(VL); continue; } + if (V.isLoadCombineReductionCandidate(RdxKind)) { + if (!AdjustReducedVals()) + V.analyzedReductionVals(VL); + continue; + } V.reorderTopToBottom(); // No need to reorder the root node at all for reassociative reduction. V.reorderBottomToTop(/*IgnoreReorder=*/RdxFMF.allowReassoc() || diff --git a/llvm/test/Transforms/PhaseOrdering/X86/loadcombine.ll b/llvm/test/Transforms/PhaseOrdering/X86/loadcombine.ll index ab15f8663ffc..fe49ba9d61d9 100644 --- a/llvm/test/Transforms/PhaseOrdering/X86/loadcombine.ll +++ b/llvm/test/Transforms/PhaseOrdering/X86/loadcombine.ll @@ -70,7 +70,23 @@ define i32 @loadCombine_4consecutive_1243(ptr %p) { define i32 @loadCombine_4consecutive_1324(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_1324( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 @@ -98,7 +114,23 @@ define i32 @loadCombine_4consecutive_1324(ptr %p) { define i32 @loadCombine_4consecutive_1342(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_1342( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 @@ -126,7 +158,23 @@ define i32 @loadCombine_4consecutive_1342(ptr %p) { define i32 @loadCombine_4consecutive_1423(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_1423( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 @@ -154,7 +202,23 @@ define i32 @loadCombine_4consecutive_1423(ptr %p) { define i32 @loadCombine_4consecutive_1432(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_1432( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 @@ -305,7 +369,23 @@ define i32 @loadCombine_4consecutive_2341(ptr %p) { define i32 @loadCombine_4consecutive_2413(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_2413( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 @@ -333,7 +413,23 @@ define i32 @loadCombine_4consecutive_2413(ptr %p) { define i32 @loadCombine_4consecutive_2431(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_2431( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 @@ -361,7 +457,23 @@ define i32 @loadCombine_4consecutive_2431(ptr %p) { define i32 @loadCombine_4consecutive_3124(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_3124( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 @@ -389,7 +501,23 @@ define i32 @loadCombine_4consecutive_3124(ptr %p) { define i32 @loadCombine_4consecutive_3142(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_3142( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 @@ -540,7 +668,23 @@ define i32 @loadCombine_4consecutive_3421(ptr %p) { define i32 @loadCombine_4consecutive_4123(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_4123( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 @@ -568,7 +712,23 @@ define i32 @loadCombine_4consecutive_4123(ptr %p) { define i32 @loadCombine_4consecutive_4132(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_4132( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 @@ -596,7 +756,23 @@ define i32 @loadCombine_4consecutive_4132(ptr %p) { define i32 @loadCombine_4consecutive_4213(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_4213( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 @@ -624,7 +800,23 @@ define i32 @loadCombine_4consecutive_4213(ptr %p) { define i32 @loadCombine_4consecutive_4231(ptr %p) { ; CHECK-LABEL: @loadCombine_4consecutive_4231( -; CHECK-NEXT: [[O3:%.*]] = load i32, ptr [[P:%.*]], align 1 +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i64 2 +; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[P]], i64 3 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr [[P1]], align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[L4:%.*]] = load i8, ptr [[P3]], align 1 +; CHECK-NEXT: [[E1:%.*]] = zext i8 [[L1]] to i32 +; CHECK-NEXT: [[E2:%.*]] = zext i8 [[L2]] to i32 +; CHECK-NEXT: [[E3:%.*]] = zext i8 [[L3]] to i32 +; CHECK-NEXT: [[E4:%.*]] = zext i8 [[L4]] to i32 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i32 [[E2]], 8 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i32 [[E3]], 16 +; CHECK-NEXT: [[S4:%.*]] = shl nuw i32 [[E4]], 24 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i32 [[S2]], [[E1]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i32 [[O1]], [[S3]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i32 [[O2]], [[S4]] ; CHECK-NEXT: ret i32 [[O3]] ; %p1 = getelementptr i8, ptr %p, i32 1 diff --git a/llvm/test/Transforms/SLPVectorizer/X86/bad-reduction.ll b/llvm/test/Transforms/SLPVectorizer/X86/bad-reduction.ll index 70ef8fdf21d5..dc370bd3055d 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/bad-reduction.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/bad-reduction.ll @@ -7,10 +7,43 @@ define i64 @load_bswap(ptr %p) { ; CHECK-LABEL: @load_bswap( -; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i8>, ptr [[P:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext <8 x i8> [[TMP1]] to <8 x i64> -; CHECK-NEXT: [[TMP3:%.*]] = shl nuw <8 x i64> [[TMP2]], -; CHECK-NEXT: [[OR01234567:%.*]] = call i64 @llvm.vector.reduce.or.v8i64(<8 x i64> [[TMP3]]) +; CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [[V8I8:%.*]], ptr [[P:%.*]], i64 0, i32 1 +; CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 2 +; CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 3 +; CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 4 +; CHECK-NEXT: [[G5:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 5 +; CHECK-NEXT: [[G6:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 6 +; CHECK-NEXT: [[G7:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 7 +; CHECK-NEXT: [[T0:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[T1:%.*]] = load i8, ptr [[G1]], align 1 +; CHECK-NEXT: [[T2:%.*]] = load i8, ptr [[G2]], align 1 +; CHECK-NEXT: [[T3:%.*]] = load i8, ptr [[G3]], align 1 +; CHECK-NEXT: [[T4:%.*]] = load i8, ptr [[G4]], align 1 +; CHECK-NEXT: [[T5:%.*]] = load i8, ptr [[G5]], align 1 +; CHECK-NEXT: [[T6:%.*]] = load i8, ptr [[G6]], align 1 +; CHECK-NEXT: [[T7:%.*]] = load i8, ptr [[G7]], align 1 +; CHECK-NEXT: [[Z0:%.*]] = zext i8 [[T0]] to i64 +; CHECK-NEXT: [[Z1:%.*]] = zext i8 [[T1]] to i64 +; CHECK-NEXT: [[Z2:%.*]] = zext i8 [[T2]] to i64 +; CHECK-NEXT: [[Z3:%.*]] = zext i8 [[T3]] to i64 +; CHECK-NEXT: [[Z4:%.*]] = zext i8 [[T4]] to i64 +; CHECK-NEXT: [[Z5:%.*]] = zext i8 [[T5]] to i64 +; CHECK-NEXT: [[Z6:%.*]] = zext i8 [[T6]] to i64 +; CHECK-NEXT: [[Z7:%.*]] = zext i8 [[T7]] to i64 +; CHECK-NEXT: [[SH0:%.*]] = shl nuw i64 [[Z0]], 56 +; CHECK-NEXT: [[SH1:%.*]] = shl nuw nsw i64 [[Z1]], 48 +; CHECK-NEXT: [[SH2:%.*]] = shl nuw nsw i64 [[Z2]], 40 +; CHECK-NEXT: [[SH3:%.*]] = shl nuw nsw i64 [[Z3]], 32 +; CHECK-NEXT: [[SH4:%.*]] = shl nuw nsw i64 [[Z4]], 24 +; CHECK-NEXT: [[SH5:%.*]] = shl nuw nsw i64 [[Z5]], 16 +; CHECK-NEXT: [[SH6:%.*]] = shl nuw nsw i64 [[Z6]], 8 +; CHECK-NEXT: [[OR01:%.*]] = or i64 [[SH0]], [[SH1]] +; CHECK-NEXT: [[OR012:%.*]] = or i64 [[OR01]], [[SH2]] +; CHECK-NEXT: [[OR0123:%.*]] = or i64 [[OR012]], [[SH3]] +; CHECK-NEXT: [[OR01234:%.*]] = or i64 [[OR0123]], [[SH4]] +; CHECK-NEXT: [[OR012345:%.*]] = or i64 [[OR01234]], [[SH5]] +; CHECK-NEXT: [[OR0123456:%.*]] = or i64 [[OR012345]], [[SH6]] +; CHECK-NEXT: [[OR01234567:%.*]] = or i64 [[OR0123456]], [[Z7]] ; CHECK-NEXT: ret i64 [[OR01234567]] ; %g1 = getelementptr inbounds %v8i8, ptr %p, i64 0, i32 1 @@ -60,10 +93,44 @@ define i64 @load_bswap(ptr %p) { define i64 @load_bswap_nop_shift(ptr %p) { ; CHECK-LABEL: @load_bswap_nop_shift( -; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i8>, ptr [[P:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext <8 x i8> [[TMP1]] to <8 x i64> -; CHECK-NEXT: [[TMP3:%.*]] = shl nuw <8 x i64> [[TMP2]], -; CHECK-NEXT: [[OR01234567:%.*]] = call i64 @llvm.vector.reduce.or.v8i64(<8 x i64> [[TMP3]]) +; CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [[V8I8:%.*]], ptr [[P:%.*]], i64 0, i32 1 +; CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 2 +; CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 3 +; CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 4 +; CHECK-NEXT: [[G5:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 5 +; CHECK-NEXT: [[G6:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 6 +; CHECK-NEXT: [[G7:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 7 +; CHECK-NEXT: [[T0:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[T1:%.*]] = load i8, ptr [[G1]], align 1 +; CHECK-NEXT: [[T2:%.*]] = load i8, ptr [[G2]], align 1 +; CHECK-NEXT: [[T3:%.*]] = load i8, ptr [[G3]], align 1 +; CHECK-NEXT: [[T4:%.*]] = load i8, ptr [[G4]], align 1 +; CHECK-NEXT: [[T5:%.*]] = load i8, ptr [[G5]], align 1 +; CHECK-NEXT: [[T6:%.*]] = load i8, ptr [[G6]], align 1 +; CHECK-NEXT: [[T7:%.*]] = load i8, ptr [[G7]], align 1 +; CHECK-NEXT: [[Z0:%.*]] = zext i8 [[T0]] to i64 +; CHECK-NEXT: [[Z1:%.*]] = zext i8 [[T1]] to i64 +; CHECK-NEXT: [[Z2:%.*]] = zext i8 [[T2]] to i64 +; CHECK-NEXT: [[Z3:%.*]] = zext i8 [[T3]] to i64 +; CHECK-NEXT: [[Z4:%.*]] = zext i8 [[T4]] to i64 +; CHECK-NEXT: [[Z5:%.*]] = zext i8 [[T5]] to i64 +; CHECK-NEXT: [[Z6:%.*]] = zext i8 [[T6]] to i64 +; CHECK-NEXT: [[Z7:%.*]] = zext i8 [[T7]] to i64 +; CHECK-NEXT: [[SH0:%.*]] = shl nuw i64 [[Z0]], 56 +; CHECK-NEXT: [[SH1:%.*]] = shl nuw nsw i64 [[Z1]], 48 +; CHECK-NEXT: [[SH2:%.*]] = shl nuw nsw i64 [[Z2]], 40 +; CHECK-NEXT: [[SH3:%.*]] = shl nuw nsw i64 [[Z3]], 32 +; CHECK-NEXT: [[SH4:%.*]] = shl nuw nsw i64 [[Z4]], 24 +; CHECK-NEXT: [[SH5:%.*]] = shl nuw nsw i64 [[Z5]], 16 +; CHECK-NEXT: [[SH6:%.*]] = shl nuw nsw i64 [[Z6]], 8 +; CHECK-NEXT: [[SH7:%.*]] = shl nuw nsw i64 [[Z7]], 0 +; CHECK-NEXT: [[OR01:%.*]] = or i64 [[SH0]], [[SH1]] +; CHECK-NEXT: [[OR012:%.*]] = or i64 [[OR01]], [[SH2]] +; CHECK-NEXT: [[OR0123:%.*]] = or i64 [[OR012]], [[SH3]] +; CHECK-NEXT: [[OR01234:%.*]] = or i64 [[OR0123]], [[SH4]] +; CHECK-NEXT: [[OR012345:%.*]] = or i64 [[OR01234]], [[SH5]] +; CHECK-NEXT: [[OR0123456:%.*]] = or i64 [[OR012345]], [[SH6]] +; CHECK-NEXT: [[OR01234567:%.*]] = or i64 [[OR0123456]], [[SH7]] ; CHECK-NEXT: ret i64 [[OR01234567]] ; %g1 = getelementptr inbounds %v8i8, ptr %p, i64 0, i32 1 @@ -115,10 +182,43 @@ define i64 @load_bswap_nop_shift(ptr %p) { define i64 @load64le(ptr %arg) { ; CHECK-LABEL: @load64le( -; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i8>, ptr [[ARG:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext <8 x i8> [[TMP1]] to <8 x i64> -; CHECK-NEXT: [[TMP3:%.*]] = shl <8 x i64> [[TMP2]], -; CHECK-NEXT: [[O7:%.*]] = call i64 @llvm.vector.reduce.or.v8i64(<8 x i64> [[TMP3]]) +; CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1 +; CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 2 +; CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 3 +; CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 4 +; CHECK-NEXT: [[G5:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 5 +; CHECK-NEXT: [[G6:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 6 +; CHECK-NEXT: [[G7:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 7 +; CHECK-NEXT: [[LD0:%.*]] = load i8, ptr [[ARG]], align 1 +; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[G1]], align 1 +; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[G2]], align 1 +; CHECK-NEXT: [[LD3:%.*]] = load i8, ptr [[G3]], align 1 +; CHECK-NEXT: [[LD4:%.*]] = load i8, ptr [[G4]], align 1 +; CHECK-NEXT: [[LD5:%.*]] = load i8, ptr [[G5]], align 1 +; CHECK-NEXT: [[LD6:%.*]] = load i8, ptr [[G6]], align 1 +; CHECK-NEXT: [[LD7:%.*]] = load i8, ptr [[G7]], align 1 +; CHECK-NEXT: [[Z0:%.*]] = zext i8 [[LD0]] to i64 +; CHECK-NEXT: [[Z1:%.*]] = zext i8 [[LD1]] to i64 +; CHECK-NEXT: [[Z2:%.*]] = zext i8 [[LD2]] to i64 +; CHECK-NEXT: [[Z3:%.*]] = zext i8 [[LD3]] to i64 +; CHECK-NEXT: [[Z4:%.*]] = zext i8 [[LD4]] to i64 +; CHECK-NEXT: [[Z5:%.*]] = zext i8 [[LD5]] to i64 +; CHECK-NEXT: [[Z6:%.*]] = zext i8 [[LD6]] to i64 +; CHECK-NEXT: [[Z7:%.*]] = zext i8 [[LD7]] to i64 +; CHECK-NEXT: [[S1:%.*]] = shl nuw nsw i64 [[Z1]], 8 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i64 [[Z2]], 16 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i64 [[Z3]], 24 +; CHECK-NEXT: [[S4:%.*]] = shl nuw nsw i64 [[Z4]], 32 +; CHECK-NEXT: [[S5:%.*]] = shl nuw nsw i64 [[Z5]], 40 +; CHECK-NEXT: [[S6:%.*]] = shl nuw nsw i64 [[Z6]], 48 +; CHECK-NEXT: [[S7:%.*]] = shl nuw i64 [[Z7]], 56 +; CHECK-NEXT: [[O1:%.*]] = or i64 [[S1]], [[Z0]] +; CHECK-NEXT: [[O2:%.*]] = or i64 [[O1]], [[S2]] +; CHECK-NEXT: [[O3:%.*]] = or i64 [[O2]], [[S3]] +; CHECK-NEXT: [[O4:%.*]] = or i64 [[O3]], [[S4]] +; CHECK-NEXT: [[O5:%.*]] = or i64 [[O4]], [[S5]] +; CHECK-NEXT: [[O6:%.*]] = or i64 [[O5]], [[S6]] +; CHECK-NEXT: [[O7:%.*]] = or i64 [[O6]], [[S7]] ; CHECK-NEXT: ret i64 [[O7]] ; %g1 = getelementptr inbounds i8, ptr %arg, i64 1 @@ -168,10 +268,44 @@ define i64 @load64le(ptr %arg) { define i64 @load64le_nop_shift(ptr %arg) { ; CHECK-LABEL: @load64le_nop_shift( -; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i8>, ptr [[ARG:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext <8 x i8> [[TMP1]] to <8 x i64> -; CHECK-NEXT: [[TMP3:%.*]] = shl nuw <8 x i64> [[TMP2]], -; CHECK-NEXT: [[O7:%.*]] = call i64 @llvm.vector.reduce.or.v8i64(<8 x i64> [[TMP3]]) +; CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1 +; CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 2 +; CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 3 +; CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 4 +; CHECK-NEXT: [[G5:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 5 +; CHECK-NEXT: [[G6:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 6 +; CHECK-NEXT: [[G7:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 7 +; CHECK-NEXT: [[LD0:%.*]] = load i8, ptr [[ARG]], align 1 +; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[G1]], align 1 +; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[G2]], align 1 +; CHECK-NEXT: [[LD3:%.*]] = load i8, ptr [[G3]], align 1 +; CHECK-NEXT: [[LD4:%.*]] = load i8, ptr [[G4]], align 1 +; CHECK-NEXT: [[LD5:%.*]] = load i8, ptr [[G5]], align 1 +; CHECK-NEXT: [[LD6:%.*]] = load i8, ptr [[G6]], align 1 +; CHECK-NEXT: [[LD7:%.*]] = load i8, ptr [[G7]], align 1 +; CHECK-NEXT: [[Z0:%.*]] = zext i8 [[LD0]] to i64 +; CHECK-NEXT: [[Z1:%.*]] = zext i8 [[LD1]] to i64 +; CHECK-NEXT: [[Z2:%.*]] = zext i8 [[LD2]] to i64 +; CHECK-NEXT: [[Z3:%.*]] = zext i8 [[LD3]] to i64 +; CHECK-NEXT: [[Z4:%.*]] = zext i8 [[LD4]] to i64 +; CHECK-NEXT: [[Z5:%.*]] = zext i8 [[LD5]] to i64 +; CHECK-NEXT: [[Z6:%.*]] = zext i8 [[LD6]] to i64 +; CHECK-NEXT: [[Z7:%.*]] = zext i8 [[LD7]] to i64 +; CHECK-NEXT: [[S0:%.*]] = shl nuw nsw i64 [[Z0]], 0 +; CHECK-NEXT: [[S1:%.*]] = shl nuw nsw i64 [[Z1]], 8 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i64 [[Z2]], 16 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i64 [[Z3]], 24 +; CHECK-NEXT: [[S4:%.*]] = shl nuw nsw i64 [[Z4]], 32 +; CHECK-NEXT: [[S5:%.*]] = shl nuw nsw i64 [[Z5]], 40 +; CHECK-NEXT: [[S6:%.*]] = shl nuw nsw i64 [[Z6]], 48 +; CHECK-NEXT: [[S7:%.*]] = shl nuw i64 [[Z7]], 56 +; CHECK-NEXT: [[O1:%.*]] = or i64 [[S1]], [[S0]] +; CHECK-NEXT: [[O2:%.*]] = or i64 [[O1]], [[S2]] +; CHECK-NEXT: [[O3:%.*]] = or i64 [[O2]], [[S3]] +; CHECK-NEXT: [[O4:%.*]] = or i64 [[O3]], [[S4]] +; CHECK-NEXT: [[O5:%.*]] = or i64 [[O4]], [[S5]] +; CHECK-NEXT: [[O6:%.*]] = or i64 [[O5]], [[S6]] +; CHECK-NEXT: [[O7:%.*]] = or i64 [[O6]], [[S7]] ; CHECK-NEXT: ret i64 [[O7]] ; %g1 = getelementptr inbounds i8, ptr %arg, i64 1 @@ -221,8 +355,43 @@ define i64 @load64le_nop_shift(ptr %arg) { define i64 @load_bswap_disjoint(ptr %p) { ; CHECK-LABEL: @load_bswap_disjoint( -; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[P:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.bswap.i64(i64 [[TMP1]]) +; CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [[V8I8:%.*]], ptr [[P:%.*]], i64 0, i32 1 +; CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 2 +; CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 3 +; CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 4 +; CHECK-NEXT: [[G5:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 5 +; CHECK-NEXT: [[G6:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 6 +; CHECK-NEXT: [[G7:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 7 +; CHECK-NEXT: [[T0:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[T1:%.*]] = load i8, ptr [[G1]], align 1 +; CHECK-NEXT: [[T2:%.*]] = load i8, ptr [[G2]], align 1 +; CHECK-NEXT: [[T3:%.*]] = load i8, ptr [[G3]], align 1 +; CHECK-NEXT: [[T4:%.*]] = load i8, ptr [[G4]], align 1 +; CHECK-NEXT: [[T5:%.*]] = load i8, ptr [[G5]], align 1 +; CHECK-NEXT: [[T6:%.*]] = load i8, ptr [[G6]], align 1 +; CHECK-NEXT: [[T7:%.*]] = load i8, ptr [[G7]], align 1 +; CHECK-NEXT: [[Z0:%.*]] = zext i8 [[T0]] to i64 +; CHECK-NEXT: [[Z1:%.*]] = zext i8 [[T1]] to i64 +; CHECK-NEXT: [[Z2:%.*]] = zext i8 [[T2]] to i64 +; CHECK-NEXT: [[Z3:%.*]] = zext i8 [[T3]] to i64 +; CHECK-NEXT: [[Z4:%.*]] = zext i8 [[T4]] to i64 +; CHECK-NEXT: [[Z5:%.*]] = zext i8 [[T5]] to i64 +; CHECK-NEXT: [[Z6:%.*]] = zext i8 [[T6]] to i64 +; CHECK-NEXT: [[Z7:%.*]] = zext i8 [[T7]] to i64 +; CHECK-NEXT: [[SH0:%.*]] = shl nuw i64 [[Z0]], 56 +; CHECK-NEXT: [[SH1:%.*]] = shl nuw nsw i64 [[Z1]], 48 +; CHECK-NEXT: [[SH2:%.*]] = shl nuw nsw i64 [[Z2]], 40 +; CHECK-NEXT: [[SH3:%.*]] = shl nuw nsw i64 [[Z3]], 32 +; CHECK-NEXT: [[SH4:%.*]] = shl nuw nsw i64 [[Z4]], 24 +; CHECK-NEXT: [[SH5:%.*]] = shl nuw nsw i64 [[Z5]], 16 +; CHECK-NEXT: [[SH6:%.*]] = shl nuw nsw i64 [[Z6]], 8 +; CHECK-NEXT: [[OR01:%.*]] = or disjoint i64 [[SH0]], [[SH1]] +; CHECK-NEXT: [[OR012:%.*]] = or disjoint i64 [[OR01]], [[SH2]] +; CHECK-NEXT: [[OR0123:%.*]] = or disjoint i64 [[OR012]], [[SH3]] +; CHECK-NEXT: [[OR01234:%.*]] = or disjoint i64 [[OR0123]], [[SH4]] +; CHECK-NEXT: [[OR012345:%.*]] = or disjoint i64 [[OR01234]], [[SH5]] +; CHECK-NEXT: [[OR0123456:%.*]] = or disjoint i64 [[OR012345]], [[SH6]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i64 [[OR0123456]], [[Z7]] ; CHECK-NEXT: ret i64 [[TMP2]] ; %g1 = getelementptr inbounds %v8i8, ptr %p, i64 0, i32 1 @@ -272,8 +441,44 @@ define i64 @load_bswap_disjoint(ptr %p) { define i64 @load_bswap_nop_shift_disjoint(ptr %p) { ; CHECK-LABEL: @load_bswap_nop_shift_disjoint( -; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[P:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.bswap.i64(i64 [[TMP1]]) +; CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds [[V8I8:%.*]], ptr [[P:%.*]], i64 0, i32 1 +; CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 2 +; CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 3 +; CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 4 +; CHECK-NEXT: [[G5:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 5 +; CHECK-NEXT: [[G6:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 6 +; CHECK-NEXT: [[G7:%.*]] = getelementptr inbounds [[V8I8]], ptr [[P]], i64 0, i32 7 +; CHECK-NEXT: [[T0:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: [[T1:%.*]] = load i8, ptr [[G1]], align 1 +; CHECK-NEXT: [[T2:%.*]] = load i8, ptr [[G2]], align 1 +; CHECK-NEXT: [[T3:%.*]] = load i8, ptr [[G3]], align 1 +; CHECK-NEXT: [[T4:%.*]] = load i8, ptr [[G4]], align 1 +; CHECK-NEXT: [[T5:%.*]] = load i8, ptr [[G5]], align 1 +; CHECK-NEXT: [[T6:%.*]] = load i8, ptr [[G6]], align 1 +; CHECK-NEXT: [[T7:%.*]] = load i8, ptr [[G7]], align 1 +; CHECK-NEXT: [[Z0:%.*]] = zext i8 [[T0]] to i64 +; CHECK-NEXT: [[Z1:%.*]] = zext i8 [[T1]] to i64 +; CHECK-NEXT: [[Z2:%.*]] = zext i8 [[T2]] to i64 +; CHECK-NEXT: [[Z3:%.*]] = zext i8 [[T3]] to i64 +; CHECK-NEXT: [[Z4:%.*]] = zext i8 [[T4]] to i64 +; CHECK-NEXT: [[Z5:%.*]] = zext i8 [[T5]] to i64 +; CHECK-NEXT: [[Z6:%.*]] = zext i8 [[T6]] to i64 +; CHECK-NEXT: [[Z7:%.*]] = zext i8 [[T7]] to i64 +; CHECK-NEXT: [[SH0:%.*]] = shl nuw i64 [[Z0]], 56 +; CHECK-NEXT: [[SH1:%.*]] = shl nuw nsw i64 [[Z1]], 48 +; CHECK-NEXT: [[SH2:%.*]] = shl nuw nsw i64 [[Z2]], 40 +; CHECK-NEXT: [[SH3:%.*]] = shl nuw nsw i64 [[Z3]], 32 +; CHECK-NEXT: [[SH4:%.*]] = shl nuw nsw i64 [[Z4]], 24 +; CHECK-NEXT: [[SH5:%.*]] = shl nuw nsw i64 [[Z5]], 16 +; CHECK-NEXT: [[SH6:%.*]] = shl nuw nsw i64 [[Z6]], 8 +; CHECK-NEXT: [[SH7:%.*]] = shl nuw nsw i64 [[Z7]], 0 +; CHECK-NEXT: [[OR01:%.*]] = or disjoint i64 [[SH0]], [[SH1]] +; CHECK-NEXT: [[OR012:%.*]] = or disjoint i64 [[OR01]], [[SH2]] +; CHECK-NEXT: [[OR0123:%.*]] = or disjoint i64 [[OR012]], [[SH3]] +; CHECK-NEXT: [[OR01234:%.*]] = or disjoint i64 [[OR0123]], [[SH4]] +; CHECK-NEXT: [[OR012345:%.*]] = or disjoint i64 [[OR01234]], [[SH5]] +; CHECK-NEXT: [[OR0123456:%.*]] = or disjoint i64 [[OR012345]], [[SH6]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i64 [[OR0123456]], [[SH7]] ; CHECK-NEXT: ret i64 [[TMP2]] ; %g1 = getelementptr inbounds %v8i8, ptr %p, i64 0, i32 1 @@ -323,7 +528,43 @@ define i64 @load_bswap_nop_shift_disjoint(ptr %p) { define i64 @load64le_disjoint(ptr %arg) { ; CHECK-LABEL: @load64le_disjoint( -; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[ARG:%.*]], align 1 +; CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1 +; CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 2 +; CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 3 +; CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 4 +; CHECK-NEXT: [[G5:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 5 +; CHECK-NEXT: [[G6:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 6 +; CHECK-NEXT: [[G7:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 7 +; CHECK-NEXT: [[LD0:%.*]] = load i8, ptr [[ARG]], align 1 +; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[G1]], align 1 +; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[G2]], align 1 +; CHECK-NEXT: [[LD3:%.*]] = load i8, ptr [[G3]], align 1 +; CHECK-NEXT: [[LD4:%.*]] = load i8, ptr [[G4]], align 1 +; CHECK-NEXT: [[LD5:%.*]] = load i8, ptr [[G5]], align 1 +; CHECK-NEXT: [[LD6:%.*]] = load i8, ptr [[G6]], align 1 +; CHECK-NEXT: [[LD7:%.*]] = load i8, ptr [[G7]], align 1 +; CHECK-NEXT: [[Z0:%.*]] = zext i8 [[LD0]] to i64 +; CHECK-NEXT: [[Z1:%.*]] = zext i8 [[LD1]] to i64 +; CHECK-NEXT: [[Z2:%.*]] = zext i8 [[LD2]] to i64 +; CHECK-NEXT: [[Z3:%.*]] = zext i8 [[LD3]] to i64 +; CHECK-NEXT: [[Z4:%.*]] = zext i8 [[LD4]] to i64 +; CHECK-NEXT: [[Z5:%.*]] = zext i8 [[LD5]] to i64 +; CHECK-NEXT: [[Z6:%.*]] = zext i8 [[LD6]] to i64 +; CHECK-NEXT: [[Z7:%.*]] = zext i8 [[LD7]] to i64 +; CHECK-NEXT: [[S1:%.*]] = shl nuw nsw i64 [[Z1]], 8 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i64 [[Z2]], 16 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i64 [[Z3]], 24 +; CHECK-NEXT: [[S4:%.*]] = shl nuw nsw i64 [[Z4]], 32 +; CHECK-NEXT: [[S5:%.*]] = shl nuw nsw i64 [[Z5]], 40 +; CHECK-NEXT: [[S6:%.*]] = shl nuw nsw i64 [[Z6]], 48 +; CHECK-NEXT: [[S7:%.*]] = shl nuw i64 [[Z7]], 56 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i64 [[S1]], [[Z0]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i64 [[O1]], [[S2]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i64 [[O2]], [[S3]] +; CHECK-NEXT: [[O4:%.*]] = or disjoint i64 [[O3]], [[S4]] +; CHECK-NEXT: [[O5:%.*]] = or disjoint i64 [[O4]], [[S5]] +; CHECK-NEXT: [[O6:%.*]] = or disjoint i64 [[O5]], [[S6]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i64 [[O6]], [[S7]] ; CHECK-NEXT: ret i64 [[TMP2]] ; %g1 = getelementptr inbounds i8, ptr %arg, i64 1 @@ -373,7 +614,44 @@ define i64 @load64le_disjoint(ptr %arg) { define i64 @load64le_nop_shift_disjoint(ptr %arg) { ; CHECK-LABEL: @load64le_nop_shift_disjoint( -; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[ARG:%.*]], align 1 +; CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1 +; CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 2 +; CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 3 +; CHECK-NEXT: [[G4:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 4 +; CHECK-NEXT: [[G5:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 5 +; CHECK-NEXT: [[G6:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 6 +; CHECK-NEXT: [[G7:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 7 +; CHECK-NEXT: [[LD0:%.*]] = load i8, ptr [[ARG]], align 1 +; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[G1]], align 1 +; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[G2]], align 1 +; CHECK-NEXT: [[LD3:%.*]] = load i8, ptr [[G3]], align 1 +; CHECK-NEXT: [[LD4:%.*]] = load i8, ptr [[G4]], align 1 +; CHECK-NEXT: [[LD5:%.*]] = load i8, ptr [[G5]], align 1 +; CHECK-NEXT: [[LD6:%.*]] = load i8, ptr [[G6]], align 1 +; CHECK-NEXT: [[LD7:%.*]] = load i8, ptr [[G7]], align 1 +; CHECK-NEXT: [[Z0:%.*]] = zext i8 [[LD0]] to i64 +; CHECK-NEXT: [[Z1:%.*]] = zext i8 [[LD1]] to i64 +; CHECK-NEXT: [[Z2:%.*]] = zext i8 [[LD2]] to i64 +; CHECK-NEXT: [[Z3:%.*]] = zext i8 [[LD3]] to i64 +; CHECK-NEXT: [[Z4:%.*]] = zext i8 [[LD4]] to i64 +; CHECK-NEXT: [[Z5:%.*]] = zext i8 [[LD5]] to i64 +; CHECK-NEXT: [[Z6:%.*]] = zext i8 [[LD6]] to i64 +; CHECK-NEXT: [[Z7:%.*]] = zext i8 [[LD7]] to i64 +; CHECK-NEXT: [[S0:%.*]] = shl nuw nsw i64 [[Z0]], 0 +; CHECK-NEXT: [[S1:%.*]] = shl nuw nsw i64 [[Z1]], 8 +; CHECK-NEXT: [[S2:%.*]] = shl nuw nsw i64 [[Z2]], 16 +; CHECK-NEXT: [[S3:%.*]] = shl nuw nsw i64 [[Z3]], 24 +; CHECK-NEXT: [[S4:%.*]] = shl nuw nsw i64 [[Z4]], 32 +; CHECK-NEXT: [[S5:%.*]] = shl nuw nsw i64 [[Z5]], 40 +; CHECK-NEXT: [[S6:%.*]] = shl nuw nsw i64 [[Z6]], 48 +; CHECK-NEXT: [[S7:%.*]] = shl nuw i64 [[Z7]], 56 +; CHECK-NEXT: [[O1:%.*]] = or disjoint i64 [[S1]], [[S0]] +; CHECK-NEXT: [[O2:%.*]] = or disjoint i64 [[O1]], [[S2]] +; CHECK-NEXT: [[O3:%.*]] = or disjoint i64 [[O2]], [[S3]] +; CHECK-NEXT: [[O4:%.*]] = or disjoint i64 [[O3]], [[S4]] +; CHECK-NEXT: [[O5:%.*]] = or disjoint i64 [[O4]], [[S5]] +; CHECK-NEXT: [[O6:%.*]] = or disjoint i64 [[O5]], [[S6]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i64 [[O6]], [[S7]] ; CHECK-NEXT: ret i64 [[TMP2]] ; %g1 = getelementptr inbounds i8, ptr %arg, i64 1 @@ -423,22 +701,84 @@ define i64 @load64le_nop_shift_disjoint(ptr %arg) { define void @PR39538(ptr %t0, ptr %t1) { ; CHECK-LABEL: @PR39538( -; CHECK-NEXT: [[TMP1:%.*]] = load <16 x i8>, ptr [[T0:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> poison, <4 x i32> -; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i8> [[TMP2]] to <4 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> poison, <4 x i32> -; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> poison, <4 x i32> -; CHECK-NEXT: [[TMP7:%.*]] = zext <4 x i8> [[TMP6]] to <4 x i32> -; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> poison, <4 x i32> -; CHECK-NEXT: [[TMP9:%.*]] = zext <4 x i8> [[TMP8]] to <4 x i32> -; CHECK-NEXT: [[TMP10:%.*]] = shl nuw <4 x i32> [[TMP3]], -; CHECK-NEXT: [[TMP11:%.*]] = shl nuw <4 x i32> [[TMP5]], -; CHECK-NEXT: [[TMP12:%.*]] = shl nuw nsw <4 x i32> [[TMP7]], splat (i32 8) -; CHECK-NEXT: [[TMP13:%.*]] = or <4 x i32> [[TMP11]], [[TMP10]] -; CHECK-NEXT: [[TMP14:%.*]] = or <4 x i32> [[TMP13]], [[TMP12]] -; CHECK-NEXT: [[TMP15:%.*]] = or <4 x i32> [[TMP14]], [[TMP9]] -; CHECK-NEXT: store <4 x i32> [[TMP15]], ptr [[T1:%.*]], align 4 +; CHECK-NEXT: [[T6:%.*]] = getelementptr inbounds i8, ptr [[T0:%.*]], i64 1 +; CHECK-NEXT: [[T11:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 2 +; CHECK-NEXT: [[T16:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 3 +; CHECK-NEXT: [[T20:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 4 +; CHECK-NEXT: [[T24:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 5 +; CHECK-NEXT: [[T29:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 6 +; CHECK-NEXT: [[T34:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 7 +; CHECK-NEXT: [[T39:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 8 +; CHECK-NEXT: [[T43:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 9 +; CHECK-NEXT: [[T48:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 10 +; CHECK-NEXT: [[T53:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 11 +; CHECK-NEXT: [[T58:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 12 +; CHECK-NEXT: [[T62:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 13 +; CHECK-NEXT: [[T67:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 14 +; CHECK-NEXT: [[T72:%.*]] = getelementptr inbounds i8, ptr [[T0]], i64 15 +; CHECK-NEXT: [[T38:%.*]] = getelementptr inbounds i32, ptr [[T1:%.*]], i64 1 +; CHECK-NEXT: [[T57:%.*]] = getelementptr inbounds i32, ptr [[T1]], i64 2 +; CHECK-NEXT: [[T76:%.*]] = getelementptr inbounds i32, ptr [[T1]], i64 3 +; CHECK-NEXT: [[T3:%.*]] = load i8, ptr [[T0]], align 1 +; CHECK-NEXT: [[T7:%.*]] = load i8, ptr [[T6]], align 1 +; CHECK-NEXT: [[T12:%.*]] = load i8, ptr [[T11]], align 1 +; CHECK-NEXT: [[T17:%.*]] = load i8, ptr [[T16]], align 1 +; CHECK-NEXT: [[T21:%.*]] = load i8, ptr [[T20]], align 1 +; CHECK-NEXT: [[T25:%.*]] = load i8, ptr [[T24]], align 1 +; CHECK-NEXT: [[T30:%.*]] = load i8, ptr [[T29]], align 1 +; CHECK-NEXT: [[T35:%.*]] = load i8, ptr [[T34]], align 1 +; CHECK-NEXT: [[T40:%.*]] = load i8, ptr [[T39]], align 1 +; CHECK-NEXT: [[T44:%.*]] = load i8, ptr [[T43]], align 1 +; CHECK-NEXT: [[T49:%.*]] = load i8, ptr [[T48]], align 1 +; CHECK-NEXT: [[T54:%.*]] = load i8, ptr [[T53]], align 1 +; CHECK-NEXT: [[T59:%.*]] = load i8, ptr [[T58]], align 1 +; CHECK-NEXT: [[T63:%.*]] = load i8, ptr [[T62]], align 1 +; CHECK-NEXT: [[T68:%.*]] = load i8, ptr [[T67]], align 1 +; CHECK-NEXT: [[T73:%.*]] = load i8, ptr [[T72]], align 1 +; CHECK-NEXT: [[T4:%.*]] = zext i8 [[T3]] to i32 +; CHECK-NEXT: [[T8:%.*]] = zext i8 [[T7]] to i32 +; CHECK-NEXT: [[T13:%.*]] = zext i8 [[T12]] to i32 +; CHECK-NEXT: [[T18:%.*]] = zext i8 [[T17]] to i32 +; CHECK-NEXT: [[T22:%.*]] = zext i8 [[T21]] to i32 +; CHECK-NEXT: [[T26:%.*]] = zext i8 [[T25]] to i32 +; CHECK-NEXT: [[T31:%.*]] = zext i8 [[T30]] to i32 +; CHECK-NEXT: [[T36:%.*]] = zext i8 [[T35]] to i32 +; CHECK-NEXT: [[T41:%.*]] = zext i8 [[T40]] to i32 +; CHECK-NEXT: [[T45:%.*]] = zext i8 [[T44]] to i32 +; CHECK-NEXT: [[T50:%.*]] = zext i8 [[T49]] to i32 +; CHECK-NEXT: [[T55:%.*]] = zext i8 [[T54]] to i32 +; CHECK-NEXT: [[T60:%.*]] = zext i8 [[T59]] to i32 +; CHECK-NEXT: [[T64:%.*]] = zext i8 [[T63]] to i32 +; CHECK-NEXT: [[T69:%.*]] = zext i8 [[T68]] to i32 +; CHECK-NEXT: [[T74:%.*]] = zext i8 [[T73]] to i32 +; CHECK-NEXT: [[T5:%.*]] = shl nuw i32 [[T4]], 24 +; CHECK-NEXT: [[T23:%.*]] = shl nuw i32 [[T22]], 24 +; CHECK-NEXT: [[T42:%.*]] = shl nuw i32 [[T41]], 24 +; CHECK-NEXT: [[T61:%.*]] = shl nuw i32 [[T60]], 24 +; CHECK-NEXT: [[T9:%.*]] = shl nuw nsw i32 [[T8]], 16 +; CHECK-NEXT: [[T27:%.*]] = shl nuw nsw i32 [[T26]], 16 +; CHECK-NEXT: [[T46:%.*]] = shl nuw nsw i32 [[T45]], 16 +; CHECK-NEXT: [[T65:%.*]] = shl nuw nsw i32 [[T64]], 16 +; CHECK-NEXT: [[T14:%.*]] = shl nuw nsw i32 [[T13]], 8 +; CHECK-NEXT: [[T32:%.*]] = shl nuw nsw i32 [[T31]], 8 +; CHECK-NEXT: [[T51:%.*]] = shl nuw nsw i32 [[T50]], 8 +; CHECK-NEXT: [[T70:%.*]] = shl nuw nsw i32 [[T69]], 8 +; CHECK-NEXT: [[T10:%.*]] = or i32 [[T9]], [[T5]] +; CHECK-NEXT: [[T15:%.*]] = or i32 [[T10]], [[T14]] +; CHECK-NEXT: [[T19:%.*]] = or i32 [[T15]], [[T18]] +; CHECK-NEXT: [[T28:%.*]] = or i32 [[T27]], [[T23]] +; CHECK-NEXT: [[T33:%.*]] = or i32 [[T28]], [[T32]] +; CHECK-NEXT: [[T37:%.*]] = or i32 [[T33]], [[T36]] +; CHECK-NEXT: [[T47:%.*]] = or i32 [[T46]], [[T42]] +; CHECK-NEXT: [[T52:%.*]] = or i32 [[T47]], [[T51]] +; CHECK-NEXT: [[T56:%.*]] = or i32 [[T52]], [[T55]] +; CHECK-NEXT: [[T66:%.*]] = or i32 [[T65]], [[T61]] +; CHECK-NEXT: [[T71:%.*]] = or i32 [[T66]], [[T70]] +; CHECK-NEXT: [[T75:%.*]] = or i32 [[T71]], [[T74]] +; CHECK-NEXT: store i32 [[T19]], ptr [[T1]], align 4 +; CHECK-NEXT: store i32 [[T37]], ptr [[T38]], align 4 +; CHECK-NEXT: store i32 [[T56]], ptr [[T57]], align 4 +; CHECK-NEXT: store i32 [[T75]], ptr [[T76]], align 4 ; CHECK-NEXT: ret void ; %t6 = getelementptr inbounds i8, ptr %t0, i64 1 diff --git a/llvm/test/Transforms/SLPVectorizer/X86/load-merge-inseltpoison.ll b/llvm/test/Transforms/SLPVectorizer/X86/load-merge-inseltpoison.ll index 7936d1e77c70..c02ef8388b06 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/load-merge-inseltpoison.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/load-merge-inseltpoison.ll @@ -10,10 +10,23 @@ define i32 @_Z9load_le32Ph(ptr nocapture readonly %data) { ; CHECK-LABEL: @_Z9load_le32Ph( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i8>, ptr [[DATA:%.*]], align 1 -; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i32> -; CHECK-NEXT: [[TMP2:%.*]] = shl <4 x i32> [[TMP1]], -; CHECK-NEXT: [[OR11:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP2]]) +; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[DATA:%.*]], align 1 +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[TMP0]] to i32 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[DATA]], i64 1 +; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 +; CHECK-NEXT: [[CONV2:%.*]] = zext i8 [[TMP1]] to i32 +; CHECK-NEXT: [[SHL3:%.*]] = shl nuw nsw i32 [[CONV2]], 8 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL3]], [[CONV]] +; CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i8, ptr [[DATA]], i64 2 +; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[ARRAYIDX4]], align 1 +; CHECK-NEXT: [[CONV5:%.*]] = zext i8 [[TMP2]] to i32 +; CHECK-NEXT: [[SHL6:%.*]] = shl nuw nsw i32 [[CONV5]], 16 +; CHECK-NEXT: [[OR7:%.*]] = or i32 [[OR]], [[SHL6]] +; CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds i8, ptr [[DATA]], i64 3 +; CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX8]], align 1 +; CHECK-NEXT: [[CONV9:%.*]] = zext i8 [[TMP3]] to i32 +; CHECK-NEXT: [[SHL10:%.*]] = shl nuw i32 [[CONV9]], 24 +; CHECK-NEXT: [[OR11:%.*]] = or i32 [[OR7]], [[SHL10]] ; CHECK-NEXT: ret i32 [[OR11]] ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/load-merge.ll b/llvm/test/Transforms/SLPVectorizer/X86/load-merge.ll index 5f8f7ac9ed36..0545e5403f59 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/load-merge.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/load-merge.ll @@ -10,10 +10,23 @@ define i32 @_Z9load_le32Ph(ptr nocapture readonly %data) { ; CHECK-LABEL: @_Z9load_le32Ph( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i8>, ptr [[DATA:%.*]], align 1 -; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i32> -; CHECK-NEXT: [[TMP2:%.*]] = shl <4 x i32> [[TMP1]], -; CHECK-NEXT: [[OR11:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP2]]) +; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[DATA:%.*]], align 1 +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[TMP0]] to i32 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[DATA]], i64 1 +; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1 +; CHECK-NEXT: [[CONV2:%.*]] = zext i8 [[TMP1]] to i32 +; CHECK-NEXT: [[SHL3:%.*]] = shl nuw nsw i32 [[CONV2]], 8 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL3]], [[CONV]] +; CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i8, ptr [[DATA]], i64 2 +; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[ARRAYIDX4]], align 1 +; CHECK-NEXT: [[CONV5:%.*]] = zext i8 [[TMP2]] to i32 +; CHECK-NEXT: [[SHL6:%.*]] = shl nuw nsw i32 [[CONV5]], 16 +; CHECK-NEXT: [[OR7:%.*]] = or i32 [[OR]], [[SHL6]] +; CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds i8, ptr [[DATA]], i64 3 +; CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[ARRAYIDX8]], align 1 +; CHECK-NEXT: [[CONV9:%.*]] = zext i8 [[TMP3]] to i32 +; CHECK-NEXT: [[SHL10:%.*]] = shl nuw i32 [[CONV9]], 24 +; CHECK-NEXT: [[OR11:%.*]] = or i32 [[OR7]], [[SHL10]] ; CHECK-NEXT: ret i32 [[OR11]] ; entry: