[llvm] Revert "[VectorCombine] Combine adjacent loads feeding as shuffle operands (#213007)" (PR #228978)
Kazu Hirata via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 4 22:47:50 PDT 2026
https://github.com/kazutakahirata created https://github.com/llvm/llvm-project/pull/228978
This reverts commit 9f70ca880b37eba68a171f36272e06d8d2d371f3.
I'm seeing:
Failed Tests (1):
LLVM :: Transforms/VectorCombine/AArch64/shuffle-of-adjacent-loads.ll
>From f3ab835a2ccf625fdcbad80b305accd4652f4412 Mon Sep 17 00:00:00 2001
From: Kazu Hirata <kazu at google.com>
Date: Sun, 4 Oct 2026 22:36:38 -0700
Subject: [PATCH] Revert "[VectorCombine] Combine adjacent loads feeding as
shuffle operands (#213007)"
This reverts commit 9f70ca880b37eba68a171f36272e06d8d2d371f3.
I'm seeing:
Failed Tests (1):
LLVM :: Transforms/VectorCombine/AArch64/shuffle-of-adjacent-loads.ll
---
.../Transforms/Vectorize/VectorCombine.cpp | 212 +-----------------
.../AArch64/shuffle-of-adjacent-loads.ll | 185 ---------------
2 files changed, 4 insertions(+), 393 deletions(-)
delete mode 100644 llvm/test/Transforms/VectorCombine/AArch64/shuffle-of-adjacent-loads.ll
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index dbbc312cf2bd8..65522c616fbe0 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -24,8 +24,6 @@
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/InstSimplifyFolder.h"
#include "llvm/Analysis/Loads.h"
-#include "llvm/Analysis/LoopAccessAnalysis.h"
-#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/TargetFolder.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
@@ -80,10 +78,10 @@ class VectorCombine {
public:
VectorCombine(Function &F, const TargetTransformInfo &TTI,
const DominatorTree &DT, AAResults &AA, AssumptionCache &AC,
- ScalarEvolution *SE, const DataLayout *DL,
- TTI::TargetCostKind CostKind, bool TryEarlyFoldsOnly)
+ const DataLayout *DL, TTI::TargetCostKind CostKind,
+ bool TryEarlyFoldsOnly)
: F(F), Builder(F.getContext(), InstSimplifyFolder(*DL)), TTI(TTI),
- DT(DT), AA(AA), SE(SE), DL(DL), CostKind(CostKind),
+ DT(DT), AA(AA), DL(DL), CostKind(CostKind),
SQ(*DL, /*TLI=*/nullptr, &DT, &AC),
TryEarlyFoldsOnly(TryEarlyFoldsOnly) {}
@@ -95,7 +93,6 @@ class VectorCombine {
const TargetTransformInfo &TTI;
const DominatorTree &DT;
AAResults &AA;
- ScalarEvolution *SE;
const DataLayout *DL;
TTI::TargetCostKind CostKind;
const SimplifyQuery SQ;
@@ -146,7 +143,6 @@ class VectorCombine {
bool foldShuffleOfSelects(Instruction &I);
bool foldShuffleOfCastops(Instruction &I);
bool foldShuffleOfShuffles(Instruction &I);
- bool foldShuffleOfAdjacentLoads(Instruction &I);
bool foldPermuteOfIntrinsic(Instruction &I);
bool foldShufflesOfLengthChangingShuffles(Instruction &I);
bool foldShuffleOfIntrinsics(Instruction &I);
@@ -6808,201 +6804,6 @@ bool VectorCombine::shrinkLoadForShuffles(Instruction &I) {
return false;
}
-// Attempt to combine two adjacent fixed-length vector loads, that only feed
-// shufflevector instructions, into a single wider load, rewriting every such
-// shuffle so that operand 0 is the wide load and operand 1 is poison.
-// clang-format off
-// e.g.
-// %loadA = load <16 x i8>, ptr %a
-// %gep = getelementptr inbounds <16 x i8>, ptr %a, i64 1
-// %loadB = load <16 x i8>, ptr %gep
-// %shuffle0 = shufflevector <16 x i8> %loadA, <16 x i8> %loadB,
-// <32 x i8> <...>
-// %shuffle1 = shufflevector <16 x i8> %loadA, <16 x i8> %loadB,
-// <32 x i8> <...>
-//
-// The fold would transform this to:
-// %loadAB = load <32 x i8>, ptr %a
-// %shuffle0 = shufflevector <32 x i8> %loadAB, <32 x i8> poison,
-// <32 x i8> <...>
-// %shuffle1 = shufflevector <32 x i8> %loadAB, <32 x i8> poison,
-// <32 x i8> <...>
-//
-// clang-format on
-// Matching this pattern in codegen becomes difficult and hence, we prefer doing
-// this here.
-bool VectorCombine::foldShuffleOfAdjacentLoads(Instruction &I) {
- auto *SV = cast<ShuffleVectorInst>(&I);
-
- // The two operands must be distinct loads of the same fixed vector type.
- auto *Load0 = dyn_cast<LoadInst>(SV->getOperand(0));
- auto *Load1 = dyn_cast<LoadInst>(SV->getOperand(1));
- if (!Load0 || !Load1 || Load0 == Load1 || !Load0->isSimple() ||
- !Load1->isSimple())
- return false;
-
- // Confirm both loads are of fixed vector type.
- auto *LoadTy = dyn_cast<FixedVectorType>(Load0->getType());
- if (!LoadTy)
- return false;
-
- // We restrict to loads occurring in the same BB for now.
- if (Load0->getParent() != Load1->getParent())
- return false;
-
- if (Load0->getPointerAddressSpace() != Load1->getPointerAddressSpace())
- return false;
-
- // Check that the original load type has no padding bits otherwise the wide
- // load would be incorrect.
- if (DL->getTypeSizeInBits(LoadTy) != 8 * DL->getTypeStoreSize(LoadTy))
- return false;
-
- const int NumElts = LoadTy->getNumElements();
-
- // Determine which load is at the lower address and confirm the two loads are
- // exactly contiguous. isConsecutiveAccess(A, B) is true only when B directly
- // follows A, so we probe both orderings to also handle the reversed case.
- LoadInst *LowLoad, *HighLoad;
- assert(SE && "ScalarEvolution is only available for late folds");
- if (isConsecutiveAccess(Load0, Load1, *DL, *SE)) {
- LowLoad = Load0;
- HighLoad = Load1;
- } else if (isConsecutiveAccess(Load1, Load0, *DL, *SE)) {
- LowLoad = Load1;
- HighLoad = Load0;
- } else {
- return false;
- }
-
- // 1. Check all users of both loads are shuffles.
- // 2. Check that both loads feed exactly the same set of shuffles.
- SmallPtrSet<ShuffleVectorInst *, 4> Shuffles;
- auto AreShufflesOnlyUsersOfLoads = [LowLoad, HighLoad, &Shuffles]() -> bool {
- // Step 1: collect every user of LowLoad, requiring each to be a shuffle.
- for (User *U : LowLoad->users()) {
- auto *SV = dyn_cast<ShuffleVectorInst>(U);
- if (!SV)
- return false;
- Shuffles.insert(SV);
- }
-
- // Step 2: every user of HighLoad must be a shuffle already collected from
- // LowLoad, counting them as we go.
- unsigned HighLoadUsers = 0;
- for (User *U : HighLoad->users()) {
- auto *SV = dyn_cast<ShuffleVectorInst>(U);
- if (!SV || !Shuffles.contains(SV))
- return false;
- ++HighLoadUsers;
- }
-
- // Step 3: both loads must feed exactly the same set of shuffles. Combined
- // with step 2, this guarantees every shuffle uses both LowLoad and
- // HighLoad, so their operands are exactly {LowLoad, HighLoad}.
- return HighLoadUsers == Shuffles.size();
- };
- if (!AreShufflesOnlyUsersOfLoads())
- return false;
-
- // The value loaded by either load must not be clobbered in between the loads.
- auto *WideTy = FixedVectorType::get(LoadTy->getElementType(), NumElts * 2);
- LoadInst *FirstLoad = LowLoad, *LastLoad = HighLoad;
- bool LowComesFirst = LowLoad->comesBefore(HighLoad);
- if (!LowComesFirst)
- std::swap(FirstLoad, LastLoad);
- MemoryLocation FirstLoc = MemoryLocation::get(FirstLoad);
- if (isMemModifiedBetween(std::next(FirstLoad->getIterator()),
- LastLoad->getIterator(), FirstLoc, AA))
- return false;
-
- // case 1: wide load = LowLoad + HighLoad ,
- // shuffle 0th operand = LowLoad
- // shuffle 1st operand = HighLoad
- // Implication with this is shuffle mask for the wide load remains unchanged
- // case 2: wide load = LowLoad + HighLoad ,
- // shuffle 0th operand = HighLoad
- // shuffle 1st operand = LowLoad
- // Implication with this is shuffle mask for the wide load changes
- auto RemapMask = [LowLoad, HighLoad, NumElts](ShuffleVectorInst *SV,
- SmallVectorImpl<int> &NewMask) {
- Value *SVOp0 = SV->getOperand(0);
- Value *SVOp1 = SV->getOperand(1);
- assert(((SVOp0 == LowLoad && SVOp1 == HighLoad) ||
- (SVOp0 == HighLoad && SVOp1 == LowLoad)) &&
- "Shuffle operands must be exactly {LowLoad, HighLoad} or {HighLoad, "
- "LowLoad}");
- NewMask.assign(SV->getShuffleMask().begin(), SV->getShuffleMask().end());
- if (SVOp0 == HighLoad)
- ShuffleVectorInst::commuteShuffleMask(NewMask, NumElts);
- };
-
- // Cost model checks
- Value *Poison = PoisonValue::get(WideTy);
- InstructionCost OldCost =
- TTI.getMemoryOpCost(Instruction::Load, LoadTy, LowLoad->getAlign(),
- LowLoad->getPointerAddressSpace(), CostKind);
- OldCost +=
- TTI.getMemoryOpCost(Instruction::Load, LoadTy, HighLoad->getAlign(),
- HighLoad->getPointerAddressSpace(), CostKind);
- InstructionCost NewCost =
- TTI.getMemoryOpCost(Instruction::Load, WideTy, LowLoad->getAlign(),
- LowLoad->getPointerAddressSpace(), CostKind);
- for (ShuffleVectorInst *SV : Shuffles) {
- OldCost += TTI.getShuffleCost(TTI::SK_PermuteTwoSrc, SV->getType(), LoadTy,
- CostKind, SV->getShuffleMask());
- SmallVector<int, 32> NewMask;
- RemapMask(SV, NewMask);
- // LoadSz = initial load size
- // WideSz = 2 * LoadSz
- // MaxMaskSize = WideSz * 2
- // Check if MaxMaskSize fits within an integer range.
- if (!ShuffleVectorInst::isValidOperands(Poison, Poison, NewMask))
- return false;
- NewCost += TTI.getShuffleCost(TTI::SK_PermuteSingleSrc, SV->getType(),
- WideTy, CostKind, NewMask);
- }
-
- LLVM_DEBUG(dbgs() << "Found adjacent loads feeding shuffles: " << *LowLoad
- << ", " << *HighLoad << "\n OldCost: " << OldCost
- << " vs NewCost: " << NewCost << "\n");
-
- if (!NewCost.isValid() || NewCost > OldCost)
- return false;
-
- // Insert the wide load at whichever original load comes last, so that both
- // halves of the contiguous range are known to be dereferenceable there.
- LoadInst *InsertPt = LastLoad;
-
- // Build the wide load at the insertion point using the low load's pointer and
- // alignment, intersecting alias metadata from both original loads.
- Builder.SetInsertPoint(InsertPt);
- Builder.SetCurrentDebugLocation(InsertPt->getDebugLoc());
- LoadInst *WideLoad = Builder.CreateAlignedLoad(
- WideTy, LowLoad->getPointerOperand(), LowLoad->getAlign());
-
- // Set the metadata on the wide load. copyMetadataForLoad seeds it from
- // LowLoad, then combineMetadataForCSE intersects every known kind against
- // HighLoad (taking the most-generic value where applicable, keeping facts
- // only where both loads agree, and dropping unknown metadata), so nothing is
- // asserted over the combined load unless justified by both halves.
- copyMetadataForLoad(*WideLoad, *LowLoad);
- combineMetadataForCSE(WideLoad, HighLoad, /*DoesKMove=*/true);
-
- for (ShuffleVectorInst *SV : Shuffles) {
- SmallVector<int, 32> NewMask;
- RemapMask(SV, NewMask);
-
- Builder.SetInsertPoint(SV);
- Builder.SetCurrentDebugLocation(SV->getDebugLoc());
- Value *NewShuf = Builder.CreateShuffleVector(WideLoad, Poison, NewMask);
- // We do not want to erase shuffles immediately because they may invalidate
- // the NextInst pointer in the caller's BB traversal.
- replaceValue(*SV, *NewShuf, /*Erase=*/false);
- }
- return true;
-}
-
// Attempt to narrow a phi of shufflevector instructions where the two incoming
// values have the same operands but different masks. If the two shuffle masks
// are offsets of one another we can use one branch to rotate the incoming
@@ -7195,8 +6996,6 @@ bool VectorCombine::run() {
return true;
if (foldShuffleOfShuffles(I))
return true;
- if (foldShuffleOfAdjacentLoads(I))
- return true;
if (foldPermuteOfIntrinsic(I))
return true;
if (foldShufflesOfLengthChangingShuffles(I))
@@ -7325,13 +7124,10 @@ PreservedAnalyses VectorCombinePass::run(Function &F,
TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
AAResults &AA = FAM.getResult<AAManager>(F);
- ScalarEvolution *SE =
- TryEarlyFoldsOnly ? nullptr : &FAM.getResult<ScalarEvolutionAnalysis>(F);
const DataLayout *DL = &F.getDataLayout();
TTI::TargetCostKind CostKind =
F.hasOptSize() ? TTI::TCK_CodeSize : TTI::TCK_RecipThroughput;
- VectorCombine Combiner(F, TTI, DT, AA, AC, SE, DL, CostKind,
- TryEarlyFoldsOnly);
+ VectorCombine Combiner(F, TTI, DT, AA, AC, DL, CostKind, TryEarlyFoldsOnly);
if (!Combiner.run())
return PreservedAnalyses::all();
PreservedAnalyses PA;
diff --git a/llvm/test/Transforms/VectorCombine/AArch64/shuffle-of-adjacent-loads.ll b/llvm/test/Transforms/VectorCombine/AArch64/shuffle-of-adjacent-loads.ll
deleted file mode 100644
index 68f6df532e2de..0000000000000
--- a/llvm/test/Transforms/VectorCombine/AArch64/shuffle-of-adjacent-loads.ll
+++ /dev/null
@@ -1,185 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt < %s -passes=vector-combine -S -mtriple=aarch64 | FileCheck %s
-
-define <8 x i32> @adjacent_loads_widen_v4i32_v8i32(ptr %p) {
-; CHECK-LABEL: define <8 x i32> @adjacent_loads_widen_v4i32_v8i32(
-; CHECK-SAME: ptr [[P:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i32>, ptr [[P]], align 4
-; CHECK-NEXT: [[S:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> poison, <8 x i32> <i32 0, i32 4, i32 1, i32 5, i32 2, i32 6, i32 3, i32 7>
-; CHECK-NEXT: ret <8 x i32> [[S]]
-;
- %p16 = getelementptr inbounds i8, ptr %p, i64 16
- %a = load <4 x i32>, ptr %p, align 4
- %b = load <4 x i32>, ptr %p16, align 4
- %s = shufflevector <4 x i32> %a, <4 x i32> %b, <8 x i32> <i32 0, i32 4, i32 1, i32 5, i32 2, i32 6, i32 3, i32 7>
- ret <8 x i32> %s
-}
-
-define void @adjacent_loads_multiple_shuffles_widen_v2i32_v4i32(ptr %p, ptr %d0, ptr %d1) {
-; CHECK-LABEL: define void @adjacent_loads_multiple_shuffles_widen_v2i32_v4i32(
-; CHECK-SAME: ptr [[P:%.*]], ptr [[D0:%.*]], ptr [[D1:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[P]], align 4
-; CHECK-NEXT: [[S0:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 3>
-; CHECK-NEXT: [[S1:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 1, i32 0>
-; CHECK-NEXT: store <4 x i32> [[S0]], ptr [[D0]], align 4
-; CHECK-NEXT: store <4 x i32> [[S1]], ptr [[D1]], align 4
-; CHECK-NEXT: ret void
-;
- %p8 = getelementptr inbounds i8, ptr %p, i64 8
- %a = load <2 x i32>, ptr %p, align 4
- %b = load <2 x i32>, ptr %p8, align 4
- %s0 = shufflevector <2 x i32> %a, <2 x i32> %b, <4 x i32> <i32 0, i32 1, i32 1, i32 3>
- %s1 = shufflevector <2 x i32> %a, <2 x i32> %b, <4 x i32> <i32 1, i32 2, i32 1, i32 0>
- store <4 x i32> %s0, ptr %d0, align 4
- store <4 x i32> %s1, ptr %d1, align 4
- ret void
-}
-
-define <8 x i32> @swapped_shuffle_ops_widen_v4i32_v8i32(ptr %p) {
-; CHECK-LABEL: define <8 x i32> @swapped_shuffle_ops_widen_v4i32_v8i32(
-; CHECK-SAME: ptr [[P:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i32>, ptr [[P]], align 4
-; CHECK-NEXT: [[S:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> poison, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
-; CHECK-NEXT: ret <8 x i32> [[S]]
-;
- %p16 = getelementptr inbounds i8, ptr %p, i64 16
- %a = load <4 x i32>, ptr %p, align 4
- %b = load <4 x i32>, ptr %p16, align 4
- %s = shufflevector <4 x i32> %b, <4 x i32> %a, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- ret <8 x i32> %s
-}
-
-define <8 x i32> @non_adjacent_loads_no_widen(ptr %p) {
-; CHECK-LABEL: define <8 x i32> @non_adjacent_loads_no_widen(
-; CHECK-SAME: ptr [[P:%.*]]) {
-; CHECK-NEXT: [[P17:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 17
-; CHECK-NEXT: [[A:%.*]] = load <4 x i32>, ptr [[P]], align 4
-; CHECK-NEXT: [[B:%.*]] = load <4 x i32>, ptr [[P17]], align 4
-; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[B]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
-; CHECK-NEXT: ret <8 x i32> [[S]]
-;
- %p17 = getelementptr inbounds i8, ptr %p, i64 17
- %a = load <4 x i32>, ptr %p, align 4
- %b = load <4 x i32>, ptr %p17, align 4
- %s = shufflevector <4 x i32> %a, <4 x i32> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- ret <8 x i32> %s
-}
-
-define <8 x i32> @non_shuffle_user_for_one_load_no_widen(ptr %p, ptr %d) {
-; CHECK-LABEL: define <8 x i32> @non_shuffle_user_for_one_load_no_widen(
-; CHECK-SAME: ptr [[P:%.*]], ptr [[D:%.*]]) {
-; CHECK-NEXT: [[P16:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 16
-; CHECK-NEXT: [[A:%.*]] = load <4 x i32>, ptr [[P]], align 4
-; CHECK-NEXT: [[B:%.*]] = load <4 x i32>, ptr [[P16]], align 4
-; CHECK-NEXT: store <4 x i32> [[A]], ptr [[D]], align 4
-; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[B]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
-; CHECK-NEXT: ret <8 x i32> [[S]]
-;
- %p16 = getelementptr inbounds i8, ptr %p, i64 16
- %a = load <4 x i32>, ptr %p, align 4
- %b = load <4 x i32>, ptr %p16, align 4
- store <4 x i32> %a, ptr %d, align 4
- %s = shufflevector <4 x i32> %a, <4 x i32> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- ret <8 x i32> %s
-}
-
-define <8 x i32> @mem_clobbered_by_store_no_widen(ptr %p, ptr %q) {
-; CHECK-LABEL: define <8 x i32> @mem_clobbered_by_store_no_widen(
-; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) {
-; CHECK-NEXT: [[P16:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 16
-; CHECK-NEXT: [[A:%.*]] = load <4 x i32>, ptr [[P]], align 4
-; CHECK-NEXT: store <4 x i32> zeroinitializer, ptr [[Q]], align 4
-; CHECK-NEXT: [[B:%.*]] = load <4 x i32>, ptr [[P16]], align 4
-; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> [[B]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
-; CHECK-NEXT: ret <8 x i32> [[S]]
-;
- %p16 = getelementptr inbounds i8, ptr %p, i64 16
- %a = load <4 x i32>, ptr %p, align 4
- store <4 x i32> zeroinitializer, ptr %q, align 4
- %b = load <4 x i32>, ptr %p16, align 4
- %s = shufflevector <4 x i32> %a, <4 x i32> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
- ret <8 x i32> %s
-}
-
-define <6 x i8> @no_padding_adjacent_loads_widen_v3i8_v6i8(ptr %p) {
-; CHECK-LABEL: define <6 x i8> @no_padding_adjacent_loads_widen_v3i8_v6i8(
-; CHECK-SAME: ptr [[P:%.*]]) {
-; CHECK-NEXT: [[S:%.*]] = load <6 x i8>, ptr [[P]], align 1
-; CHECK-NEXT: ret <6 x i8> [[S]]
-;
- %p3 = getelementptr inbounds i8, ptr %p, i64 3
- %a = load <3 x i8>, ptr %p, align 1
- %b = load <3 x i8>, ptr %p3, align 1
- %s = shufflevector <3 x i8> %a, <3 x i8> %b, <6 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5>
- ret <6 x i8> %s
-}
-
-define <12 x i1> @padding_bits_for_load_no_widen(ptr %p) {
-; CHECK-LABEL: define <12 x i1> @padding_bits_for_load_no_widen(
-; CHECK-SAME: ptr [[P:%.*]]) {
-; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 1
-; CHECK-NEXT: [[A:%.*]] = load <6 x i1>, ptr [[P]], align 1
-; CHECK-NEXT: [[B:%.*]] = load <6 x i1>, ptr [[P1]], align 1
-; CHECK-NEXT: [[S:%.*]] = shufflevector <6 x i1> [[A]], <6 x i1> [[B]], <12 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11>
-; CHECK-NEXT: ret <12 x i1> [[S]]
-;
- %p1 = getelementptr inbounds i8, ptr %p, i64 1
- %a = load <6 x i1>, ptr %p, align 1
- %b = load <6 x i1>, ptr %p1, align 1
- %s = shufflevector <6 x i1> %a, <6 x i1> %b, <12 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11>
- ret <12 x i1> %s
-}
-
-; Make sure we do not crash when the widened shuffle would have more than
-; INT_MAX elements in the concatenated operand space.
-define <2 x i8> @huge_adjacent_loads_no_widen(ptr %p) {
-; CHECK-LABEL: define <2 x i8> @huge_adjacent_loads_no_widen(
-; CHECK-SAME: ptr [[P:%.*]]) {
-; CHECK-NEXT: [[P_HI:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 1073741823
-; CHECK-NEXT: [[A:%.*]] = load <1073741823 x i8>, ptr [[P]], align 1073741824
-; CHECK-NEXT: [[B:%.*]] = load <1073741823 x i8>, ptr [[P_HI]], align 1073741824
-; CHECK-NEXT: [[S:%.*]] = shufflevector <1073741823 x i8> [[A]], <1073741823 x i8> [[B]], <2 x i32> <i32 0, i32 1>
-; CHECK-NEXT: ret <2 x i8> [[S]]
-;
- %p_hi = getelementptr inbounds i8, ptr %p, i64 1073741823
- %a = load <1073741823 x i8>, ptr %p
- %b = load <1073741823 x i8>, ptr %p_hi
- %s = shufflevector <1073741823 x i8> %a, <1073741823 x i8> %b, <2 x i32> <i32 0, i32 1>
- ret <2 x i8> %s
-}
-
-define <8 x i32> @adjacent_loads_different_metadata_widen_v4i32_v8i32(ptr %p) {
-; CHECK-LABEL: define <8 x i32> @adjacent_loads_different_metadata_widen_v4i32_v8i32(
-; CHECK-SAME: ptr [[P:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i32>, ptr [[P]], align 4, !tbaa [[CHAR_TBAA0:![0-9]+]], !alias.scope [[META3:![0-9]+]], !noalias [[META7:![0-9]+]]
-; CHECK-NEXT: [[S:%.*]] = shufflevector <8 x i32> [[TMP1]], <8 x i32> poison, <8 x i32> <i32 0, i32 4, i32 1, i32 5, i32 2, i32 6, i32 3, i32 7>
-; CHECK-NEXT: ret <8 x i32> [[S]]
-;
- %p16 = getelementptr inbounds i8, ptr %p, i64 16
- %a = load <4 x i32>, ptr %p, align 4, !tbaa !0, !alias.scope !5, !noalias !8
- %b = load <4 x i32>, ptr %p16, align 4, !tbaa !3, !alias.scope !8, !noalias !5
- %s = shufflevector <4 x i32> %a, <4 x i32> %b, <8 x i32> <i32 0, i32 4, i32 1, i32 5, i32 2, i32 6, i32 3, i32 7>
- ret <8 x i32> %s
-}
-
-!0 = !{!1, !1, i64 0}
-!1 = !{!"int", !2, i64 0}
-!2 = !{!"omnipotent char", !4, i64 0}
-!3 = !{!10, !10, i64 0}
-!10 = !{!"float", !2, i64 0}
-!4 = !{!"Simple C++ TBAA"}
-!5 = !{!6}
-!6 = distinct !{!6, !7, !"scopeA"}
-!7 = distinct !{!7, !"domain"}
-!8 = !{!9}
-!9 = distinct !{!9, !7, !"scopeB"}
-;.
-; CHECK: [[CHAR_TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
-; CHECK: [[META1]] = !{!"omnipotent char", [[META2:![0-9]+]], i64 0}
-; CHECK: [[META2]] = !{!"Simple C++ TBAA"}
-; CHECK: [[META3]] = !{[[META4:![0-9]+]], [[META6:![0-9]+]]}
-; CHECK: [[META4]] = distinct !{[[META4]], [[META5:![0-9]+]], !"scopeA"}
-; CHECK: [[META5]] = distinct !{[[META5]], !"domain"}
-; CHECK: [[META6]] = distinct !{[[META6]], [[META5]], !"scopeB"}
-; CHECK: [[META7]] = !{}
-;.
More information about the llvm-commits
mailing list