mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-21 09:56:48 +00:00
Revert "[SLP]Support revectorization of the previously vectorized scalars"
This reverts commit 0e3049c562ccdea288c3b1f3b3d1ce5992d284b0.
This commit is contained in:
parent
5748ddbab4
commit
1fcb75a5c0
llvm
lib/Transforms/Vectorize
test/Transforms/SLPVectorizer
@ -3783,6 +3783,11 @@ private:
|
||||
if (isa<PoisonValue>(V))
|
||||
continue;
|
||||
auto It = ScalarToTreeEntries.find(V);
|
||||
assert(
|
||||
(It == ScalarToTreeEntries.end() ||
|
||||
(It->getSecond().size() == 1 && It->getSecond().front() == Last) ||
|
||||
doesNotNeedToBeScheduled(V)) &&
|
||||
"Scalar already in tree!");
|
||||
if (It == ScalarToTreeEntries.end()) {
|
||||
ScalarToTreeEntries.try_emplace(V).first->getSecond().push_back(Last);
|
||||
(void)Processed.insert(V);
|
||||
@ -4042,9 +4047,6 @@ private:
|
||||
private:
|
||||
/// Used for getting a "good" final ordering of instructions.
|
||||
int SchedulingPriority = 0;
|
||||
/// True if this instruction (or bundle) is scheduled (or considered as
|
||||
/// scheduled in the dry-run).
|
||||
bool IsScheduled = false;
|
||||
/// The kind of the ScheduleEntity.
|
||||
const Kind K = Kind::ScheduleData;
|
||||
|
||||
@ -4058,10 +4060,6 @@ private:
|
||||
return SD->isReady();
|
||||
return cast<ScheduleBundle>(this)->isReady();
|
||||
}
|
||||
/// Gets/sets if the bundle is scheduled.
|
||||
bool isScheduled() const { return IsScheduled; }
|
||||
void setScheduled(bool Scheduled) { IsScheduled = Scheduled; }
|
||||
|
||||
static bool classof(const ScheduleEntity *) { return true; }
|
||||
};
|
||||
|
||||
@ -4134,6 +4132,10 @@ private:
|
||||
IsScheduled = false;
|
||||
}
|
||||
|
||||
/// Gets/sets if the bundle is scheduled.
|
||||
bool isScheduled() const { return IsScheduled; }
|
||||
void setScheduled(bool Scheduled) { IsScheduled = Scheduled; }
|
||||
|
||||
/// Gets the number of unscheduled dependencies.
|
||||
int getUnscheduledDeps() const { return UnscheduledDeps; }
|
||||
/// Gets the number of dependencies.
|
||||
@ -4208,6 +4210,10 @@ private:
|
||||
/// for scheduling.
|
||||
/// Note that this is negative as long as Dependencies is not calculated.
|
||||
int UnscheduledDeps = InvalidDeps;
|
||||
|
||||
/// True if this instruction is scheduled (or considered as scheduled in the
|
||||
/// dry-run).
|
||||
bool IsScheduled = false;
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
@ -4252,6 +4258,11 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
bool isScheduled() const {
|
||||
return all_of(Bundle,
|
||||
[](const ScheduleData *SD) { return SD->isScheduled(); });
|
||||
}
|
||||
|
||||
/// Returns the number of unscheduled dependencies in the bundle.
|
||||
int unscheduledDepsInBundle() const {
|
||||
assert(*this && "bundle must not be empty");
|
||||
@ -4508,22 +4519,12 @@ private:
|
||||
ProcessBundleMember(SD, nullptr);
|
||||
} else {
|
||||
ScheduleBundle &Bundle = *cast<ScheduleBundle>(Data);
|
||||
Bundle.setScheduled(/*Scheduled=*/true);
|
||||
for_each(Bundle.getBundle(), [](ScheduleData *SD) {
|
||||
SD->setScheduled(/*Scheduled=*/true);
|
||||
});
|
||||
LLVM_DEBUG(dbgs() << "SLP: schedule " << Bundle << "\n");
|
||||
auto AreAllBundlesScheduled = [&](const ScheduleData *SD) {
|
||||
ArrayRef<ScheduleBundle *> SDBundles =
|
||||
getScheduleBundles(SD->getInst());
|
||||
return !SDBundles.empty() &&
|
||||
all_of(SDBundles, [&](const ScheduleBundle *SDBundle) {
|
||||
return SDBundle->isScheduled();
|
||||
});
|
||||
};
|
||||
for (ScheduleData *SD : Bundle.getBundle()) {
|
||||
if (AreAllBundlesScheduled(SD)) {
|
||||
SD->setScheduled(/*Scheduled=*/true);
|
||||
ProcessBundleMember(SD, &Bundle);
|
||||
}
|
||||
}
|
||||
for (ScheduleData *SD : Bundle.getBundle())
|
||||
ProcessBundleMember(SD, &Bundle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4554,11 +4555,10 @@ private:
|
||||
SD->verify();
|
||||
}
|
||||
|
||||
assert(all_of(ReadyInsts,
|
||||
[](const ScheduleEntity *Bundle) {
|
||||
return Bundle->isReady();
|
||||
}) &&
|
||||
"item in ready list not ready?");
|
||||
for (const ScheduleEntity *Bundle : ReadyInsts) {
|
||||
assert(Bundle->isReady() && "item in ready list not ready?");
|
||||
(void)Bundle;
|
||||
}
|
||||
}
|
||||
|
||||
/// Put all instructions into the ReadyList which are ready for scheduling.
|
||||
@ -7440,7 +7440,7 @@ void BoUpSLP::buildExternalUses(
|
||||
// Some in-tree scalars will remain as scalar in vectorized
|
||||
// instructions. If that is the case, the one in FoundLane will
|
||||
// be used.
|
||||
if (all_of(UseEntries, [&](TreeEntry *UseEntry) {
|
||||
if (any_of(UseEntries, [&](TreeEntry *UseEntry) {
|
||||
return UseEntry->State == TreeEntry::ScatterVectorize ||
|
||||
!doesInTreeUserNeedToExtract(
|
||||
Scalar, getRootEntryInstruction(*UseEntry), TLI,
|
||||
@ -9488,47 +9488,14 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
|
||||
// We now know that this is a vector of instructions of the same type from
|
||||
// the same block.
|
||||
|
||||
// Check that none of the instructions in the bundle are already in the tree
|
||||
// and the node may be not profitable for the vectorization as the small
|
||||
// alternate node.
|
||||
if (S && S.isAltShuffle()) {
|
||||
auto GetNumVectorizedExtracted = [&]() {
|
||||
APInt Extracted = APInt::getZero(VL.size());
|
||||
APInt Vectorized = APInt::getAllOnes(VL.size());
|
||||
for (auto [Idx, V] : enumerate(VL)) {
|
||||
auto *I = dyn_cast<Instruction>(V);
|
||||
if (!I || doesNotNeedToBeScheduled(I) ||
|
||||
all_of(I->operands(), [&](const Use &U) {
|
||||
return isa<ExtractElementInst>(U.get());
|
||||
}))
|
||||
continue;
|
||||
if (isVectorized(I))
|
||||
Vectorized.clearBit(Idx);
|
||||
else if (!I->hasOneUser() && !areAllUsersVectorized(I, UserIgnoreList))
|
||||
Extracted.setBit(Idx);
|
||||
}
|
||||
return std::make_pair(Vectorized, Extracted);
|
||||
};
|
||||
auto [Vectorized, Extracted] = GetNumVectorizedExtracted();
|
||||
constexpr TTI::TargetCostKind Kind = TTI::TCK_RecipThroughput;
|
||||
bool PreferScalarize = !Vectorized.isAllOnes() && VL.size() == 2;
|
||||
if (!Vectorized.isAllOnes() && !PreferScalarize) {
|
||||
// Rough cost estimation, if the vector code (+ potential extracts) is
|
||||
// more profitable than the scalar + buildvector.
|
||||
Type *ScalarTy = VL.front()->getType();
|
||||
auto *VecTy = getWidenedType(ScalarTy, VL.size());
|
||||
InstructionCost VectorizeCostEstimate =
|
||||
::getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, VecTy, {}, Kind) +
|
||||
::getScalarizationOverhead(*TTI, ScalarTy, VecTy, Extracted,
|
||||
/*Insert=*/false, /*Extract=*/true, Kind);
|
||||
InstructionCost ScalarizeCostEstimate =
|
||||
::getScalarizationOverhead(*TTI, ScalarTy, VecTy, Vectorized,
|
||||
/*Insert=*/true, /*Extract=*/false, Kind);
|
||||
PreferScalarize = VectorizeCostEstimate > ScalarizeCostEstimate;
|
||||
}
|
||||
if (PreferScalarize) {
|
||||
LLVM_DEBUG(dbgs() << "SLP: The instructions are in tree and alternate "
|
||||
"node is not profitable.\n");
|
||||
// Check that none of the instructions in the bundle are already in the tree.
|
||||
for (Value *V : VL) {
|
||||
if ((!IsScatterVectorizeUserTE && !isa<Instruction>(V)) ||
|
||||
doesNotNeedToBeScheduled(V))
|
||||
continue;
|
||||
if (isVectorized(V)) {
|
||||
LLVM_DEBUG(dbgs() << "SLP: The instruction (" << *V
|
||||
<< ") is already in tree.\n");
|
||||
if (TryToFindDuplicates(S)) {
|
||||
auto Invalid = ScheduleBundle::invalid();
|
||||
newTreeEntry(VL, Invalid /*not vectorized*/, S, UserTreeIdx,
|
||||
@ -9617,6 +9584,8 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
|
||||
#endif
|
||||
if (!BundlePtr || (*BundlePtr && !*BundlePtr.value())) {
|
||||
LLVM_DEBUG(dbgs() << "SLP: We are not able to schedule this bundle!\n");
|
||||
assert((!BS.getScheduleData(VL0) || BS.getScheduleBundles(VL0).empty()) &&
|
||||
"tryScheduleBundle should not create bundle on failure");
|
||||
// Last chance to try to vectorize alternate node.
|
||||
if (S.isAltShuffle() && ReuseShuffleIndices.empty() &&
|
||||
TrySplitNode(SmallNodeSize, S))
|
||||
@ -12405,7 +12374,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals,
|
||||
SmallBitVector UsedScalars(Sz, false);
|
||||
for (unsigned I = 0; I < Sz; ++I) {
|
||||
if (isa<Instruction>(UniqueValues[I]) &&
|
||||
getTreeEntries(UniqueValues[I]).front() == E)
|
||||
is_contained(getTreeEntries(UniqueValues[I]), E))
|
||||
continue;
|
||||
UsedScalars.set(I);
|
||||
}
|
||||
@ -13975,7 +13944,6 @@ InstructionCost BoUpSLP::getTreeCost(ArrayRef<Value *> VectorizedVals,
|
||||
for (ExternalUser &EU : ExternalUses) {
|
||||
ScalarUserAndIdx.emplace_back(EU.Scalar, EU.User, EU.Lane);
|
||||
}
|
||||
SmallDenseSet<std::pair<Value *, Value *>, 8> CheckedScalarUser;
|
||||
for (ExternalUser &EU : ExternalUses) {
|
||||
// Uses by ephemeral values are free (because the ephemeral value will be
|
||||
// removed prior to code generation, and so the extraction will be
|
||||
@ -13983,12 +13951,6 @@ InstructionCost BoUpSLP::getTreeCost(ArrayRef<Value *> VectorizedVals,
|
||||
if (EphValues.count(EU.User))
|
||||
continue;
|
||||
|
||||
// Check if the scalar for the given user or all users is accounted already.
|
||||
if (!CheckedScalarUser.insert(std::make_pair(EU.Scalar, EU.User)).second ||
|
||||
(EU.User &&
|
||||
CheckedScalarUser.contains(std::make_pair(EU.Scalar, nullptr))))
|
||||
continue;
|
||||
|
||||
// Used in unreachable blocks or in EH pads (rarely executed) or is
|
||||
// terminated with unreachable instruction.
|
||||
if (BasicBlock *UserParent =
|
||||
@ -14691,16 +14653,10 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry(
|
||||
PHINode *UserPHI = UseEI.UserTE->State != TreeEntry::SplitVectorize
|
||||
? dyn_cast<PHINode>(UseEI.UserTE->getMainOp())
|
||||
: nullptr;
|
||||
Instruction *InsertPt =
|
||||
const Instruction *InsertPt =
|
||||
UserPHI ? UserPHI->getIncomingBlock(UseEI.EdgeIdx)->getTerminator()
|
||||
: &getLastInstructionInBundle(UseEI.UserTE);
|
||||
if (TEInsertPt == InsertPt) {
|
||||
// If the schedulable insertion point is used in multiple entries - just
|
||||
// exit, no known ordering at this point, available only after real
|
||||
// scheduling.
|
||||
if (!doesNotNeedToBeScheduled(InsertPt) &&
|
||||
(TEUseEI.UserTE != UseEI.UserTE || TEUseEI.EdgeIdx < UseEI.EdgeIdx))
|
||||
continue;
|
||||
// If the users are the PHI nodes with the same incoming blocks - skip.
|
||||
if (TEUseEI.UserTE->State == TreeEntry::Vectorize &&
|
||||
TEUseEI.UserTE->getOpcode() == Instruction::PHI &&
|
||||
@ -15426,29 +15382,19 @@ Instruction &BoUpSLP::getLastInstructionInBundle(const TreeEntry *E) {
|
||||
|
||||
// Set the insert point to the beginning of the basic block if the entry
|
||||
// should not be scheduled.
|
||||
auto FindScheduleBundle = [&](const TreeEntry *E) -> const ScheduleBundle * {
|
||||
const auto *It = BlocksSchedules.find(BB);
|
||||
auto IsNotScheduledEntry = [&](const TreeEntry *E) {
|
||||
if (E->isGather())
|
||||
return nullptr;
|
||||
return false;
|
||||
// Found previously that the instruction do not need to be scheduled.
|
||||
const auto *It = BlocksSchedules.find(BB);
|
||||
if (It == BlocksSchedules.end())
|
||||
return nullptr;
|
||||
for (Value *V : E->Scalars) {
|
||||
auto *I = dyn_cast<Instruction>(V);
|
||||
if (!I || isa<PHINode>(I) || doesNotNeedToBeScheduled(I))
|
||||
continue;
|
||||
ArrayRef<ScheduleBundle *> Bundles = It->second->getScheduleBundles(I);
|
||||
if (Bundles.empty())
|
||||
continue;
|
||||
const auto *It = find_if(
|
||||
Bundles, [&](ScheduleBundle *B) { return B->getTreeEntry() == E; });
|
||||
if (It != Bundles.end())
|
||||
return *It;
|
||||
}
|
||||
return nullptr;
|
||||
return It == BlocksSchedules.end() || all_of(E->Scalars, [&](Value *V) {
|
||||
if (!isa<Instruction>(V))
|
||||
return true;
|
||||
return It->second->getScheduleBundles(V).empty();
|
||||
});
|
||||
};
|
||||
const ScheduleBundle *Bundle = FindScheduleBundle(E);
|
||||
if (!E->isGather() && !Bundle) {
|
||||
if (IsNotScheduledEntry(E) ||
|
||||
(!E->isGather() && all_of(E->Scalars, isVectorLikeInstWithConstOps))) {
|
||||
if ((E->getOpcode() == Instruction::GetElementPtr &&
|
||||
any_of(E->Scalars,
|
||||
[](Value *V) {
|
||||
@ -15474,10 +15420,19 @@ Instruction &BoUpSLP::getLastInstructionInBundle(const TreeEntry *E) {
|
||||
// scheduled, and the last instruction is VL.back(). So we start with
|
||||
// VL.back() and iterate over schedule data until we reach the end of the
|
||||
// bundle. The end of the bundle is marked by null ScheduleData.
|
||||
if (Bundle) {
|
||||
assert(!E->isGather() && "Gathered instructions should not be scheduled");
|
||||
Res = Bundle->getBundle().back()->getInst();
|
||||
return *Res;
|
||||
if (It != BlocksSchedules.end() && !E->isGather()) {
|
||||
Value *V = E->isOneOf(E->Scalars.back());
|
||||
if (doesNotNeedToBeScheduled(V))
|
||||
V = *find_if_not(E->Scalars, doesNotNeedToBeScheduled);
|
||||
if (ArrayRef<ScheduleBundle *> Bundles = It->second->getScheduleBundles(V);
|
||||
!Bundles.empty()) {
|
||||
const auto *It = find_if(
|
||||
Bundles, [&](ScheduleBundle *B) { return B->getTreeEntry() == E; });
|
||||
assert(It != Bundles.end() && "Failed to find bundle");
|
||||
Res = (*It)->getBundle().back()->getInst();
|
||||
return *Res;
|
||||
}
|
||||
assert(E->getOpcode() == Instruction::PHI && "Expected PHI");
|
||||
}
|
||||
|
||||
// LastInst can still be null at this point if there's either not an entry
|
||||
@ -16230,10 +16185,10 @@ BoUpSLP::getMatchedVectorizedOperand(const TreeEntry *E, unsigned NodeIdx,
|
||||
const InstructionsState &S) {
|
||||
if (!S)
|
||||
return nullptr;
|
||||
for (TreeEntry *TE : ScalarToTreeEntries.lookup(S.getMainOp()))
|
||||
if (TE->UserTreeIndex.UserTE == E && TE->UserTreeIndex.EdgeIdx == NodeIdx &&
|
||||
TE->isSame(VL))
|
||||
return TE;
|
||||
if (TreeEntry *VE = getSameValuesTreeEntry(S.getMainOp(), VL);
|
||||
VE && VE->UserTreeIndex.UserTE == E &&
|
||||
VE->UserTreeIndex.EdgeIdx == NodeIdx)
|
||||
return VE;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -17926,13 +17881,13 @@ Value *BoUpSLP::vectorizeTree(
|
||||
const ExtraValueToDebugLocsMap &ExternallyUsedValues,
|
||||
Instruction *ReductionRoot,
|
||||
ArrayRef<std::tuple<Value *, unsigned, bool>> VectorValuesAndScales) {
|
||||
// Clean Entry-to-LastInstruction table. It can be affected after scheduling,
|
||||
// need to rebuild it.
|
||||
EntryToLastInstruction.clear();
|
||||
// All blocks must be scheduled before any instructions are inserted.
|
||||
for (auto &BSIter : BlocksSchedules) {
|
||||
scheduleBlock(BSIter.second.get());
|
||||
}
|
||||
// Clean Entry-to-LastInstruction table. It can be affected after scheduling,
|
||||
// need to rebuild it.
|
||||
EntryToLastInstruction.clear();
|
||||
|
||||
if (ReductionRoot)
|
||||
Builder.SetInsertPoint(ReductionRoot->getParent(),
|
||||
@ -18774,10 +18729,18 @@ BoUpSLP::BlockScheduling::tryScheduleBundle(ArrayRef<Value *> VL, BoUpSLP *SLP,
|
||||
// dependencies. As soon as the bundle is "ready" it means that there are no
|
||||
// cyclic dependencies and we can schedule it. Note that's important that we
|
||||
// don't "schedule" the bundle yet.
|
||||
SmallPtrSet<const ScheduleBundle *, 16> Visited;
|
||||
while (((!Bundle && ReSchedule) || (Bundle && !Bundle.isReady())) &&
|
||||
!ReadyInsts.empty()) {
|
||||
ScheduleEntity *Picked = ReadyInsts.pop_back_val();
|
||||
assert(Picked->isReady() && "must be ready to schedule");
|
||||
const auto *PickedBundle = dyn_cast<ScheduleBundle>(Picked);
|
||||
if (PickedBundle && !Visited.insert(PickedBundle).second) {
|
||||
assert(PickedBundle->isScheduled() && "bundle must be scheduled");
|
||||
continue;
|
||||
}
|
||||
assert((PickedBundle ? PickedBundle->isReady()
|
||||
: cast<ScheduleData>(Picked)->isReady()) &&
|
||||
"must be ready to schedule");
|
||||
schedule(Picked, ReadyInsts);
|
||||
if (Picked == &Bundle)
|
||||
break;
|
||||
@ -18831,16 +18794,8 @@ BoUpSLP::BlockScheduling::tryScheduleBundle(ArrayRef<Value *> VL, BoUpSLP *SLP,
|
||||
TryScheduleBundleImpl(ReSchedule, Bundle);
|
||||
if (!Bundle.isReady()) {
|
||||
for (ScheduleData *BD : Bundle.getBundle()) {
|
||||
if (BD->isReady()) {
|
||||
ArrayRef<ScheduleBundle *> Bundles = getScheduleBundles(BD->getInst());
|
||||
if (Bundles.empty()) {
|
||||
ReadyInsts.insert(BD);
|
||||
continue;
|
||||
}
|
||||
for (ScheduleBundle *B : Bundles)
|
||||
if (B->isReady())
|
||||
ReadyInsts.insert(B);
|
||||
}
|
||||
if (BD->isReady())
|
||||
ReadyInsts.insert(BD);
|
||||
}
|
||||
ScheduledBundlesList.pop_back();
|
||||
for (Value *V : VL) {
|
||||
@ -19171,11 +19126,6 @@ void BoUpSLP::BlockScheduling::resetSchedule() {
|
||||
SD->setScheduled(/*Scheduled=*/false);
|
||||
SD->resetUnscheduledDeps();
|
||||
}
|
||||
for (ScheduleBundle *Bundle : getScheduleBundles(I)) {
|
||||
assert(isInSchedulingRegion(*Bundle) &&
|
||||
"ScheduleBundle not in scheduling region");
|
||||
Bundle->setScheduled(/*Scheduled=*/false);
|
||||
}
|
||||
}
|
||||
ReadyInsts.clear();
|
||||
}
|
||||
@ -19234,7 +19184,6 @@ void BoUpSLP::scheduleBlock(BlockScheduling *BS) {
|
||||
Instruction *LastScheduledInst = BS->ScheduleEnd;
|
||||
|
||||
// Do the "real" scheduling.
|
||||
SmallPtrSet<Instruction *, 16> Scheduled;
|
||||
while (!ReadyInsts.empty()) {
|
||||
auto *Picked = *ReadyInsts.begin();
|
||||
ReadyInsts.erase(ReadyInsts.begin());
|
||||
@ -19244,14 +19193,10 @@ void BoUpSLP::scheduleBlock(BlockScheduling *BS) {
|
||||
if (auto *Bundle = dyn_cast<ScheduleBundle>(Picked)) {
|
||||
for (const ScheduleData *BundleMember : Bundle->getBundle()) {
|
||||
Instruction *PickedInst = BundleMember->getInst();
|
||||
if (!Scheduled.insert(PickedInst).second)
|
||||
continue;
|
||||
if (PickedInst->getNextNonDebugInstruction() != LastScheduledInst)
|
||||
PickedInst->moveAfter(LastScheduledInst->getPrevNode());
|
||||
LastScheduledInst = PickedInst;
|
||||
}
|
||||
EntryToLastInstruction.try_emplace(Bundle->getTreeEntry(),
|
||||
LastScheduledInst);
|
||||
} else {
|
||||
auto *SD = cast<ScheduleData>(Picked);
|
||||
Instruction *PickedInst = SD->getInst();
|
||||
|
@ -39,26 +39,28 @@ define void @test() {
|
||||
; CHECK: [[BB77]]:
|
||||
; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <16 x float> [[TMP11]], <16 x float> poison, <8 x i32> <i32 poison, i32 poison, i32 poison, i32 poison, i32 14, i32 15, i32 poison, i32 poison>
|
||||
; CHECK-NEXT: [[TMP17:%.*]] = insertelement <8 x float> [[TMP12]], float [[I70]], i32 0
|
||||
; CHECK-NEXT: [[TMP14:%.*]] = insertelement <8 x float> poison, float [[I70]], i32 1
|
||||
; CHECK-NEXT: [[TMP19:%.*]] = insertelement <8 x float> [[TMP14]], float [[I68]], i32 2
|
||||
; CHECK-NEXT: [[TMP16:%.*]] = insertelement <8 x float> [[TMP19]], float [[I66]], i32 3
|
||||
; CHECK-NEXT: [[TMP20:%.*]] = insertelement <8 x float> [[TMP16]], float [[I67]], i32 6
|
||||
; CHECK-NEXT: [[TMP21:%.*]] = insertelement <8 x float> [[TMP20]], float [[I69]], i32 7
|
||||
; CHECK-NEXT: [[TMP30:%.*]] = insertelement <2 x float> poison, float [[I68]], i32 0
|
||||
; CHECK-NEXT: [[TMP31:%.*]] = insertelement <2 x float> [[TMP30]], float [[I66]], i32 1
|
||||
; CHECK-NEXT: [[TMP39:%.*]] = shufflevector <16 x float> [[TMP25]], <16 x float> poison, <16 x i32> <i32 poison, i32 poison, i32 3, i32 2, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
|
||||
; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <16 x float> [[TMP39]], <16 x float> [[TMP25]], <16 x i32> <i32 poison, i32 poison, i32 2, i32 3, i32 18, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 19, i32 poison, i32 poison>
|
||||
; CHECK-NEXT: br label %[[BB78:.*]]
|
||||
; CHECK: [[BB78]]:
|
||||
; CHECK-NEXT: [[TMP15:%.*]] = phi <8 x float> [ [[TMP17]], %[[BB77]] ], [ [[TMP36:%.*]], %[[BB78]] ]
|
||||
; CHECK-NEXT: [[TMP22:%.*]] = phi <8 x float> [ [[TMP21]], %[[BB77]] ], [ [[TMP31:%.*]], %[[BB78]] ]
|
||||
; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <8 x float> [[TMP22]], <8 x float> poison, <16 x i32> <i32 0, i32 3, i32 1, i32 2, i32 3, i32 0, i32 2, i32 3, i32 2, i32 6, i32 2, i32 3, i32 0, i32 7, i32 6, i32 6>
|
||||
; CHECK-NEXT: [[TMP16:%.*]] = phi <2 x float> [ [[TMP31]], %[[BB77]] ], [ [[TMP37:%.*]], %[[BB78]] ]
|
||||
; CHECK-NEXT: [[TMP38:%.*]] = shufflevector <8 x float> [[TMP15]], <8 x float> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 1, i32 0, i32 3, i32 1, i32 3, i32 5, i32 3, i32 1, i32 0, i32 4, i32 5, i32 5>
|
||||
; CHECK-NEXT: [[TMP21:%.*]] = shufflevector <8 x float> [[TMP15]], <8 x float> poison, <16 x i32> <i32 2, i32 poison, i32 0, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
|
||||
; CHECK-NEXT: [[TMP20:%.*]] = shufflevector <2 x float> [[TMP16]], <2 x float> poison, <16 x i32> <i32 0, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
|
||||
; CHECK-NEXT: [[TMP23:%.*]] = shufflevector <16 x float> [[TMP21]], <16 x float> [[TMP20]], <16 x i32> <i32 0, i32 17, i32 2, i32 16, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
|
||||
; CHECK-NEXT: [[TMP22:%.*]] = shufflevector <8 x float> [[TMP15]], <8 x float> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
|
||||
; CHECK-NEXT: [[TMP40:%.*]] = shufflevector <16 x float> [[TMP23]], <16 x float> [[TMP22]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 18, i32 6, i32 7, i32 8, i32 20, i32 10, i32 11, i32 12, i32 21, i32 14, i32 15>
|
||||
; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <16 x float> [[TMP40]], <16 x float> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 1, i32 5, i32 3, i32 1, i32 3, i32 9, i32 3, i32 1, i32 5, i32 13, i32 9, i32 9>
|
||||
; CHECK-NEXT: [[TMP18:%.*]] = fmul fast <16 x float> [[TMP24]], [[TMP13]]
|
||||
; CHECK-NEXT: [[TMP26:%.*]] = fmul fast <16 x float> [[TMP38]], [[TMP25]]
|
||||
; CHECK-NEXT: [[TMP27:%.*]] = fadd fast <16 x float> [[TMP26]], [[TMP18]]
|
||||
; CHECK-NEXT: [[TMP28:%.*]] = fadd fast <16 x float> [[TMP27]], poison
|
||||
; CHECK-NEXT: [[TMP29:%.*]] = fadd fast <16 x float> [[TMP28]], poison
|
||||
; CHECK-NEXT: [[TMP36]] = shufflevector <16 x float> [[TMP29]], <16 x float> poison, <8 x i32> <i32 5, i32 11, i32 12, i32 10, i32 14, i32 15, i32 poison, i32 poison>
|
||||
; CHECK-NEXT: [[TMP31]] = shufflevector <16 x float> [[TMP29]], <16 x float> poison, <8 x i32> <i32 12, i32 5, i32 6, i32 7, i32 poison, i32 poison, i32 14, i32 15>
|
||||
; CHECK-NEXT: [[TMP37]] = shufflevector <16 x float> [[TMP29]], <16 x float> poison, <2 x i32> <i32 6, i32 7>
|
||||
; CHECK-NEXT: br i1 poison, label %[[BB78]], label %[[BB167]]
|
||||
; CHECK: [[BB167]]:
|
||||
; CHECK-NEXT: [[TMP32:%.*]] = phi <16 x float> [ [[TMP11]], %[[BB64]] ], [ [[TMP29]], %[[BB78]] ]
|
||||
|
@ -123,17 +123,18 @@ define <4 x i32> @build_vec_v4i32_reuse_0(<2 x i32> %v0, <2 x i32> %v1) {
|
||||
|
||||
define <4 x i32> @build_vec_v4i32_reuse_1(<2 x i32> %v0, <2 x i32> %v1) {
|
||||
; CHECK-LABEL: @build_vec_v4i32_reuse_1(
|
||||
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x i32> [[V0:%.*]], <2 x i32> poison, <4 x i32> <i32 0, i32 0, i32 0, i32 1>
|
||||
; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x i32> [[V1:%.*]], <2 x i32> poison, <4 x i32> <i32 0, i32 0, i32 0, i32 1>
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = add <4 x i32> [[TMP6]], [[TMP7]]
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = xor <4 x i32> [[TMP6]], [[TMP7]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i32> [[V0:%.*]], <2 x i32> poison, <4 x i32> <i32 0, i32 0, i32 0, i32 1>
|
||||
; CHECK-NEXT: [[V0_1:%.*]] = extractelement <2 x i32> [[V0]], i64 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i32> [[V1:%.*]], <2 x i32> poison, <4 x i32> <i32 0, i32 0, i32 0, i32 1>
|
||||
; CHECK-NEXT: [[V1_1:%.*]] = extractelement <2 x i32> [[V1]], i64 1
|
||||
; CHECK-NEXT: [[TMP0_1:%.*]] = add i32 [[V0_1]], [[V1_1]]
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = add <4 x i32> [[TMP1]], [[TMP2]]
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = xor <4 x i32> [[TMP1]], [[TMP2]]
|
||||
; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i32> [[V0]], <2 x i32> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 0>
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i32> [[V1]], <2 x i32> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 0>
|
||||
; CHECK-NEXT: [[TMP8:%.*]] = add <4 x i32> [[TMP1]], [[TMP2]]
|
||||
; CHECK-NEXT: [[TMP11:%.*]] = xor <4 x i32> [[TMP1]], [[TMP2]]
|
||||
; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <4 x i32> [[TMP8]], <4 x i32> [[TMP11]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
|
||||
; CHECK-NEXT: [[TMP9:%.*]] = sub <4 x i32> [[TMP5]], [[TMP10]]
|
||||
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <4 x i32> [[TMP5]], <4 x i32> poison, <4 x i32> <i32 poison, i32 poison, i32 3, i32 2>
|
||||
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x i32> [[TMP6]], i32 [[TMP0_1]], i64 0
|
||||
; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <4 x i32> [[TMP7]], <4 x i32> poison, <4 x i32> <i32 0, i32 0, i32 2, i32 3>
|
||||
; CHECK-NEXT: [[TMP9:%.*]] = sub <4 x i32> [[TMP5]], [[TMP8]]
|
||||
; CHECK-NEXT: ret <4 x i32> [[TMP9]]
|
||||
;
|
||||
%v0.0 = extractelement <2 x i32> %v0, i32 0
|
||||
|
@ -123,17 +123,18 @@ define <4 x i32> @build_vec_v4i32_reuse_0(<2 x i32> %v0, <2 x i32> %v1) {
|
||||
|
||||
define <4 x i32> @build_vec_v4i32_reuse_1(<2 x i32> %v0, <2 x i32> %v1) {
|
||||
; CHECK-LABEL: @build_vec_v4i32_reuse_1(
|
||||
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x i32> [[V0:%.*]], <2 x i32> poison, <4 x i32> <i32 0, i32 0, i32 0, i32 1>
|
||||
; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x i32> [[V1:%.*]], <2 x i32> poison, <4 x i32> <i32 0, i32 0, i32 0, i32 1>
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = add <4 x i32> [[TMP6]], [[TMP7]]
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = xor <4 x i32> [[TMP6]], [[TMP7]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i32> [[V0:%.*]], <2 x i32> poison, <4 x i32> <i32 0, i32 0, i32 0, i32 1>
|
||||
; CHECK-NEXT: [[V0_1:%.*]] = extractelement <2 x i32> [[V0]], i64 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i32> [[V1:%.*]], <2 x i32> poison, <4 x i32> <i32 0, i32 0, i32 0, i32 1>
|
||||
; CHECK-NEXT: [[V1_1:%.*]] = extractelement <2 x i32> [[V1]], i64 1
|
||||
; CHECK-NEXT: [[TMP0_1:%.*]] = add i32 [[V0_1]], [[V1_1]]
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = add <4 x i32> [[TMP1]], [[TMP2]]
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = xor <4 x i32> [[TMP1]], [[TMP2]]
|
||||
; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> [[TMP4]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i32> [[V0]], <2 x i32> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 0>
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i32> [[V1]], <2 x i32> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 0>
|
||||
; CHECK-NEXT: [[TMP8:%.*]] = add <4 x i32> [[TMP1]], [[TMP2]]
|
||||
; CHECK-NEXT: [[TMP11:%.*]] = xor <4 x i32> [[TMP1]], [[TMP2]]
|
||||
; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <4 x i32> [[TMP8]], <4 x i32> [[TMP11]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>
|
||||
; CHECK-NEXT: [[TMP9:%.*]] = sub <4 x i32> [[TMP5]], [[TMP10]]
|
||||
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <4 x i32> [[TMP5]], <4 x i32> poison, <4 x i32> <i32 poison, i32 poison, i32 3, i32 2>
|
||||
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x i32> [[TMP6]], i32 [[TMP0_1]], i64 0
|
||||
; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <4 x i32> [[TMP7]], <4 x i32> poison, <4 x i32> <i32 0, i32 0, i32 2, i32 3>
|
||||
; CHECK-NEXT: [[TMP9:%.*]] = sub <4 x i32> [[TMP5]], [[TMP8]]
|
||||
; CHECK-NEXT: ret <4 x i32> [[TMP9]]
|
||||
;
|
||||
%v0.0 = extractelement <2 x i32> %v0, i32 0
|
||||
|
@ -206,15 +206,15 @@ define i32 @reorder_indices_1(float %0) {
|
||||
; POW2-ONLY-SAME: float [[TMP0:%.*]]) {
|
||||
; POW2-ONLY-NEXT: entry:
|
||||
; POW2-ONLY-NEXT: [[NOR1:%.*]] = alloca [0 x [3 x float]], i32 0, align 4
|
||||
; POW2-ONLY-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr float, ptr [[NOR1]], i64 1
|
||||
; POW2-ONLY-NEXT: [[ARRAYIDX2_I265:%.*]] = getelementptr float, ptr [[NOR1]], i64 2
|
||||
; POW2-ONLY-NEXT: [[TMP1:%.*]] = load float, ptr [[ARRAYIDX2_I265]], align 4
|
||||
; POW2-ONLY-NEXT: [[TMP7:%.*]] = load <2 x float>, ptr [[ARRAYIDX_I]], align 4
|
||||
; POW2-ONLY-NEXT: [[TMP2:%.*]] = load <2 x float>, ptr [[NOR1]], align 4
|
||||
; POW2-ONLY-NEXT: [[TMP3:%.*]] = extractelement <2 x float> [[TMP2]], i32 0
|
||||
; POW2-ONLY-NEXT: [[TMP4:%.*]] = fneg float [[TMP3]]
|
||||
; POW2-ONLY-NEXT: [[NEG11_I:%.*]] = fmul float [[TMP4]], [[TMP0]]
|
||||
; POW2-ONLY-NEXT: [[TMP5:%.*]] = call float @llvm.fmuladd.f32(float [[TMP1]], float 0.000000e+00, float [[NEG11_I]])
|
||||
; POW2-ONLY-NEXT: [[TMP6:%.*]] = shufflevector <2 x float> [[TMP2]], <2 x float> poison, <2 x i32> <i32 1, i32 poison>
|
||||
; POW2-ONLY-NEXT: [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[TMP1]], i32 1
|
||||
; POW2-ONLY-NEXT: [[TMP8:%.*]] = fneg <2 x float> [[TMP7]]
|
||||
; POW2-ONLY-NEXT: [[TMP9:%.*]] = insertelement <2 x float> poison, float [[TMP0]], i32 0
|
||||
; POW2-ONLY-NEXT: [[TMP10:%.*]] = shufflevector <2 x float> [[TMP9]], <2 x float> poison, <2 x i32> zeroinitializer
|
||||
|
@ -8,19 +8,19 @@ define void @test(ptr %0, i32 %add651) {
|
||||
; CHECK-NEXT: [[PREDPEL11:%.*]] = alloca [0 x [0 x [25 x i32]]], i32 0, align 16
|
||||
; CHECK-NEXT: [[ARRAYIDX469_6:%.*]] = getelementptr i8, ptr [[PREDPEL11]], i64 28
|
||||
; CHECK-NEXT: [[ARRAYIDX469_7:%.*]] = getelementptr i8, ptr [[PREDPEL11]], i64 32
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[PREDPEL11]], i64 40
|
||||
; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP1]], align 8
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = load <2 x i32>, ptr [[ARRAYIDX469_6]], align 4
|
||||
; CHECK-NEXT: [[TMP7:%.*]] = load <2 x i32>, ptr [[ARRAYIDX469_7]], align 16
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[PREDPEL11]], i64 36
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX469_7]], align 16
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = load <2 x i32>, ptr [[ARRAYIDX469_6]], align 4
|
||||
; CHECK-NEXT: [[CONV470_7:%.*]] = trunc i32 [[TMP2]] to i16
|
||||
; CHECK-NEXT: store i16 [[CONV470_7]], ptr [[TMP0]], align 2
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP0]], align 8
|
||||
; CHECK-NEXT: [[ARRAYIDX660:%.*]] = getelementptr i8, ptr [[TMP4]], i64 7800
|
||||
; CHECK-NEXT: [[ARRAYIDX689:%.*]] = getelementptr i8, ptr [[TMP4]], i64 7816
|
||||
; CHECK-NEXT: [[TMP5:%.*]] = load <2 x i32>, ptr [[TMP1]], align 4
|
||||
; CHECK-NEXT: [[TMP6:%.*]] = add <2 x i32> [[TMP3]], splat (i32 1)
|
||||
; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x i32> [[TMP3]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 2>
|
||||
; CHECK-NEXT: [[TMP8:%.*]] = add <2 x i32> [[TMP6]], [[TMP7]]
|
||||
; CHECK-NEXT: [[TMP9:%.*]] = insertelement <2 x i32> <i32 1, i32 poison>, i32 [[TMP5]], i32 1
|
||||
; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 poison>, <2 x i32> <i32 2, i32 1>
|
||||
; CHECK-NEXT: [[TMP10:%.*]] = add <2 x i32> [[TMP8]], [[TMP9]]
|
||||
; CHECK-NEXT: [[TMP11:%.*]] = insertelement <4 x i32> poison, i32 [[ADD651]], i32 0
|
||||
; CHECK-NEXT: [[TMP13:%.*]] = insertelement <4 x i32> [[TMP11]], i32 [[TMP2]], i32 1
|
||||
|
@ -8,13 +8,14 @@ define void @test() {
|
||||
; CHECK-NEXT: [[ARRAYIDX21_I:%.*]] = getelementptr inbounds [4 x float], ptr undef, i64 2
|
||||
; CHECK-NEXT: br label [[BB1:%.*]]
|
||||
; CHECK: bb1:
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[ARRAYIDX10_I_I86]], align 4
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr undef, align 4
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = load <2 x float>, ptr undef, align 4
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = fsub <2 x float> zeroinitializer, [[TMP0]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[ARRAYIDX10_I_I86]], align 4
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = load float, ptr undef, align 4
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x float> <float 0.000000e+00, float poison>, float [[TMP2]], i32 1
|
||||
; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x float> [[TMP0]], float [[TMP3]], i32 0
|
||||
; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x float> <float poison, float 0.000000e+00>, float [[TMP2]], i32 0
|
||||
; CHECK-NEXT: [[TMP7:%.*]] = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP3]], <2 x float> [[TMP6]])
|
||||
; CHECK-NEXT: [[TMP7:%.*]] = call <2 x float> @llvm.fmuladd.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP6]])
|
||||
; CHECK-NEXT: br i1 false, label [[BB2:%.*]], label [[BB3:%.*]]
|
||||
; CHECK: bb2:
|
||||
; CHECK-NEXT: [[TMP8:%.*]] = fmul <2 x float> [[TMP7]], zeroinitializer
|
||||
|
@ -205,15 +205,15 @@ define i32 @reorder_indices_1(float %0) {
|
||||
; POW2-ONLY-SAME: float [[TMP0:%.*]]) {
|
||||
; POW2-ONLY-NEXT: entry:
|
||||
; POW2-ONLY-NEXT: [[NOR1:%.*]] = alloca [0 x [3 x float]], i32 0, align 4
|
||||
; POW2-ONLY-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr float, ptr [[NOR1]], i64 1
|
||||
; POW2-ONLY-NEXT: [[ARRAYIDX2_I265:%.*]] = getelementptr float, ptr [[NOR1]], i64 2
|
||||
; POW2-ONLY-NEXT: [[TMP1:%.*]] = load float, ptr [[ARRAYIDX2_I265]], align 4
|
||||
; POW2-ONLY-NEXT: [[TMP7:%.*]] = load <2 x float>, ptr [[ARRAYIDX_I]], align 4
|
||||
; POW2-ONLY-NEXT: [[TMP2:%.*]] = load <2 x float>, ptr [[NOR1]], align 4
|
||||
; POW2-ONLY-NEXT: [[TMP3:%.*]] = extractelement <2 x float> [[TMP2]], i32 0
|
||||
; POW2-ONLY-NEXT: [[TMP4:%.*]] = fneg float [[TMP3]]
|
||||
; POW2-ONLY-NEXT: [[NEG11_I:%.*]] = fmul float [[TMP4]], [[TMP0]]
|
||||
; POW2-ONLY-NEXT: [[TMP5:%.*]] = call float @llvm.fmuladd.f32(float [[TMP1]], float 0.000000e+00, float [[NEG11_I]])
|
||||
; POW2-ONLY-NEXT: [[TMP6:%.*]] = shufflevector <2 x float> [[TMP2]], <2 x float> poison, <2 x i32> <i32 1, i32 poison>
|
||||
; POW2-ONLY-NEXT: [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[TMP1]], i32 1
|
||||
; POW2-ONLY-NEXT: [[TMP8:%.*]] = fneg <2 x float> [[TMP7]]
|
||||
; POW2-ONLY-NEXT: [[TMP9:%.*]] = insertelement <2 x float> poison, float [[TMP0]], i32 0
|
||||
; POW2-ONLY-NEXT: [[TMP10:%.*]] = shufflevector <2 x float> [[TMP9]], <2 x float> poison, <2 x i32> zeroinitializer
|
||||
|
Loading…
x
Reference in New Issue
Block a user