[SPIR-V] Fix BB ordering & register lifetime (#111026)
The "topological" sorting was behaving incorrectly in some cases: the exit of a loop could have a lower rank than a node in the loop. This causes issues when structurizing some patterns, and also codegen issues as we could generate BBs in the incorrect order in regard to the SPIR-V spec. Fixing this ordering alone broke other parts of the structurizer, which by luck worked. Had to fix those. Added more test cases, especially to test basic patterns. I also needed to tweak/disable some tests for 2 reasons: - SPIR-V now required reg2mem/mem2reg to run. Meaning dead stores are optimized away. Some tests require tweaks to avoid having the whole function removed. - Mem2Reg will generate variable & load/stores. This generates G_BITCAST in several cases. And there is currently something wrong we do with G_BITCAST which causes MIR verifier to complain. Until this is resolved, I disabled -verify-machineinstrs flag on those tests. --------- Signed-off-by: Nathan Gauër <brioche@google.com>
This commit is contained in:
@@ -130,6 +130,13 @@ public:
|
||||
assert(false && "Unhandled terminator type.");
|
||||
}
|
||||
|
||||
AllocaInst *CreateVariable(Function &F, Type *Type,
|
||||
BasicBlock::iterator Position) {
|
||||
const DataLayout &DL = F.getDataLayout();
|
||||
return new AllocaInst(Type, DL.getAllocaAddrSpace(), nullptr, "reg",
|
||||
Position);
|
||||
}
|
||||
|
||||
// Run the pass on the given convergence region, ignoring the sub-regions.
|
||||
// Returns true if the CFG changed, false otherwise.
|
||||
bool runOnConvergenceRegionNoRecurse(LoopInfo &LI,
|
||||
@@ -152,6 +159,9 @@ public:
|
||||
auto NewExitTarget = BasicBlock::Create(F->getContext(), "new.exit", F);
|
||||
IRBuilder<> Builder(NewExitTarget);
|
||||
|
||||
AllocaInst *Variable = CreateVariable(*F, Builder.getInt32Ty(),
|
||||
F->begin()->getFirstInsertionPt());
|
||||
|
||||
// CodeGen output needs to be stable. Using the set as-is would order
|
||||
// the targets differently depending on the allocation pattern.
|
||||
// Sorting per basic-block ordering in the function.
|
||||
@@ -176,18 +186,16 @@ public:
|
||||
std::vector<std::pair<BasicBlock *, Value *>> ExitToVariable;
|
||||
for (auto Exit : SortedExits) {
|
||||
llvm::Value *Value = createExitVariable(Exit, TargetToValue);
|
||||
IRBuilder<> B2(Exit);
|
||||
B2.SetInsertPoint(Exit->getFirstInsertionPt());
|
||||
B2.CreateStore(Value, Variable);
|
||||
ExitToVariable.emplace_back(std::make_pair(Exit, Value));
|
||||
}
|
||||
|
||||
// Gather the correct value depending on the exit we came from.
|
||||
llvm::PHINode *node =
|
||||
Builder.CreatePHI(Builder.getInt32Ty(), ExitToVariable.size());
|
||||
for (auto [BB, Value] : ExitToVariable) {
|
||||
node->addIncoming(Value, BB);
|
||||
}
|
||||
llvm::Value *Load = Builder.CreateLoad(Builder.getInt32Ty(), Variable);
|
||||
|
||||
// Creating the switch to jump to the correct exit target.
|
||||
llvm::SwitchInst *Sw = Builder.CreateSwitch(node, SortedExitTargets[0],
|
||||
llvm::SwitchInst *Sw = Builder.CreateSwitch(Load, SortedExitTargets[0],
|
||||
SortedExitTargets.size() - 1);
|
||||
for (size_t i = 1; i < SortedExitTargets.size(); i++) {
|
||||
BasicBlock *BB = SortedExitTargets[i];
|
||||
|
||||
@@ -87,7 +87,7 @@ BasicBlock *getExitFor(const ConvergenceRegion *CR) {
|
||||
// Returns the merge block designated by I if I is a merge instruction, nullptr
|
||||
// otherwise.
|
||||
BasicBlock *getDesignatedMergeBlock(Instruction *I) {
|
||||
IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);
|
||||
IntrinsicInst *II = dyn_cast_or_null<IntrinsicInst>(I);
|
||||
if (II == nullptr)
|
||||
return nullptr;
|
||||
|
||||
@@ -102,7 +102,7 @@ BasicBlock *getDesignatedMergeBlock(Instruction *I) {
|
||||
// Returns the continue block designated by I if I is an OpLoopMerge, nullptr
|
||||
// otherwise.
|
||||
BasicBlock *getDesignatedContinueBlock(Instruction *I) {
|
||||
IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);
|
||||
IntrinsicInst *II = dyn_cast_or_null<IntrinsicInst>(I);
|
||||
if (II == nullptr)
|
||||
return nullptr;
|
||||
|
||||
@@ -284,18 +284,6 @@ void replaceBranchTargets(BasicBlock *BB, BasicBlock *OldTarget,
|
||||
assert(false && "Unhandled terminator type.");
|
||||
}
|
||||
|
||||
// Replaces basic bloc operands |OldSrc| or OpPhi instructions in |BB| by
|
||||
// |NewSrc|. This function does not simplify the OpPhi instruction once
|
||||
// transformed.
|
||||
void replacePhiTargets(BasicBlock *BB, BasicBlock *OldSrc, BasicBlock *NewSrc) {
|
||||
for (PHINode &Phi : BB->phis()) {
|
||||
int index = Phi.getBasicBlockIndex(OldSrc);
|
||||
if (index == -1)
|
||||
continue;
|
||||
Phi.setIncomingBlock(index, NewSrc);
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// Given a reducible CFG, produces a structurized CFG in the SPIR-V sense,
|
||||
@@ -423,7 +411,7 @@ class SPIRVStructurizer : public FunctionPass {
|
||||
}
|
||||
|
||||
// Splits the given edges by recreating proxy nodes so that the destination
|
||||
// OpPhi instruction can still be viable.
|
||||
// has unique incoming edges from this region.
|
||||
//
|
||||
// clang-format off
|
||||
//
|
||||
@@ -436,66 +424,58 @@ class SPIRVStructurizer : public FunctionPass {
|
||||
// A -> D -> C
|
||||
// B -> D -> C
|
||||
//
|
||||
// But if C had a phi node, adding such proxy-block breaks it. In such case, we must add 1 new block per
|
||||
// exit, and patchup the phi node:
|
||||
// This is fine (assuming C has no PHI nodes), but requires handling the merge instruction here.
|
||||
// By adding a proxy node, we create a regular divergent shape which can easily be regularized later on.
|
||||
// A -> D -> D1 -> C
|
||||
// B -> D -> D2 -> C
|
||||
//
|
||||
// A, B, D belongs to the construct. D is the exit. D1 and D2 are empty, just used as
|
||||
// source operands for C's phi node.
|
||||
// A, B, D belongs to the construct. D is the exit. D1 and D2 are empty.
|
||||
//
|
||||
// clang-format on
|
||||
std::vector<Edge>
|
||||
createAliasBlocksForComplexEdges(std::vector<Edge> Edges) {
|
||||
std::unordered_map<BasicBlock *, BasicBlock *> Seen;
|
||||
std::unordered_set<BasicBlock *> Seen;
|
||||
std::vector<Edge> Output;
|
||||
Output.reserve(Edges.size());
|
||||
|
||||
for (auto &[Src, Dst] : Edges) {
|
||||
auto [iterator, inserted] = Seen.insert({Src, Dst});
|
||||
if (inserted) {
|
||||
Output.emplace_back(Src, Dst);
|
||||
continue;
|
||||
auto [Iterator, Inserted] = Seen.insert(Src);
|
||||
if (!Inserted) {
|
||||
// Src already a source node. Cannot have 2 edges from A to B.
|
||||
// Creating alias source block.
|
||||
BasicBlock *NewSrc = BasicBlock::Create(
|
||||
F.getContext(), Src->getName() + ".new.src", &F);
|
||||
replaceBranchTargets(Src, Dst, NewSrc);
|
||||
IRBuilder<> Builder(NewSrc);
|
||||
Builder.CreateBr(Dst);
|
||||
Src = NewSrc;
|
||||
}
|
||||
|
||||
// The exact same edge was already seen. Ignoring.
|
||||
if (iterator->second == Dst)
|
||||
continue;
|
||||
|
||||
// The same Src block branches to 2 distinct blocks. This will be an
|
||||
// issue for the generated OpPhi. Creating alias block.
|
||||
BasicBlock *NewSrc =
|
||||
BasicBlock::Create(F.getContext(), "new.exit.src", &F);
|
||||
replaceBranchTargets(Src, Dst, NewSrc);
|
||||
replacePhiTargets(Dst, Src, NewSrc);
|
||||
|
||||
IRBuilder<> Builder(NewSrc);
|
||||
Builder.CreateBr(Dst);
|
||||
|
||||
Seen.emplace(NewSrc, Dst);
|
||||
Output.emplace_back(NewSrc, Dst);
|
||||
Output.emplace_back(Src, Dst);
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
||||
AllocaInst *CreateVariable(Function &F, Type *Type,
|
||||
BasicBlock::iterator Position) {
|
||||
const DataLayout &DL = F.getDataLayout();
|
||||
return new AllocaInst(Type, DL.getAllocaAddrSpace(), nullptr, "reg",
|
||||
Position);
|
||||
}
|
||||
|
||||
// Given a construct defined by |Header|, and a list of exiting edges
|
||||
// |Edges|, creates a new single exit node, fixing up those edges.
|
||||
BasicBlock *createSingleExitNode(BasicBlock *Header,
|
||||
std::vector<Edge> &Edges) {
|
||||
auto NewExit = BasicBlock::Create(F.getContext(), "new.exit", &F);
|
||||
IRBuilder<> ExitBuilder(NewExit);
|
||||
|
||||
std::vector<Edge> FixedEdges = createAliasBlocksForComplexEdges(Edges);
|
||||
|
||||
std::vector<BasicBlock *> Dsts;
|
||||
std::unordered_map<BasicBlock *, ConstantInt *> DstToIndex;
|
||||
|
||||
// Given 2 edges: Src1 -> Dst, Src2 -> Dst:
|
||||
// If Dst has an PHI node, and Src1 and Src2 are both operands, both Src1
|
||||
// and Src2 cannot be hidden by NewExit. Create 2 new nodes: Alias1,
|
||||
// Alias2 to which NewExit will branch before going to Dst. Then, patchup
|
||||
// Dst PHI node to look for Alias1 and Alias2.
|
||||
std::vector<Edge> FixedEdges = createAliasBlocksForComplexEdges(Edges);
|
||||
|
||||
auto NewExit = BasicBlock::Create(F.getContext(),
|
||||
Header->getName() + ".new.exit", &F);
|
||||
IRBuilder<> ExitBuilder(NewExit);
|
||||
for (auto &[Src, Dst] : FixedEdges) {
|
||||
if (DstToIndex.count(Dst) != 0)
|
||||
continue;
|
||||
@@ -506,33 +486,34 @@ class SPIRVStructurizer : public FunctionPass {
|
||||
if (Dsts.size() == 1) {
|
||||
for (auto &[Src, Dst] : FixedEdges) {
|
||||
replaceBranchTargets(Src, Dst, NewExit);
|
||||
replacePhiTargets(Dst, Src, NewExit);
|
||||
}
|
||||
ExitBuilder.CreateBr(Dsts[0]);
|
||||
return NewExit;
|
||||
}
|
||||
|
||||
PHINode *PhiNode =
|
||||
ExitBuilder.CreatePHI(ExitBuilder.getInt32Ty(), FixedEdges.size());
|
||||
|
||||
AllocaInst *Variable = CreateVariable(F, ExitBuilder.getInt32Ty(),
|
||||
F.begin()->getFirstInsertionPt());
|
||||
for (auto &[Src, Dst] : FixedEdges) {
|
||||
PhiNode->addIncoming(DstToIndex[Dst], Src);
|
||||
IRBuilder<> B2(Src);
|
||||
B2.SetInsertPoint(Src->getFirstInsertionPt());
|
||||
B2.CreateStore(DstToIndex[Dst], Variable);
|
||||
replaceBranchTargets(Src, Dst, NewExit);
|
||||
replacePhiTargets(Dst, Src, NewExit);
|
||||
}
|
||||
|
||||
llvm::Value *Load =
|
||||
ExitBuilder.CreateLoad(ExitBuilder.getInt32Ty(), Variable);
|
||||
|
||||
// If we can avoid an OpSwitch, generate an OpBranch. Reason is some
|
||||
// OpBranch are allowed to exist without a new OpSelectionMerge if one of
|
||||
// the branch is the parent's merge node, while OpSwitches are not.
|
||||
if (Dsts.size() == 2) {
|
||||
Value *Condition = ExitBuilder.CreateCmp(CmpInst::ICMP_EQ,
|
||||
DstToIndex[Dsts[0]], PhiNode);
|
||||
Value *Condition =
|
||||
ExitBuilder.CreateCmp(CmpInst::ICMP_EQ, DstToIndex[Dsts[0]], Load);
|
||||
ExitBuilder.CreateCondBr(Condition, Dsts[0], Dsts[1]);
|
||||
return NewExit;
|
||||
}
|
||||
|
||||
SwitchInst *Sw =
|
||||
ExitBuilder.CreateSwitch(PhiNode, Dsts[0], Dsts.size() - 1);
|
||||
SwitchInst *Sw = ExitBuilder.CreateSwitch(Load, Dsts[0], Dsts.size() - 1);
|
||||
for (auto It = Dsts.begin() + 1; It != Dsts.end(); ++It) {
|
||||
Sw->addCase(DstToIndex[*It], *It);
|
||||
}
|
||||
@@ -576,7 +557,7 @@ class SPIRVStructurizer : public FunctionPass {
|
||||
|
||||
// Creates a new basic block in F with a single OpUnreachable instruction.
|
||||
BasicBlock *CreateUnreachable(Function &F) {
|
||||
BasicBlock *BB = BasicBlock::Create(F.getContext(), "new.exit", &F);
|
||||
BasicBlock *BB = BasicBlock::Create(F.getContext(), "unreachable", &F);
|
||||
IRBuilder<> Builder(BB);
|
||||
Builder.CreateUnreachable();
|
||||
return BB;
|
||||
@@ -1027,17 +1008,8 @@ class SPIRVStructurizer : public FunctionPass {
|
||||
return Modified;
|
||||
}
|
||||
|
||||
bool IsRequiredForPhiNode(BasicBlock *BB) {
|
||||
for (BasicBlock *Successor : successors(BB)) {
|
||||
for (PHINode &Phi : Successor->phis()) {
|
||||
if (Phi.getBasicBlockIndex(BB) != -1)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Removes blocks not contributing to any structured CFG. This assumes there
|
||||
// is no PHI nodes.
|
||||
bool removeUselessBlocks(Function &F) {
|
||||
std::vector<BasicBlock *> ToRemove;
|
||||
|
||||
@@ -1054,9 +1026,6 @@ class SPIRVStructurizer : public FunctionPass {
|
||||
if (MergeBlocks.count(&BB) != 0 || ContinueBlocks.count(&BB) != 0)
|
||||
continue;
|
||||
|
||||
if (IsRequiredForPhiNode(&BB))
|
||||
continue;
|
||||
|
||||
if (BB.getUniqueSuccessor() == nullptr)
|
||||
continue;
|
||||
|
||||
@@ -1127,6 +1096,18 @@ class SPIRVStructurizer : public FunctionPass {
|
||||
continue;
|
||||
|
||||
Modified = true;
|
||||
|
||||
if (Merge == nullptr) {
|
||||
Merge = *successors(Header).begin();
|
||||
IRBuilder<> Builder(Header);
|
||||
Builder.SetInsertPoint(Header->getTerminator());
|
||||
|
||||
auto MergeAddress = BlockAddress::get(Merge->getParent(), Merge);
|
||||
SmallVector<Value *, 1> Args = {MergeAddress};
|
||||
Builder.CreateIntrinsic(Intrinsic::spv_selection_merge, {}, {Args});
|
||||
continue;
|
||||
}
|
||||
|
||||
Instruction *SplitInstruction = Merge->getTerminator();
|
||||
if (isMergeInstruction(SplitInstruction->getPrevNode()))
|
||||
SplitInstruction = SplitInstruction->getPrevNode();
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "llvm/MC/TargetRegistry.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Transforms/Scalar/Reg2Mem.h"
|
||||
#include "llvm/Transforms/Utils.h"
|
||||
#include <optional>
|
||||
|
||||
@@ -169,13 +170,21 @@ void SPIRVPassConfig::addIRPasses() {
|
||||
// - loops have a single back-edge.
|
||||
addPass(createLoopSimplifyPass());
|
||||
|
||||
// 2. Merge the convergence region exit nodes into one. After this step,
|
||||
// 2. Removes registers whose lifetime spans across basic blocks. Also
|
||||
// removes phi nodes. This will greatly simplify the next steps.
|
||||
addPass(createRegToMemWrapperPass());
|
||||
|
||||
// 3. Merge the convergence region exit nodes into one. After this step,
|
||||
// regions are single-entry, single-exit. This will help determine the
|
||||
// correct merge block.
|
||||
addPass(createSPIRVMergeRegionExitTargetsPass());
|
||||
|
||||
// 3. Structurize.
|
||||
// 4. Structurize.
|
||||
addPass(createSPIRVStructurizerPass());
|
||||
|
||||
// 5. Reduce the amount of variables required by pushing some operations
|
||||
// back to virtual registers.
|
||||
addPass(createPromoteMemoryToRegisterPass());
|
||||
}
|
||||
|
||||
addPass(createSPIRVRegularizerPass());
|
||||
|
||||
@@ -460,53 +460,98 @@ PartialOrderingVisitor::getReachableFrom(BasicBlock *Start) {
|
||||
return Output;
|
||||
}
|
||||
|
||||
size_t PartialOrderingVisitor::visit(BasicBlock *BB, size_t Rank) {
|
||||
if (Visited.count(BB) != 0)
|
||||
return Rank;
|
||||
bool PartialOrderingVisitor::CanBeVisited(BasicBlock *BB) const {
|
||||
for (BasicBlock *P : predecessors(BB)) {
|
||||
// Ignore back-edges.
|
||||
if (DT.dominates(BB, P))
|
||||
continue;
|
||||
|
||||
Loop *L = LI.getLoopFor(BB);
|
||||
const bool isLoopHeader = LI.isLoopHeader(BB);
|
||||
// One of the predecessor hasn't been visited. Not ready yet.
|
||||
if (BlockToOrder.count(P) == 0)
|
||||
return false;
|
||||
|
||||
if (BlockToOrder.count(BB) == 0) {
|
||||
OrderInfo Info = {Rank, Visited.size()};
|
||||
// If the block is a loop exit, the loop must be finished before
|
||||
// we can continue.
|
||||
Loop *L = LI.getLoopFor(P);
|
||||
if (L == nullptr || L->contains(BB))
|
||||
continue;
|
||||
|
||||
// SPIR-V requires a single back-edge. And the backend first
|
||||
// step transforms loops into the simplified format. If we have
|
||||
// more than 1 back-edge, something is wrong.
|
||||
assert(L->getNumBackEdges() <= 1);
|
||||
|
||||
// If the loop has no latch, loop's rank won't matter, so we can
|
||||
// proceed.
|
||||
BasicBlock *Latch = L->getLoopLatch();
|
||||
assert(Latch);
|
||||
if (Latch == nullptr)
|
||||
continue;
|
||||
|
||||
// The latch is not ready yet, let's wait.
|
||||
if (BlockToOrder.count(Latch) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t PartialOrderingVisitor::GetNodeRank(BasicBlock *BB) const {
|
||||
size_t result = 0;
|
||||
|
||||
for (BasicBlock *P : predecessors(BB)) {
|
||||
// Ignore back-edges.
|
||||
if (DT.dominates(BB, P))
|
||||
continue;
|
||||
|
||||
auto Iterator = BlockToOrder.end();
|
||||
Loop *L = LI.getLoopFor(P);
|
||||
BasicBlock *Latch = L ? L->getLoopLatch() : nullptr;
|
||||
|
||||
// If the predecessor is either outside a loop, or part of
|
||||
// the same loop, simply take its rank + 1.
|
||||
if (L == nullptr || L->contains(BB) || Latch == nullptr) {
|
||||
Iterator = BlockToOrder.find(P);
|
||||
} else {
|
||||
// Otherwise, take the loop's rank (highest rank in the loop) as base.
|
||||
// Since loops have a single latch, highest rank is easy to find.
|
||||
// If the loop has no latch, then it doesn't matter.
|
||||
Iterator = BlockToOrder.find(Latch);
|
||||
}
|
||||
|
||||
assert(Iterator != BlockToOrder.end());
|
||||
result = std::max(result, Iterator->second.Rank + 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t PartialOrderingVisitor::visit(BasicBlock *BB, size_t Unused) {
|
||||
ToVisit.push(BB);
|
||||
Queued.insert(BB);
|
||||
|
||||
while (ToVisit.size() != 0) {
|
||||
BasicBlock *BB = ToVisit.front();
|
||||
ToVisit.pop();
|
||||
|
||||
if (!CanBeVisited(BB)) {
|
||||
ToVisit.push(BB);
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t Rank = GetNodeRank(BB);
|
||||
OrderInfo Info = {Rank, BlockToOrder.size()};
|
||||
BlockToOrder.emplace(BB, Info);
|
||||
} else {
|
||||
BlockToOrder[BB].Rank = std::max(BlockToOrder[BB].Rank, Rank);
|
||||
}
|
||||
|
||||
for (BasicBlock *Predecessor : predecessors(BB)) {
|
||||
if (isLoopHeader && L->contains(Predecessor)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BlockToOrder.count(Predecessor) == 0) {
|
||||
return Rank;
|
||||
for (BasicBlock *S : successors(BB)) {
|
||||
if (Queued.count(S) != 0)
|
||||
continue;
|
||||
ToVisit.push(S);
|
||||
Queued.insert(S);
|
||||
}
|
||||
}
|
||||
|
||||
Visited.insert(BB);
|
||||
|
||||
SmallVector<BasicBlock *, 2> OtherSuccessors;
|
||||
SmallVector<BasicBlock *, 2> LoopSuccessors;
|
||||
|
||||
for (BasicBlock *Successor : successors(BB)) {
|
||||
// Ignoring back-edges.
|
||||
if (DT.dominates(Successor, BB))
|
||||
continue;
|
||||
|
||||
if (isLoopHeader && L->contains(Successor)) {
|
||||
LoopSuccessors.push_back(Successor);
|
||||
} else
|
||||
OtherSuccessors.push_back(Successor);
|
||||
}
|
||||
|
||||
for (BasicBlock *BB : LoopSuccessors)
|
||||
Rank = std::max(Rank, visit(BB, Rank + 1));
|
||||
|
||||
size_t OutputRank = Rank;
|
||||
for (BasicBlock *Item : OtherSuccessors)
|
||||
OutputRank = std::max(OutputRank, visit(Item, Rank + 1));
|
||||
return OutputRank;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PartialOrderingVisitor::PartialOrderingVisitor(Function &F) {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/TypedPointerType.h"
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
@@ -62,7 +63,9 @@ class SPIRVSubtarget;
|
||||
class PartialOrderingVisitor {
|
||||
DomTreeBuilder::BBDomTree DT;
|
||||
LoopInfo LI;
|
||||
std::unordered_set<BasicBlock *> Visited = {};
|
||||
|
||||
std::unordered_set<BasicBlock *> Queued = {};
|
||||
std::queue<BasicBlock *> ToVisit = {};
|
||||
|
||||
struct OrderInfo {
|
||||
size_t Rank;
|
||||
@@ -80,6 +83,9 @@ class PartialOrderingVisitor {
|
||||
// Visits |BB| with the current rank being |Rank|.
|
||||
size_t visit(BasicBlock *BB, size_t Rank);
|
||||
|
||||
size_t GetNodeRank(BasicBlock *BB) const;
|
||||
bool CanBeVisited(BasicBlock *BB) const;
|
||||
|
||||
public:
|
||||
// Build the visitor to operate on the function F.
|
||||
PartialOrderingVisitor(Function &F);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-vulkan-library %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-vulkan-library %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-library %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: OpDecorate [[IntBufferVar:%[0-9]+]] DescriptorSet 16
|
||||
@@ -18,13 +19,13 @@
|
||||
; CHECK: {{%[0-9]+}} = OpFunction {{%[0-9]+}} DontInline {{%[0-9]+}}
|
||||
; CHECK-NEXT: OpLabel
|
||||
define void @RWBufferLoad() #0 {
|
||||
; CHECK-NEXT: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
|
||||
; CHECK: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
|
||||
%buffer0 = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 24)
|
||||
@llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_24(
|
||||
i32 16, i32 7, i32 1, i32 0, i1 false)
|
||||
|
||||
; Make sure we use the same variable with multiple loads.
|
||||
; CHECK-NEXT: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
|
||||
; CHECK: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
|
||||
%buffer1 = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 24)
|
||||
@llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_24(
|
||||
i32 16, i32 7, i32 1, i32 0, i1 false)
|
||||
@@ -36,7 +37,7 @@ define void @RWBufferLoad() #0 {
|
||||
define void @UseDifferentGlobalVar() #0 {
|
||||
; Make sure we use a different variable from the first function. They have
|
||||
; different types.
|
||||
; CHECK-NEXT: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeFloat]] [[FloatBufferVar]]
|
||||
; CHECK: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeFloat]] [[FloatBufferVar]]
|
||||
%buffer0 = call target("spirv.Image", float, 5, 2, 0, 0, 2, 3)
|
||||
@llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_3(
|
||||
i32 16, i32 7, i32 1, i32 0, i1 false)
|
||||
@@ -48,7 +49,7 @@ define void @UseDifferentGlobalVar() #0 {
|
||||
define void @ReuseGlobalVarFromFirstFunction() #0 {
|
||||
; Make sure we use the same variable as the first function. They should be the
|
||||
; same in case one function calls the other.
|
||||
; CHECK-NEXT: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
|
||||
; CHECK: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
|
||||
%buffer1 = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 24)
|
||||
@llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_24(
|
||||
i32 16, i32 7, i32 1, i32 0, i1 false)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
; All OpVariable instructions in a function must be the first instructions in the first block
|
||||
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-linux %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-linux %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -O0 -mtriple=spirv32-unknown-linux %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-linux %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-SPIRV: OpFunction
|
||||
; CHECK-SPIRV-NEXT: OpLabel
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-vulkan-library %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-vulkan-library %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-library %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-NOT: OpCapability ImageBasic
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-vulkan-library %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-vulkan-library %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-library %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: [[Float:%[0-9]+]] = OpTypeFloat 32
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; REQUIRES: spirv-tools
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - --filetype=obj | spirv-dis | FileCheck %s
|
||||
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - --filetype=obj | spirv-dis | FileCheck %s
|
||||
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - --filetype=obj | spirv-dis | FileCheck %s
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-vulkan-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-vulkan-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; This file generated from the following command:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-vulkan-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-vulkan-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; This file generated from the following command:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-HLSL
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-OCL
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-HLSL
|
||||
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-OCL
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
; Make sure spirv operation function calls for all are generated.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-HLSL
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-OCL
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-HLSL
|
||||
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-OCL
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
; Make sure spirv operation function calls for any are generated.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpMemoryModel Logical GLSL450
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#int_16:]] = OpTypeInt 16 0
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; Make sure SPIRV operation function calls for lerp are generated as FMix
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: %[[#extinst:]] = OpExtInstImport "GLSL.std.450"
|
||||
@@ -6,35 +7,22 @@
|
||||
; CHECK: %[[#float:]] = OpTypeFloat 32
|
||||
; CHECK: %[[#v4float:]] = OpTypeVector %[[#float]] 4
|
||||
; CHECK: %[[#float_0_30103001:]] = OpConstant %[[#float]] 0.30103000998497009
|
||||
; CHECK: %[[#_ptr_Function_v4float:]] = OpTypePointer Function %[[#v4float]]
|
||||
; CHECK: %[[#_ptr_Function_float:]] = OpTypePointer Function %[[#float]]
|
||||
|
||||
define void @main() {
|
||||
define void @main(float %f, <4 x float> %f4) {
|
||||
entry:
|
||||
; CHECK: %[[#f:]] = OpVariable %[[#_ptr_Function_float]] Function
|
||||
; CHECK: %[[#logf:]] = OpVariable %[[#_ptr_Function_float]] Function
|
||||
; CHECK: %[[#f4:]] = OpVariable %[[#_ptr_Function_v4float]] Function
|
||||
; CHECK: %[[#logf4:]] = OpVariable %[[#_ptr_Function_v4float]] Function
|
||||
%f = alloca float, align 4
|
||||
; CHECK-DAG: %[[#f:]] = OpFunctionParameter %[[#float]]
|
||||
; CHECK-DAG: %[[#f4:]] = OpFunctionParameter %[[#v4float]]
|
||||
%logf = alloca float, align 4
|
||||
%f4 = alloca <4 x float>, align 16
|
||||
%logf4 = alloca <4 x float>, align 16
|
||||
|
||||
; CHECK: %[[#load:]] = OpLoad %[[#float]] %[[#f]] Aligned 4
|
||||
; CHECK: %[[#log2:]] = OpExtInst %[[#float]] %[[#extinst]] Log2 %[[#load]]
|
||||
; CHECK: %[[#res:]] = OpFMul %[[#float]] %[[#log2]] %[[#float_0_30103001]]
|
||||
; CHECK: OpStore %[[#logf]] %[[#res]] Aligned 4
|
||||
%0 = load float, ptr %f, align 4
|
||||
%elt.log10 = call float @llvm.log10.f32(float %0)
|
||||
store float %elt.log10, ptr %logf, align 4
|
||||
|
||||
; CHECK: %[[#load:]] = OpLoad %[[#v4float]] %[[#f4]] Aligned 16
|
||||
; CHECK: %[[#log2:]] = OpExtInst %[[#v4float]] %[[#extinst]] Log2 %[[#load]]
|
||||
; CHECK: %[[#log2:]] = OpExtInst %[[#float]] %[[#extinst]] Log2 %[[#f]]
|
||||
; CHECK: %[[#res:]] = OpFMul %[[#float]] %[[#log2]] %[[#float_0_30103001]]
|
||||
%elt.log10 = call float @llvm.log10.f32(float %f)
|
||||
|
||||
; CHECK: %[[#log2:]] = OpExtInst %[[#v4float]] %[[#extinst]] Log2 %[[#f4]]
|
||||
; CHECK: %[[#res:]] = OpVectorTimesScalar %[[#v4float]] %[[#log2]] %[[#float_0_30103001]]
|
||||
; CHECK: OpStore %[[#logf4]] %[[#res]] Aligned 16
|
||||
%1 = load <4 x float>, ptr %f4, align 16
|
||||
%elt.log101 = call <4 x float> @llvm.log10.v4f32(<4 x float> %1)
|
||||
store <4 x float> %elt.log101, ptr %logf4, align 16
|
||||
%elt.log101 = call <4 x float> @llvm.log10.v4f32(<4 x float> %f4)
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
|
||||
; CHECK-DAG: %[[#float_64:]] = OpTypeFloat 64
|
||||
; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpMemoryModel Logical GLSL450
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; Make sure lowering is correctly generating spirv code.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: OpExtInstImport "GLSL.std.450"
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
; TODO(pull/110270): verifier, fix G_BITCAST error "bitcast must change type"
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK: %[[#F32:]] = OpTypeFloat 32
|
||||
; CHECK: %[[#F64:]] = OpTypeFloat 64
|
||||
|
||||
|
||||
52
llvm/test/CodeGen/SPIRV/structurizer/basic-if.ll
Normal file
52
llvm/test/CodeGen/SPIRV/structurizer/basic-if.ll
Normal file
@@ -0,0 +1,52 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
|
||||
; Function Attrs: convergent noinline norecurse nounwind optnone
|
||||
define spir_func noundef i32 @_Z7processv() #0 {
|
||||
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#left:]] %[[#right:]]
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
%1 = alloca i32, align 4
|
||||
br i1 true, label %left, label %right
|
||||
|
||||
; CHECK: %[[#left]] = OpLabel
|
||||
; CHECK: OpBranch %[[#merge]]
|
||||
left:
|
||||
store i32 0, ptr %1
|
||||
br label %end
|
||||
|
||||
; CHECK: %[[#right]] = OpLabel
|
||||
; CHECK: OpBranch %[[#merge]]
|
||||
right:
|
||||
store i32 0, ptr %1
|
||||
br label %end
|
||||
|
||||
; CHECK: %[[#merge]] = OpLabel
|
||||
; CHECK: OpReturnValue %[[#]]
|
||||
end:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none)
|
||||
declare token @llvm.experimental.convergence.entry() #1
|
||||
|
||||
; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none)
|
||||
declare token @llvm.experimental.convergence.loop() #1
|
||||
|
||||
|
||||
attributes #0 = { convergent noinline norecurse nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
|
||||
attributes #1 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
|
||||
attributes #2 = { convergent norecurse "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
|
||||
attributes #3 = { convergent }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2}
|
||||
|
||||
|
||||
!0 = !{i32 1, !"wchar_size", i32 4}
|
||||
!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
|
||||
!2 = !{i32 7, !"frame-pointer", i32 2}
|
||||
47
llvm/test/CodeGen/SPIRV/structurizer/basic-imbalanced-if.ll
Normal file
47
llvm/test/CodeGen/SPIRV/structurizer/basic-imbalanced-if.ll
Normal file
@@ -0,0 +1,47 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
|
||||
; Function Attrs: convergent noinline norecurse nounwind optnone
|
||||
define spir_func noundef i32 @_Z7processv() #0 {
|
||||
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#left:]] %[[#merge]]
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
%1 = alloca i32, align 4
|
||||
br i1 true, label %left, label %end
|
||||
|
||||
; CHECK: %[[#left]] = OpLabel
|
||||
; CHECK: OpBranch %[[#merge]]
|
||||
left:
|
||||
store i32 0, ptr %1
|
||||
br label %end
|
||||
|
||||
; CHECK: %[[#merge]] = OpLabel
|
||||
; CHECK: OpReturnValue %[[#]]
|
||||
end:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none)
|
||||
declare token @llvm.experimental.convergence.entry() #1
|
||||
|
||||
; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none)
|
||||
declare token @llvm.experimental.convergence.loop() #1
|
||||
|
||||
|
||||
attributes #0 = { convergent noinline norecurse nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
|
||||
attributes #1 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
|
||||
attributes #2 = { convergent norecurse "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
|
||||
attributes #3 = { convergent }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2}
|
||||
|
||||
|
||||
!0 = !{i32 1, !"wchar_size", i32 4}
|
||||
!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
|
||||
!2 = !{i32 7, !"frame-pointer", i32 2}
|
||||
59
llvm/test/CodeGen/SPIRV/structurizer/basic-loop.ll
Normal file
59
llvm/test/CodeGen/SPIRV/structurizer/basic-loop.ll
Normal file
@@ -0,0 +1,59 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
|
||||
; Function Attrs: convergent noinline norecurse nounwind optnone
|
||||
define spir_func noundef i32 @_Z7processv() #0 {
|
||||
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#header:]]
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
%1 = alloca i32, align 4
|
||||
br label %header
|
||||
|
||||
; CHECK: %[[#header]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#merge:]] %[[#continue:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#body:]] %[[#merge]]
|
||||
header:
|
||||
%2 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
|
||||
br i1 true, label %body, label %merge
|
||||
|
||||
; CHECK: %[[#body]] = OpLabel
|
||||
; CHECK: OpBranch %[[#continue]]
|
||||
body:
|
||||
store i32 0, ptr %1
|
||||
br label %continue
|
||||
|
||||
continue:
|
||||
br label %header
|
||||
; CHECK: %[[#continue]] = OpLabel
|
||||
; CHECK: OpBranch %[[#header]]
|
||||
|
||||
; CHECK: %[[#merge]] = OpLabel
|
||||
; CHECK: OpReturnValue %[[#]]
|
||||
merge:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none)
|
||||
declare token @llvm.experimental.convergence.entry() #1
|
||||
|
||||
; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none)
|
||||
declare token @llvm.experimental.convergence.loop() #1
|
||||
|
||||
|
||||
attributes #0 = { convergent noinline norecurse nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
|
||||
attributes #1 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
|
||||
attributes #2 = { convergent norecurse "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
|
||||
attributes #3 = { convergent }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2}
|
||||
|
||||
|
||||
!0 = !{i32 1, !"wchar_size", i32 4}
|
||||
!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
|
||||
!2 = !{i32 7, !"frame-pointer", i32 2}
|
||||
|
||||
58
llvm/test/CodeGen/SPIRV/structurizer/basic-phi.ll
Normal file
58
llvm/test/CodeGen/SPIRV/structurizer/basic-phi.ll
Normal file
@@ -0,0 +1,58 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
|
||||
; Function Attrs: convergent noinline norecurse nounwind optnone
|
||||
define spir_func noundef i32 @_Z7processv() #0 {
|
||||
|
||||
; CHECK-DAG: %[[#int_0:]] = OpConstant %[[#]] 0
|
||||
; CHECK-DAG: %[[#int_1:]] = OpConstant %[[#]] 1
|
||||
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK: %[[#var:]] = OpVariable %[[#]] Function
|
||||
; CHECK: OpSelectionMerge %[[#merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#left:]] %[[#right:]]
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
br i1 true, label %left, label %right
|
||||
|
||||
; CHECK: %[[#left]] = OpLabel
|
||||
; CHECK-NEXT: OpStore %[[#var]] %[[#int_0]]
|
||||
; CHECK-NEXT: OpBranch %[[#merge]]
|
||||
left:
|
||||
br label %end
|
||||
|
||||
; CHECK: %[[#right]] = OpLabel
|
||||
; CHECK-NEXT: OpStore %[[#var]] %[[#int_1]]
|
||||
; CHECK-NEXT: OpBranch %[[#merge]]
|
||||
right:
|
||||
br label %end
|
||||
|
||||
; CHECK: %[[#merge]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#]] %[[#var]]
|
||||
; CHECK: OpReturnValue %[[#tmp]]
|
||||
end:
|
||||
%1 = phi i32 [ 0, %left ], [ 1, %right ]
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none)
|
||||
declare token @llvm.experimental.convergence.entry() #1
|
||||
|
||||
; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none)
|
||||
declare token @llvm.experimental.convergence.loop() #1
|
||||
|
||||
|
||||
attributes #0 = { convergent noinline norecurse nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
|
||||
attributes #1 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
|
||||
attributes #2 = { convergent norecurse "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
|
||||
attributes #3 = { convergent }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2}
|
||||
|
||||
|
||||
!0 = !{i32 1, !"wchar_size", i32 4}
|
||||
!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
|
||||
!2 = !{i32 7, !"frame-pointer", i32 2}
|
||||
@@ -8,16 +8,17 @@ target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
; CHECK-DAG: OpName %[[#fn:]] "_Z2fnv"
|
||||
; CHECK-DAG: OpName %[[#fn1:]] "_Z3fn1v"
|
||||
; CHECK-DAG: OpName %[[#fn2:]] "_Z3fn2v"
|
||||
; CHECK-DAG: OpName %[[#val:]] "val"
|
||||
; CHECK-DAG: OpName %[[#a:]] "a"
|
||||
; CHECK-DAG: OpName %[[#b:]] "b"
|
||||
; CHECK-DAG: OpName %[[#c:]] "c"
|
||||
|
||||
; CHECK-DAG: OpName %[[#r2m_a:]] ".reg2mem3"
|
||||
; CHECK-DAG: OpName %[[#r2m_b:]] ".reg2mem1"
|
||||
; CHECK-DAG: OpName %[[#r2m_c:]] ".reg2mem"
|
||||
|
||||
; CHECK-DAG: %[[#int_ty:]] = OpTypeInt 32 0
|
||||
; CHECK-DAG: %[[#bool_ty:]] = OpTypeBool
|
||||
; CHECK-DAG: %[[#int_pfty:]] = OpTypePointer Function %[[#int_ty]]
|
||||
|
||||
; CHECK-DAG: %[[#int_0:]] = OpConstant %[[#int_ty]] 0
|
||||
; CHECK-DAG: %[[#int_0:]] = OpConstant %[[#]] 0
|
||||
; CHECK-DAG: %[[#int_1:]] = OpConstant %[[#]] 1
|
||||
; CHECK-DAG: %[[#true:]] = OpConstantTrue
|
||||
; CHECK-DAG: %[[#false:]] = OpConstantFalse
|
||||
|
||||
declare token @llvm.experimental.convergence.entry() #1
|
||||
|
||||
@@ -44,100 +45,86 @@ entry:
|
||||
|
||||
; CHECK: %[[#process]] = OpFunction %[[#int_ty]]
|
||||
define spir_func noundef i32 @_Z7processv() #0 {
|
||||
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK-DAG: %[[#r2m_a]] = OpVariable %[[#]] Function
|
||||
; CHECK: OpSelectionMerge %[[#a_merge:]]
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#a_true:]] %[[#a_false:]]
|
||||
entry:
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
%a = alloca i32, align 4
|
||||
%b = alloca i32, align 4
|
||||
%c = alloca i32, align 4
|
||||
%val = alloca i32, align 4
|
||||
store i32 0, ptr %a, align 4
|
||||
store i32 1, ptr %b, align 4
|
||||
store i32 2, ptr %c, align 4
|
||||
store i32 0, ptr %val, align 4
|
||||
; CHECK-DAG: %[[#a]] = OpVariable %[[#int_pfty]] Function
|
||||
; CHECK-DAG: %[[#b]] = OpVariable %[[#int_pfty]] Function
|
||||
; CHECK-DAG: %[[#c]] = OpVariable %[[#int_pfty]] Function
|
||||
; CHECK-DAG: %[[#val]] = OpVariable %[[#int_pfty]] Function
|
||||
%1 = load i32, ptr %a, align 4
|
||||
%tobool = icmp ne i32 %1, 0
|
||||
br i1 %tobool, label %cond.true, label %cond.false
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#a]]
|
||||
; CHECK: %[[#cond:]] = OpINotEqual %[[#bool_ty]] %[[#tmp]] %[[#int_0]]
|
||||
; CHECK: OpSelectionMerge %[[#cond_end:]]
|
||||
; CHECK: OpBranchConditional %[[#cond]] %[[#cond_true:]] %[[#cond_false:]]
|
||||
%var = alloca i32
|
||||
br i1 true, label %a_true, label %a_false
|
||||
|
||||
cond.true: ; preds = %entry
|
||||
%2 = load i32, ptr %b, align 4
|
||||
br label %cond.end
|
||||
; CHECK: %[[#cond_true]] = OpLabel
|
||||
; CHECK: OpBranch %[[#cond_end]]
|
||||
; CHECK: %[[#a_true]] = OpLabel
|
||||
; CHECK: OpStore %[[#r2m_a]] %[[#true]]
|
||||
; CHECK: OpBranch %[[#a_merge]]
|
||||
a_true:
|
||||
br label %a_merge
|
||||
|
||||
cond.false: ; preds = %entry
|
||||
%3 = load i32, ptr %c, align 4
|
||||
br label %cond.end
|
||||
; CHECK: %[[#cond_false]] = OpLabel
|
||||
; CHECK: %[[#load_c:]] = OpLoad %[[#]] %[[#c]]
|
||||
; CHECK: OpBranch %[[#cond_end]]
|
||||
; CHECK: %[[#a_false]] = OpLabel
|
||||
; CHECK: OpStore %[[#r2m_a]] %[[#false]]
|
||||
; CHECK: OpBranch %[[#a_merge]]
|
||||
a_false:
|
||||
br label %a_merge
|
||||
|
||||
cond.end: ; preds = %cond.false, %cond.true
|
||||
%cond = phi i32 [ %2, %cond.true ], [ %3, %cond.false ]
|
||||
%tobool1 = icmp ne i32 %cond, 0
|
||||
br i1 %tobool1, label %if.then, label %if.end
|
||||
; CHECK: %[[#cond_end]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpPhi %[[#int_ty]] %[[#load_b:]] %[[#cond_true]] %[[#load_c]] %[[#cond_false]]
|
||||
; CHECK: OpSelectionMerge %[[#if_end:]]
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#if_then:]] %[[#if_end]]
|
||||
; CHECK: %[[#a_merge]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#]] %[[#r2m_a]]
|
||||
; CHECK: OpSelectionMerge %[[#b_merge:]]
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#b_true:]] %[[#b_merge]]
|
||||
a_merge:
|
||||
%1 = phi i1 [ true, %a_true ], [ false, %a_false ]
|
||||
br i1 %1, label %b_true, label %b_merge
|
||||
|
||||
if.then: ; preds = %cond.end
|
||||
%4 = load i32, ptr %val, align 4
|
||||
%inc = add nsw i32 %4, 1
|
||||
store i32 %inc, ptr %val, align 4
|
||||
br label %if.end
|
||||
; CHECK: %[[#if_then]] = OpLabel
|
||||
; CHECK: OpBranch %[[#if_end]]
|
||||
; CHECK: %[[#b_true]] = OpLabel
|
||||
; CHECK: OpBranch %[[#b_merge]]
|
||||
b_true:
|
||||
store i32 0, ptr %var ; Prevents whole branch optimization.
|
||||
br label %b_merge
|
||||
|
||||
if.end: ; preds = %if.then, %cond.end
|
||||
%call2 = call spir_func noundef i32 @_Z2fnv() #4 [ "convergencectrl"(token %0) ]
|
||||
%tobool3 = icmp ne i32 %call2, 0
|
||||
br i1 %tobool3, label %cond.true4, label %cond.false6
|
||||
; CHECK: %[[#if_end]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#cond_end8:]]
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#cond_true4:]] %[[#cond_false6:]]
|
||||
; CHECK: %[[#b_merge]] = OpLabel
|
||||
; CHECK: OpFunctionCall
|
||||
; CHECK: OpSelectionMerge %[[#c_merge:]]
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#c_true:]] %[[#c_false:]]
|
||||
b_merge:
|
||||
%f1 = call spir_func noundef i32 @_Z2fnv() #4 [ "convergencectrl"(token %0) ]
|
||||
br i1 true, label %c_true, label %c_false
|
||||
|
||||
cond.true4: ; preds = %if.end
|
||||
%call5 = call spir_func noundef i32 @_Z3fn1v() #4 [ "convergencectrl"(token %0) ]
|
||||
br label %cond.end8
|
||||
; CHECK: %[[#cond_true4]] = OpLabel
|
||||
; CHECK: OpBranch %[[#cond_end8]]
|
||||
; CHECK: %[[#c_true]] = OpLabel
|
||||
; CHECK: %[[#]] = OpFunctionCall
|
||||
; CHECK: OpStore %[[#r2m_b]] %[[#]]
|
||||
; CHECK: OpBranch %[[#c_merge]]
|
||||
c_true:
|
||||
%f2 = call spir_func noundef i32 @_Z3fn1v() #4 [ "convergencectrl"(token %0) ]
|
||||
br label %c_merge
|
||||
|
||||
cond.false6: ; preds = %if.end
|
||||
%call7 = call spir_func noundef i32 @_Z3fn2v() #4 [ "convergencectrl"(token %0) ]
|
||||
br label %cond.end8
|
||||
; CHECK: %[[#cond_false6]] = OpLabel
|
||||
; CHECK: OpBranch %[[#cond_end8]]
|
||||
; CHECK: %[[#c_false]] = OpLabel
|
||||
; CHECK: %[[#]] = OpFunctionCall
|
||||
; CHECK: OpStore %[[#r2m_b]] %[[#]]
|
||||
; CHECK: OpBranch %[[#c_merge]]
|
||||
c_false:
|
||||
%f3 = call spir_func noundef i32 @_Z3fn2v() #4 [ "convergencectrl"(token %0) ]
|
||||
br label %c_merge
|
||||
|
||||
cond.end8: ; preds = %cond.false6, %cond.true4
|
||||
%cond9 = phi i32 [ %call5, %cond.true4 ], [ %call7, %cond.false6 ]
|
||||
%tobool10 = icmp ne i32 %cond9, 0
|
||||
br i1 %tobool10, label %if.then11, label %if.end13
|
||||
; CHECK: %[[#cond_end8]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#if_end13:]]
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#if_then11:]] %[[#if_end13]]
|
||||
; CHECK: %[[#c_merge]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#]] %[[#r2m_b]]
|
||||
; CHECK: OpStore %[[#r2m_c]] %[[#tmp:]]
|
||||
; CHECK: OpSelectionMerge %[[#d_merge:]]
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#d_true:]] %[[#d_merge]]
|
||||
c_merge:
|
||||
%5 = phi i32 [ %f2, %c_true ], [ %f3, %c_false ]
|
||||
br i1 true, label %d_true, label %d_merge
|
||||
|
||||
if.then11: ; preds = %cond.end8
|
||||
%5 = load i32, ptr %val, align 4
|
||||
%inc12 = add nsw i32 %5, 1
|
||||
store i32 %inc12, ptr %val, align 4
|
||||
br label %if.end13
|
||||
; CHECK: %[[#if_then11]] = OpLabel
|
||||
; CHECK: OpBranch %[[#if_end13]]
|
||||
; CHECK: %[[#d_true]] = OpLabel
|
||||
; CHECK: OpBranch %[[#d_merge]]
|
||||
d_true:
|
||||
store i32 0, ptr %var ; Prevents whole branch optimization.
|
||||
br label %d_merge
|
||||
|
||||
if.end13: ; preds = %if.then11, %cond.end8
|
||||
%6 = load i32, ptr %val, align 4
|
||||
ret i32 %6
|
||||
; CHECK: %[[#if_end13]] = OpLabel
|
||||
; CHECK: OpReturnValue
|
||||
; CHECK: %[[#d_merge]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#]] %[[#r2m_c]]
|
||||
; CHECK: OpReturnValue %[[#tmp]]
|
||||
d_merge:
|
||||
ret i32 %5
|
||||
}
|
||||
|
||||
; Function Attrs: convergent noinline norecurse nounwind optnone
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=2
|
||||
|
||||
; int foo() { return true; }
|
||||
;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=10
|
||||
; RUN: %if spirv-tools %{ llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-as --preserve-numeric-ids - -o - | spirv-val %}
|
||||
;
|
||||
; Source HLSL:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
; RUN: %if spirv-tools %{ llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-as --preserve-numeric-ids - -o - | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=142
|
||||
;
|
||||
; Source HLSL:
|
||||
;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
; RUN: %if spirv-tools %{ llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-as --preserve-numeric-ids - -o - | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=4
|
||||
;
|
||||
; Source HLSL:
|
||||
;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=19
|
||||
|
||||
;
|
||||
; int process() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=2563170
|
||||
|
||||
;
|
||||
; int process() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=9
|
||||
|
||||
;
|
||||
; int process() {
|
||||
@@ -139,10 +138,10 @@
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#bb130:]] %[[#bb125:]]
|
||||
; CHECK: %[[#bb130:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb126:]]
|
||||
; CHECK: %[[#bb125:]] = OpLabel
|
||||
; CHECK: OpReturnValue %[[#]]
|
||||
; CHECK: %[[#bb126:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb124:]]
|
||||
; CHECK: %[[#bb125:]] = OpLabel
|
||||
; CHECK: OpReturnValue %[[#]]
|
||||
; CHECK: OpFunctionEnd
|
||||
; CHECK: %[[#func_83:]] = OpFunction %[[#void:]] DontInline %[[#]]
|
||||
; CHECK: %[[#bb131:]] = OpLabel
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=3
|
||||
|
||||
;
|
||||
; int process() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=6
|
||||
|
||||
;
|
||||
; int process() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=3
|
||||
|
||||
|
||||
;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=2
|
||||
|
||||
;
|
||||
; int process() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=1
|
||||
|
||||
;
|
||||
; int fn() { return true; }
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=3
|
||||
|
||||
;
|
||||
; int fn() { return true; }
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=0
|
||||
|
||||
;
|
||||
; int process() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=308
|
||||
|
||||
;
|
||||
; int foo() { return 200; }
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=5
|
||||
|
||||
;
|
||||
; int process() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | spirv-sim --function=_Z7processv --wave=1 --expects=5
|
||||
|
||||
;
|
||||
; int foo() { return 200; }
|
||||
|
||||
@@ -41,46 +41,44 @@
|
||||
; }
|
||||
|
||||
; CHECK: %[[#func_16:]] = OpFunction %[[#uint:]] DontInline %[[#]]
|
||||
; CHECK: %[[#bb37:]] = OpLabel
|
||||
; CHECK: %[[#bb44:]] = OpLabel
|
||||
; CHECK: OpReturnValue %[[#]]
|
||||
; CHECK: OpFunctionEnd
|
||||
; CHECK: %[[#func_17:]] = OpFunction %[[#void:]] DontInline %[[#]]
|
||||
; CHECK: %[[#bb38:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb39:]]
|
||||
; CHECK: %[[#bb39:]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#bb40:]] %[[#bb41:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#bb42:]] %[[#bb40:]]
|
||||
; CHECK: %[[#bb42:]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#bb40:]] %[[#bb43:]]
|
||||
; CHECK: %[[#bb43:]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#bb40:]] %[[#bb41:]]
|
||||
; CHECK: %[[#bb40:]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#bb44:]] None
|
||||
; CHECK: OpSwitch %[[#]] %[[#bb44:]] 1 %[[#bb44:]] 2 %[[#bb44:]]
|
||||
; CHECK: %[[#bb41:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb39:]]
|
||||
; CHECK: %[[#bb44:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb45:]]
|
||||
; CHECK: %[[#func_19:]] = OpFunction %[[#void:]] DontInline %[[#]]
|
||||
; CHECK: %[[#bb45:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb46:]]
|
||||
; CHECK: %[[#bb46:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb47:]]
|
||||
; CHECK: %[[#bb47:]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#bb48:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#bb49:]] %[[#bb48:]]
|
||||
; CHECK: OpLoopMerge %[[#bb47:]] %[[#bb48:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#bb49:]] %[[#bb47:]]
|
||||
; CHECK: %[[#bb49:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb48:]]
|
||||
; CHECK: %[[#bb48:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb50:]]
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#bb47:]] %[[#bb50:]]
|
||||
; CHECK: %[[#bb50:]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
; CHECK: OpFunctionEnd
|
||||
; CHECK: %[[#func_35:]] = OpFunction %[[#void:]] None %[[#]]
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#bb47:]] %[[#bb48:]]
|
||||
; CHECK: %[[#bb48:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb46:]]
|
||||
; CHECK: %[[#bb47:]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#bb51:]] None
|
||||
; CHECK: OpSwitch %[[#]] %[[#bb51:]] 1 %[[#bb51:]] 2 %[[#bb51:]]
|
||||
; CHECK: %[[#bb51:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb52:]]
|
||||
; CHECK: %[[#bb52:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb53:]]
|
||||
; CHECK: %[[#bb53:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb54:]]
|
||||
; CHECK: %[[#bb54:]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#bb55:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#bb56:]] %[[#bb55:]]
|
||||
; CHECK: %[[#bb56:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb55:]]
|
||||
; CHECK: %[[#bb55:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#bb57:]]
|
||||
; CHECK: %[[#bb57:]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
; CHECK: OpFunctionEnd
|
||||
; CHECK: %[[#func_40:]] = OpFunction %[[#void:]] None %[[#]]
|
||||
; CHECK: %[[#bb58:]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
; CHECK: OpFunctionEnd
|
||||
|
||||
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s --match-full-lines
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan-compute"
|
||||
@@ -25,90 +25,92 @@ entry:
|
||||
ret i32 1
|
||||
}
|
||||
|
||||
|
||||
; CHECK-DAG: OpName %[[#reg_0:]] "cond.reg2mem"
|
||||
; CHECK-DAG: OpName %[[#reg_1:]] "cond9.reg2mem"
|
||||
|
||||
define internal spir_func void @main() #0 {
|
||||
; CHECK: %[[#cond:]] = OpINotEqual %[[#bool_ty:]] %[[#a:]] %[[#b:]]
|
||||
; CHECK: OpSelectionMerge %[[#cond_end:]] None
|
||||
; CHECK: OpBranchConditional %[[#cond]] %[[#cond_true:]] %[[#cond_false:]]
|
||||
; CHECK: OpSelectionMerge %[[#cond1_merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#cond1_true:]] %[[#cond1_false:]]
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
%a = alloca i32, align 4
|
||||
%b = alloca i32, align 4
|
||||
%c = alloca i32, align 4
|
||||
%val = alloca i32, align 4
|
||||
store i32 0, ptr %val, align 4
|
||||
%1 = load i32, ptr %a, align 4
|
||||
%tobool = icmp ne i32 %1, 0
|
||||
br i1 %tobool, label %cond.true, label %cond.false
|
||||
br i1 true, label %cond1_true, label %cond1_false
|
||||
|
||||
; CHECK: %[[#cond_true]] = OpLabel
|
||||
; CHECK: OpBranch %[[#cond_end]]
|
||||
cond.true:
|
||||
%2 = load i32, ptr %b, align 4
|
||||
br label %cond.end
|
||||
; CHECK: %[[#cond1_true]] = OpLabel
|
||||
; CHECK: OpStore %[[#reg_0]] %[[#]]
|
||||
; CHECK: OpBranch %[[#cond1_merge]]
|
||||
cond1_true:
|
||||
%2 = load i32, ptr %a, align 4
|
||||
br label %cond1_merge
|
||||
|
||||
; CHECK: %[[#cond_false]] = OpLabel
|
||||
; CHECK: OpBranch %[[#cond_end]]
|
||||
cond.false:
|
||||
%3 = load i32, ptr %c, align 4
|
||||
br label %cond.end
|
||||
; CHECK: %[[#cond1_false]] = OpLabel
|
||||
; CHECK: OpStore %[[#reg_0]] %[[#]]
|
||||
; CHECK: OpBranch %[[#cond1_merge]]
|
||||
cond1_false:
|
||||
%3 = load i32, ptr %b, align 4
|
||||
br label %cond1_merge
|
||||
|
||||
; CHECK: %[[#cond_end]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpPhi %[[#int_ty:]] %[[#load_cond_true:]] %[[#cond_true]] %[[#load_cond_false:]] %[[#cond_false:]]
|
||||
; CHECK: %[[#cond:]] = OpINotEqual %[[#bool_ty]] %[[#tmp]] %[[#int_0:]]
|
||||
; CHECK: OpSelectionMerge %[[#if_end:]] None
|
||||
; CHECK: OpBranchConditional %[[#cond]] %[[#if_then:]] %[[#if_end]]
|
||||
cond.end:
|
||||
%cond = phi i32 [ %2, %cond.true ], [ %3, %cond.false ]
|
||||
; CHECK: %[[#cond1_merge]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#]] %[[#reg_0]]
|
||||
; CHECK: %[[#cond:]] = OpINotEqual %[[#]] %[[#tmp]] %[[#]]
|
||||
; CHECK: OpSelectionMerge %[[#cond2_merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#cond]] %[[#cond2_true:]] %[[#cond2_merge]]
|
||||
cond1_merge:
|
||||
%cond = phi i32 [ %2, %cond1_true ], [ %3, %cond1_false ]
|
||||
%tobool1 = icmp ne i32 %cond, 0
|
||||
br i1 %tobool1, label %if.then, label %if.end
|
||||
br i1 %tobool1, label %cond2_true, label %cond2_merge
|
||||
|
||||
; CHECK: %[[#if_then]] = OpLabel
|
||||
; CHECK: OpBranch %[[#if_end]]
|
||||
if.then:
|
||||
%4 = load i32, ptr %val, align 4
|
||||
%inc = add nsw i32 %4, 1
|
||||
store i32 %inc, ptr %val, align 4
|
||||
br label %if.end
|
||||
; CHECK: %[[#cond2_true]] = OpLabel
|
||||
; CHECK: OpBranch %[[#cond2_merge]]
|
||||
cond2_true:
|
||||
store i32 0, ptr %a
|
||||
br label %cond2_merge
|
||||
|
||||
; CHECK: %[[#if_end]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#cond_end8:]] None
|
||||
; CHECK: OpBranchConditional %[[#tmp:]] %[[#cond4_true:]] %[[#cond_false6:]]
|
||||
if.end:
|
||||
; CHECK: %[[#cond2_merge]] = OpLabel
|
||||
; CHECK: OpFunctionCall
|
||||
; CHECK: OpSelectionMerge %[[#cond3_merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#cond3_true:]] %[[#cond3_false:]]
|
||||
cond2_merge:
|
||||
%call2 = call spir_func noundef i32 @fn() #4 [ "convergencectrl"(token %0) ]
|
||||
%tobool3 = icmp ne i32 %call2, 0
|
||||
br i1 %tobool3, label %cond.true4, label %cond.false6
|
||||
br i1 true, label %cond3_true, label %cond3_false
|
||||
|
||||
; CHECK: %[[#cond3_true]] = OpLabel
|
||||
; CHECK: OpFunctionCall
|
||||
; CHECK: OpStore %[[#reg_1]] %[[#]]
|
||||
; CHECK: OpBranch %[[#cond3_merge]]
|
||||
cond3_true:
|
||||
%call5 = call spir_func noundef i32 @fn1() #4 [ "convergencectrl"(token %0) ]
|
||||
br label %cond3_merge
|
||||
|
||||
; CHECK: %[[#cond3_false]] = OpLabel
|
||||
; CHECK: OpFunctionCall
|
||||
; CHECK: OpStore %[[#reg_1]] %[[#]]
|
||||
; CHECK: OpBranch %[[#cond3_merge]]
|
||||
cond3_false:
|
||||
%call7 = call spir_func noundef i32 @fn2() #4 [ "convergencectrl"(token %0) ]
|
||||
br label %cond3_merge
|
||||
|
||||
; CHECK: %[[#cond3_merge]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#]] %[[#reg_1]]
|
||||
; CHECK: %[[#cond:]] = OpINotEqual %[[#]] %[[#tmp]] %[[#]]
|
||||
; CHECK: OpSelectionMerge %[[#cond4_merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#cond]] %[[#cond4_true:]] %[[#cond4_merge]]
|
||||
cond3_merge:
|
||||
%cond9 = phi i32 [ %call5, %cond3_true ], [ %call7, %cond3_false ]
|
||||
%tobool10 = icmp ne i32 %cond9, 0
|
||||
br i1 %tobool10, label %cond4_true, label %cond4_merge
|
||||
|
||||
; CHECK: %[[#cond4_true]] = OpLabel
|
||||
; CHECK: OpBranch %[[#cond_end8]]
|
||||
cond.true4:
|
||||
%call5 = call spir_func noundef i32 @fn1() #4 [ "convergencectrl"(token %0) ]
|
||||
br label %cond.end8
|
||||
; CHECK: OpBranch %[[#cond4_merge]]
|
||||
cond4_true:
|
||||
store i32 0, ptr %a
|
||||
br label %cond4_merge
|
||||
|
||||
; CHECK: %[[#cond_false6]] = OpLabel
|
||||
; CHECK: OpBranch %[[#cond_end8]]
|
||||
cond.false6:
|
||||
%call7 = call spir_func noundef i32 @fn2() #4 [ "convergencectrl"(token %0) ]
|
||||
br label %cond.end8
|
||||
|
||||
; CHECK: %[[#cond_end8]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#if_end13:]] None
|
||||
; CHECK: OpBranchConditional %[[#tmp:]] %[[#if_then11:]] %[[#if_end13]]
|
||||
cond.end8:
|
||||
%cond9 = phi i32 [ %call5, %cond.true4 ], [ %call7, %cond.false6 ]
|
||||
%tobool10 = icmp ne i32 %cond9, 0
|
||||
br i1 %tobool10, label %if.then11, label %if.end13
|
||||
|
||||
; CHECK: %[[#if_then11]] = OpLabel
|
||||
; CHECK: OpBranch %[[#if_end13]]
|
||||
if.then11:
|
||||
%5 = load i32, ptr %val, align 4
|
||||
%inc12 = add nsw i32 %5, 1
|
||||
store i32 %inc12, ptr %val, align 4
|
||||
br label %if.end13
|
||||
|
||||
; CHECK: %[[#if_end13]] = OpLabel
|
||||
; CHECK: %[[#cond4_merge]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
if.end13:
|
||||
cond4_merge:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s --match-full-lines
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
@@ -12,100 +12,98 @@ entry:
|
||||
|
||||
define internal spir_func void @main() #2 {
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do_body:]]
|
||||
; CHECK: OpBranch %[[#do_header:]]
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
%val = alloca i32, align 4
|
||||
%i = alloca i32, align 4
|
||||
store i32 0, ptr %val, align 4
|
||||
store i32 0, ptr %i, align 4
|
||||
br label %do.body
|
||||
%var = alloca i32, align 4
|
||||
br label %do_header
|
||||
|
||||
; Here a the loop header had to be split in two:
|
||||
; - 1 header for the loop
|
||||
; - 1 header for the condition.
|
||||
; In SPIR-V, a loop header cannot directly
|
||||
; CHECK: %[[#do_header:]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do_end:]] %[[#do_cond:]] None
|
||||
; CHECK: OpBranch %[[#do_body:]]
|
||||
; CHECK: OpLoopMerge %[[#do_merge:]] %[[#do_latch:]] None
|
||||
; CHECK: OpBranch %[[#new_header:]]
|
||||
|
||||
; CHECK: %[[#do_body]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#if_then:]] None
|
||||
; CHECK: OpBranchConditional %[[#cond:]] %[[#if_then]] %[[#if_end:]]
|
||||
do.body:
|
||||
; CHECK: %[[#new_header]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#if_merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#if_then:]] %[[#if_end:]]
|
||||
do_header:
|
||||
%1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
|
||||
%2 = load i32, ptr %i, align 4
|
||||
%inc = add nsw i32 %2, 1
|
||||
store i32 %inc, ptr %i, align 4
|
||||
%3 = load i32, ptr %i, align 4
|
||||
%cmp = icmp sgt i32 %3, 5
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
||||
; CHECK: %[[#if_end]] = OpLabel
|
||||
; CHECK: OpBranch %[[#if_then]]
|
||||
if.end:
|
||||
%4 = load i32, ptr %i, align 4
|
||||
store i32 %4, ptr %val, align 4
|
||||
br label %do.cond
|
||||
store i32 0, ptr %var
|
||||
br i1 true, label %if.then, label %if.end
|
||||
|
||||
; CHECK: %[[#if_then]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do_cond]]
|
||||
; CHECK: OpBranch %[[#if_merge]]
|
||||
if.then:
|
||||
br label %do.cond
|
||||
store i32 0, ptr %var
|
||||
br label %do_latch
|
||||
|
||||
; CHECK: %[[#do_cond]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#cond:]] %[[#do_header]] %[[#do_end]]
|
||||
do.cond:
|
||||
%5 = load i32, ptr %i, align 4
|
||||
%cmp1 = icmp slt i32 %5, 10
|
||||
br i1 %cmp1, label %do.body, label %do.end
|
||||
; CHECK: %[[#if_end]] = OpLabel
|
||||
; CHECK: OpBranch %[[#if_merge]]
|
||||
if.end:
|
||||
store i32 0, ptr %var
|
||||
br label %do_latch
|
||||
|
||||
; CHECK: %[[#do_end]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do_body2:]]
|
||||
; CHECK: %[[#if_merge]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#do_latch]] %[[#do_merge]]
|
||||
|
||||
; CHECK: %[[#do_latch]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do_header]]
|
||||
do_latch:
|
||||
store i32 0, ptr %var
|
||||
br i1 true, label %do_header, label %do.end
|
||||
|
||||
; CHECK: %[[#do_merge]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do2_header:]]
|
||||
do.end:
|
||||
br label %do.body2
|
||||
store i32 0, ptr %var
|
||||
br label %do2_header
|
||||
|
||||
; CHECK: %[[#do_body2]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do_end11:]] %[[#do_cond9:]] None
|
||||
; CHECK: OpBranch %[[#do_body4:]]
|
||||
do.body2:
|
||||
; CHECK: %[[#do2_header]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do2_merge:]] %[[#do2_continue:]] None
|
||||
; CHECK: OpBranch %[[#do3_header:]]
|
||||
do2_header:
|
||||
%6 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
|
||||
%7 = load i32, ptr %i, align 4
|
||||
%inc3 = add nsw i32 %7, 1
|
||||
store i32 %inc3, ptr %i, align 4
|
||||
br label %do.body4
|
||||
store i32 0, ptr %var
|
||||
br label %do3_header
|
||||
|
||||
; CHECK: %[[#do_body4]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do_end8:]] %[[#do_cond6:]] None
|
||||
; CHECK: OpBranch %[[#do_cond6]]
|
||||
do.body4:
|
||||
; CHECK: %[[#do3_header]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do3_merge:]] %[[#do3_continue:]] None
|
||||
; CHECK: OpBranch %[[#do3_body:]]
|
||||
do3_header:
|
||||
%8 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %6) ]
|
||||
%9 = load i32, ptr %val, align 4
|
||||
%inc5 = add nsw i32 %9, 1
|
||||
store i32 %inc5, ptr %val, align 4
|
||||
br label %do.cond6
|
||||
store i32 0, ptr %var
|
||||
br label %do3_continue
|
||||
|
||||
; CHECK: %[[#do_cond6]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#cond:]] %[[#do_body4]] %[[#do_end8]]
|
||||
do.cond6:
|
||||
%10 = load i32, ptr %i, align 4
|
||||
%cmp7 = icmp slt i32 %10, 10
|
||||
br i1 %cmp7, label %do.body4, label %do.end8
|
||||
; CHECK: %[[#do3_body]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#do3_continue]] %[[#do3_merge]]
|
||||
|
||||
; CHECK: %[[#do_end8]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do_cond9]]
|
||||
do.end8:
|
||||
%11 = load i32, ptr %i, align 4
|
||||
%dec = add nsw i32 %11, -1
|
||||
store i32 %dec, ptr %i, align 4
|
||||
br label %do.cond9
|
||||
; CHECK: %[[#do3_continue]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do3_header]]
|
||||
do3_continue:
|
||||
store i32 0, ptr %var
|
||||
br i1 true, label %do3_header, label %do3_merge
|
||||
|
||||
; CHECK: %[[#do_cond9]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#cond:]] %[[#do_body2]] %[[#do_end11]]
|
||||
do.cond9:
|
||||
%12 = load i32, ptr %val, align 4
|
||||
%cmp10 = icmp slt i32 %12, 10
|
||||
br i1 %cmp10, label %do.body2, label %do.end11
|
||||
; CHECK: %[[#do3_merge]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do2_new_latch:]]
|
||||
do3_merge:
|
||||
store i32 0, ptr %var
|
||||
br label %do2_continue
|
||||
|
||||
; CHECK: %[[#do_end11]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
do.end11:
|
||||
; CHECK: %[[#do2_new_latch]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#do2_continue]] %[[#do2_merge]]
|
||||
|
||||
; CHECK: %[[#do2_continue]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do2_header]]
|
||||
do2_continue:
|
||||
store i32 0, ptr %var
|
||||
br i1 true, label %do2_header, label %do2_merge
|
||||
|
||||
; CHECK: %[[#do2_merge]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
do2_merge:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s --match-full-lines
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
@@ -8,84 +8,72 @@ define internal spir_func void @main() #0 {
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
%val = alloca i32, align 4
|
||||
%i = alloca i32, align 4
|
||||
%j = alloca i32, align 4
|
||||
%k = alloca i32, align 4
|
||||
store i32 0, ptr %val, align 4
|
||||
store i32 0, ptr %i, align 4
|
||||
store i32 0, ptr %j, align 4
|
||||
store i32 0, ptr %k, align 4
|
||||
br label %do.body
|
||||
%var = alloca i32, align 4
|
||||
br label %do1_header
|
||||
|
||||
; CHECK: %[[#do_1_header:]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#end:]] %[[#do_1_latch:]] None
|
||||
; CHECK: OpBranch %[[#do_2_header:]]
|
||||
do.body:
|
||||
; CHECK: %[[#do1_header:]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do1_merge:]] %[[#do1_continue:]] None
|
||||
; CHECK: OpBranch %[[#do2_header:]]
|
||||
do1_header:
|
||||
%1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
|
||||
%2 = load i32, ptr %val, align 4
|
||||
%3 = load i32, ptr %i, align 4
|
||||
%add = add nsw i32 %2, %3
|
||||
store i32 %add, ptr %val, align 4
|
||||
br label %do.body1
|
||||
store i32 0, ptr %var
|
||||
br label %do2_header
|
||||
|
||||
; CHECK: %[[#do_2_header]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do_2_end:]] %[[#do_2_latch:]] None
|
||||
; CHECK: OpBranch %[[#do_2_body:]]
|
||||
do.body1:
|
||||
; CHECK: %[[#do2_header:]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do2_merge:]] %[[#do2_continue:]] None
|
||||
; CHECK: OpBranch %[[#do3_header:]]
|
||||
do2_header:
|
||||
%4 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %1) ]
|
||||
br label %do.body2
|
||||
store i32 0, ptr %var
|
||||
br label %do3_header
|
||||
|
||||
; CHECK: %[[#do_2_body]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do_3_end:]] %[[#do_3_header:]] None
|
||||
; CHECK: OpBranch %[[#do_3_header]]
|
||||
do.body2:
|
||||
; CHECK: %[[#do3_header:]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do3_merge:]] %[[#do3_continue:]] None
|
||||
; CHECK: OpBranch %[[#do3_cond:]]
|
||||
do3_header:
|
||||
%5 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %4) ]
|
||||
%6 = load i32, ptr %k, align 4
|
||||
%inc = add nsw i32 %6, 1
|
||||
store i32 %inc, ptr %k, align 4
|
||||
br label %do.cond
|
||||
store i32 0, ptr %var
|
||||
br label %do3_continue
|
||||
|
||||
; CHECK: %[[#do_3_header]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#cond:]] %[[#do_2_body]] %[[#do_3_end]]
|
||||
do.cond:
|
||||
%7 = load i32, ptr %k, align 4
|
||||
%cmp = icmp slt i32 %7, 30
|
||||
br i1 %cmp, label %do.body2, label %do.end
|
||||
; CHECK: %[[#do3_cond]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#do3_continue]] %[[#do3_merge]]
|
||||
; CHECK: %[[#do3_continue]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do3_header]]
|
||||
do3_continue:
|
||||
store i32 0, ptr %var
|
||||
br i1 true, label %do3_header, label %do3_merge
|
||||
|
||||
; CHECK: %[[#do_3_end]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do_2_latch]]
|
||||
do.end:
|
||||
%8 = load i32, ptr %j, align 4
|
||||
%inc3 = add nsw i32 %8, 1
|
||||
store i32 %inc3, ptr %j, align 4
|
||||
br label %do.cond4
|
||||
; CHECK: %[[#do3_merge]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do2_cond:]]
|
||||
do3_merge:
|
||||
store i32 0, ptr %var
|
||||
br label %do2_continue
|
||||
|
||||
; CHECK: %[[#do_2_latch]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#cond:]] %[[#do_2_header]] %[[#do_2_end]]
|
||||
do.cond4:
|
||||
%9 = load i32, ptr %j, align 4
|
||||
%cmp5 = icmp slt i32 %9, 20
|
||||
br i1 %cmp5, label %do.body1, label %do.end6
|
||||
; CHECK: %[[#do2_cond]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#do2_continue]] %[[#do2_merge]]
|
||||
; CHECK: %[[#do2_continue]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do2_header]]
|
||||
do2_continue:
|
||||
store i32 0, ptr %var
|
||||
br i1 true, label %do2_header, label %do2_merge
|
||||
|
||||
; CHECK: %[[#do_2_end]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do_1_latch]]
|
||||
do.end6:
|
||||
%10 = load i32, ptr %i, align 4
|
||||
%inc7 = add nsw i32 %10, 1
|
||||
store i32 %inc7, ptr %i, align 4
|
||||
br label %do.cond8
|
||||
; CHECK: %[[#do2_merge]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do1_cond:]]
|
||||
do2_merge:
|
||||
store i32 0, ptr %var
|
||||
br label %do1_continue
|
||||
|
||||
; CHECK: %[[#do_1_latch]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#cond:]] %[[#do_1_header]] %[[#end]]
|
||||
do.cond8:
|
||||
%11 = load i32, ptr %i, align 4
|
||||
%cmp9 = icmp slt i32 %11, 10
|
||||
br i1 %cmp9, label %do.body, label %do.end10
|
||||
; CHECK: %[[#do1_cond]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#do1_continue]] %[[#do1_merge]]
|
||||
; CHECK: %[[#do1_continue]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do1_header]]
|
||||
do1_continue:
|
||||
store i32 0, ptr %var
|
||||
br i1 true, label %do1_header, label %do1_merge
|
||||
|
||||
; CHECK: %[[#end]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
do.end10:
|
||||
; CHECK: %[[#do1_merge]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
do1_merge:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@@ -15,71 +15,75 @@ entry:
|
||||
|
||||
define internal spir_func void @main() #2 {
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do_body:]]
|
||||
; CHECK: OpBranch %[[#do1_header:]]
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
%val = alloca i32, align 4
|
||||
%i = alloca i32, align 4
|
||||
store i32 0, ptr %val, align 4
|
||||
store i32 0, ptr %i, align 4
|
||||
br label %do.body
|
||||
%var = alloca i32, align 4
|
||||
br label %do1_header
|
||||
|
||||
; CHECK: %[[#do_body]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do_end:]] %[[#do_cond:]] None
|
||||
; CHECK: OpBranch %[[#do_cond]]
|
||||
do.body:
|
||||
; CHECK: %[[#do1_header]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do1_merge:]] %[[#do1_continue:]] None
|
||||
; CHECK: OpBranch %[[#do1_cond:]]
|
||||
do1_header:
|
||||
%1 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
|
||||
%2 = load i32, ptr %i, align 4
|
||||
store i32 %2, ptr %val, align 4
|
||||
br label %do.cond
|
||||
store i32 0, ptr %var
|
||||
br label %do1_continue
|
||||
|
||||
; CHECK: %[[#do_cond]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#cond:]] %[[#do_body]] %[[#do_end]]
|
||||
do.cond:
|
||||
%3 = load i32, ptr %i, align 4
|
||||
%cmp = icmp slt i32 %3, 10
|
||||
br i1 %cmp, label %do.body, label %do.end
|
||||
; CHECK: %[[#do1_cond]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#do1_continue]] %[[#do1_merge]]
|
||||
; CHECK: %[[#do1_continue]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do1_header]]
|
||||
do1_continue:
|
||||
store i32 0, ptr %var
|
||||
br i1 true, label %do1_header, label %do1_merge
|
||||
|
||||
; CHECK: %[[#do_end]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do_body1:]]
|
||||
do.end:
|
||||
br label %do.body1
|
||||
; CHECK: %[[#do1_merge]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do2_header:]]
|
||||
do1_merge:
|
||||
store i32 0, ptr %var
|
||||
br label %do2_header
|
||||
|
||||
; CHECK: %[[#do_body1]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do_end3:]] %[[#do_cond2:]] None
|
||||
; CHECK: OpBranch %[[#do_cond2]]
|
||||
do.body1:
|
||||
; CHECK: %[[#do2_header]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do2_merge:]] %[[#do2_continue:]] None
|
||||
; CHECK: OpBranch %[[#do2_cond:]]
|
||||
do2_header:
|
||||
%4 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
|
||||
store i32 0, ptr %val, align 4
|
||||
br label %do.cond2
|
||||
store i32 0, ptr %var
|
||||
br label %do2_continue
|
||||
|
||||
; CHECK: %[[#do_cond2]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#cond:]] %[[#do_body1]] %[[#do_end3]]
|
||||
do.cond2:
|
||||
br i1 true, label %do.body1, label %do.end3
|
||||
; CHECK: %[[#do2_cond]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#do2_continue]] %[[#do2_merge]]
|
||||
; CHECK: %[[#do2_continue]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do2_header]]
|
||||
do2_continue:
|
||||
store i32 0, ptr %var
|
||||
br i1 true, label %do2_header, label %do2_merge
|
||||
|
||||
; CHECK: %[[#do_end3]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do_body4:]]
|
||||
do.end3:
|
||||
br label %do.body4
|
||||
; CHECK: %[[#do2_merge]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do3_header:]]
|
||||
do2_merge:
|
||||
store i32 0, ptr %var
|
||||
br label %do3_header
|
||||
|
||||
; CHECK: %[[#do_body4]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do_end7:]] %[[#do_cond5:]] None
|
||||
; CHECK: OpBranch %[[#do_cond5]]
|
||||
do.body4:
|
||||
; CHECK: %[[#do3_header]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#do3_merge:]] %[[#do3_continue:]] None
|
||||
; CHECK: OpBranch %[[#do3_cond:]]
|
||||
do3_header:
|
||||
%5 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
|
||||
br label %do.cond5
|
||||
store i32 0, ptr %var
|
||||
br label %do3_continue
|
||||
|
||||
; CHECK: %[[#do_cond5]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#cond:]] %[[#do_body4]] %[[#do_end7]]
|
||||
do.cond5:
|
||||
%6 = load i32, ptr %val, align 4
|
||||
%cmp6 = icmp slt i32 %6, 20
|
||||
br i1 %cmp6, label %do.body4, label %do.end7
|
||||
; CHECK: %[[#do3_cond]] = OpLabel
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#do3_continue]] %[[#do3_merge]]
|
||||
; CHECK: %[[#do3_continue]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do3_header]]
|
||||
do3_continue:
|
||||
store i32 0, ptr %var
|
||||
br i1 true, label %do3_header, label %do3_merge
|
||||
|
||||
; CHECK: %[[#do_end7]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
do.end7:
|
||||
; CHECK: %[[#do3_merge]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
do3_merge:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@@ -1,84 +1,77 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - --asm-verbose=0 | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - --asm-verbose=0 | FileCheck %s --match-full-lines
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
|
||||
; CHECK-DAG: OpName %[[#fn:]] "fn"
|
||||
; CHECK-DAG: OpName %[[#main:]] "main"
|
||||
; CHECK-DAG: OpName %[[#var_a:]] "a"
|
||||
; CHECK-DAG: OpName %[[#var_b:]] "b"
|
||||
|
||||
; CHECK-DAG: %[[#bool:]] = OpTypeBool
|
||||
; CHECK-DAG: %[[#true:]] = OpConstantTrue %[[#bool]]
|
||||
|
||||
; CHECK: %[[#fn]] = OpFunction %[[#param:]] DontInline %[[#ftype:]]
|
||||
define spir_func noundef i32 @fn() #0 {
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
ret i32 1
|
||||
}
|
||||
|
||||
; CHECK: %[[#main]] = OpFunction %[[#param:]] DontInline %[[#ftype:]]
|
||||
|
||||
define internal spir_func void @main() #3 {
|
||||
; CHECK-DAG: OpName %[[#switch_0:]] "reg1"
|
||||
; CHECK-DAG: OpName %[[#switch_1:]] "reg"
|
||||
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK-DAG: %[[#var_a]] = OpVariable %[[#type:]] Function
|
||||
; CHECK-DAG: %[[#var_b]] = OpVariable %[[#type:]] Function
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#type:]] %[[#var_a]] Aligned 4
|
||||
; CHECK: %[[#cond:]] = OpINotEqual %[[#bool]] %[[#tmp]] %[[#const:]]
|
||||
; CHECK: OpSelectionMerge %[[#if_end:]] None
|
||||
; CHECK: OpBranchConditional %[[#true]] %[[#cond1:]] %[[#dead:]]
|
||||
; CHECK-DAG: %[[#int_0:]] = OpConstant %[[#]] 0
|
||||
; CHECK-DAG: %[[#int_1:]] = OpConstant %[[#]] 1
|
||||
|
||||
; CHECK: %[[#cond1]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#new_exit:]] None
|
||||
; CHECK: OpBranchConditional %[[#cond]] %[[#new_exit]] %[[#lor_lhs_false:]]
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK-DAG: %[[#switch_0]] = OpVariable %[[#]] Function
|
||||
; CHECK-DAG: %[[#switch_1]] = OpVariable %[[#]] Function
|
||||
; CHECK: OpSelectionMerge %[[#merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#new_header:]] %[[#unreachable:]]
|
||||
|
||||
; CHECK: %[[#dead]] = OpLabel
|
||||
; CHECK-NEXT: OpUnreachable
|
||||
; CHECK: %[[#new_header]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#new_merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#taint_true_merge:]] %[[#br_false:]]
|
||||
|
||||
; CHECK: %[[#lor_lhs_false]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#type:]] %[[#var_b]] Aligned 4
|
||||
; CHECK: %[[#cond:]] = OpINotEqual %[[#bool]] %[[#tmp]] %[[#value:]]
|
||||
; CHECK: OpBranchConditional %[[#cond]] %[[#new_exit]] %[[#alias_exit:]]
|
||||
; CHECK: %[[#unreachable]] = OpLabel
|
||||
; CHECK-NEXT: OpUnreachable
|
||||
|
||||
; CHECK: %[[#alias_exit]] = OpLabel
|
||||
; CHECK: OpBranch %[[#new_exit]]
|
||||
; CHECK: %[[#taint_true_merge]] = OpLabel
|
||||
; CHECK: OpStore %[[#switch_0]] %[[#int_1]]
|
||||
; CHECK: OpBranch %[[#new_merge]]
|
||||
|
||||
; CHECK: %[[#new_exit]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpPhi %[[#type:]] %[[#A:]] %[[#cond1]] %[[#A:]] %[[#lor_lhs_false]] %[[#B:]] %[[#alias_exit]]
|
||||
; CHECK: %[[#cond:]] = OpIEqual %[[#bool]] %[[#A]] %[[#tmp]]
|
||||
; CHECK: OpBranchConditional %[[#cond]] %[[#if_then:]] %[[#if_end]]
|
||||
; CHECK: %[[#br_false]] = OpLabel
|
||||
; CHECK-DAG: OpStore %[[#switch_1]] %[[#int_0]]
|
||||
; CHECK: OpSelectionMerge %[[#taint_merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#taint_merge]] %[[#taint_false:]]
|
||||
|
||||
; CHECK: %[[#if_then]] = OpLabel
|
||||
; CHECK: OpBranch %[[#if_end]]
|
||||
; CHECK: %[[#taint_false]] = OpLabel
|
||||
; CHECK: OpStore %[[#switch_1]] %[[#int_1]]
|
||||
; CHECK: OpBranch %[[#taint_merge]]
|
||||
|
||||
; CHECK: %[[#if_end]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
; CHECK: %[[#taint_merge]] = OpLabel
|
||||
; CHECK: OpStore %[[#switch_0]] %[[#int_0]]
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#]] %[[#switch_1]]
|
||||
; CHECK: %[[#cond:]] = OpIEqual %[[#]] %[[#int_0]] %[[#tmp]]
|
||||
; CHECK: OpBranchConditional %[[#cond]] %[[#taint_false_true:]] %[[#new_merge]]
|
||||
|
||||
; CHECK: %[[#taint_false_true]] = OpLabel
|
||||
; CHECK: OpStore %[[#switch_0]] %[[#int_1]]
|
||||
; CHECK: OpBranch %[[#new_merge]]
|
||||
|
||||
; CHECK: %[[#new_merge]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#]] %[[#switch_0]]
|
||||
; CHECK: %[[#cond:]] = OpIEqual %[[#]] %[[#int_0]] %[[#tmp]]
|
||||
; CHECK: OpBranchConditional %[[#cond]] %[[#merge]] %[[#br_true:]]
|
||||
|
||||
; CHECK: %[[#br_true]] = OpLabel
|
||||
; CHECK: OpBranch %[[#merge]]
|
||||
|
||||
; CHECK: %[[#merge]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
%a = alloca i32, align 4
|
||||
%b = alloca i32, align 4
|
||||
%val = alloca i32, align 4
|
||||
store i32 0, ptr %val, align 4
|
||||
%1 = load i32, ptr %a, align 4
|
||||
%tobool = icmp ne i32 %1, 0
|
||||
br i1 %tobool, label %if.then, label %lor.lhs.false
|
||||
%var = alloca i32, align 4
|
||||
br i1 true, label %br_true, label %br_false
|
||||
|
||||
lor.lhs.false:
|
||||
%2 = load i32, ptr %b, align 4
|
||||
%tobool1 = icmp ne i32 %2, 0
|
||||
br i1 %tobool1, label %if.then, label %if.end
|
||||
br_false:
|
||||
store i32 0, ptr %var, align 4
|
||||
br i1 true, label %br_true, label %merge
|
||||
|
||||
if.then:
|
||||
%8 = load i32, ptr %val, align 4
|
||||
%inc = add nsw i32 %8, 1
|
||||
store i32 %inc, ptr %val, align 4
|
||||
br label %if.end
|
||||
br_true:
|
||||
store i32 0, ptr %var, align 4
|
||||
br label %merge
|
||||
|
||||
if.end:
|
||||
merge:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
104
llvm/test/CodeGen/SPIRV/structurizer/loop-continue-split.ll
Normal file
104
llvm/test/CodeGen/SPIRV/structurizer/loop-continue-split.ll
Normal file
@@ -0,0 +1,104 @@
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
|
||||
; The goal of this test is to voluntarily create 2 overlapping convergence
|
||||
; structures: the loop, and the inner condition.
|
||||
; Here, the condition header also branches to 2 internal nodes, which are not
|
||||
; directly a merge/exits.
|
||||
; This will require a proper header-split.
|
||||
; In addition, splitting the header makes the continue the merge of the inner
|
||||
; condition, so we need to properly split the continue block to create a
|
||||
; valid inner merge, in the correct order.
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
|
||||
; CHECK-DAG: OpName %[[#switch_0:]] "reg1"
|
||||
; CHECK-DAG: OpName %[[#variable:]] "var"
|
||||
|
||||
; CHECK-DAG: %[[#int_0:]] = OpConstant %[[#]] 0
|
||||
; CHECK-DAG: %[[#int_1:]] = OpConstant %[[#]] 1
|
||||
; CHECK-DAG: %[[#int_2:]] = OpConstant %[[#]] 2
|
||||
; CHECK-DAG: %[[#int_3:]] = OpConstant %[[#]] 3
|
||||
; CHECK-DAG: %[[#int_4:]] = OpConstant %[[#]] 4
|
||||
|
||||
define internal spir_func void @main() #1 {
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK: %[[#switch_0]] = OpVariable %[[#]] Function
|
||||
; CHECK: %[[#variable]] = OpVariable %[[#]] Function
|
||||
; CHECK: OpBranch %[[#header:]]
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
%var = alloca i32, align 4
|
||||
br label %header
|
||||
|
||||
; CHECK: %[[#header]] = OpLabel
|
||||
; CHECK: OpLoopMerge %[[#merge:]] %[[#continue:]] None
|
||||
; CHECK: OpBranch %[[#split_header:]]
|
||||
|
||||
; CHECK: %[[#split_header]] = OpLabel
|
||||
; CHECK: OpSelectionMerge %[[#inner_merge:]] None
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#left:]] %[[#right:]]
|
||||
header:
|
||||
%2 = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %0) ]
|
||||
br i1 true, label %left, label %right
|
||||
|
||||
; CHECK: %[[#left]] = OpLabel
|
||||
; CHECK-DAG: OpStore %[[#switch_0]] %[[#int_0]]
|
||||
; CHECK-DAG: OpStore %[[#variable]] %[[#int_1]]
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#inner_merge]] %[[#left_next:]]
|
||||
left:
|
||||
store i32 1, ptr %var
|
||||
br i1 true, label %merge, label %left_next
|
||||
|
||||
; CHECK: %[[#right]] = OpLabel
|
||||
; CHECK-DAG: OpStore %[[#switch_0]] %[[#int_0]]
|
||||
; CHECK-DAG: OpStore %[[#variable]] %[[#int_2]]
|
||||
; CHECK: OpBranchConditional %[[#]] %[[#inner_merge]] %[[#right_next:]]
|
||||
right:
|
||||
store i32 2, ptr %var
|
||||
br i1 true, label %merge, label %right_next
|
||||
|
||||
; CHECK: %[[#left_next]] = OpLabel
|
||||
; CHECK-DAG: OpStore %[[#switch_0]] %[[#int_1]]
|
||||
; CHECK-DAG: OpStore %[[#variable]] %[[#int_3]]
|
||||
; CHECK: OpBranch %[[#inner_merge]]
|
||||
left_next:
|
||||
store i32 3, ptr %var
|
||||
br label %continue
|
||||
|
||||
; CHECK: %[[#right_next]] = OpLabel
|
||||
; CHECK-DAG: OpStore %[[#switch_0]] %[[#int_1]]
|
||||
; CHECK-DAG: OpStore %[[#variable]] %[[#int_4]]
|
||||
; CHECK: OpBranch %[[#inner_merge]]
|
||||
right_next:
|
||||
store i32 4, ptr %var
|
||||
br label %continue
|
||||
|
||||
; CHECK: %[[#inner_merge]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#]] %[[#switch_0]]
|
||||
; CHECK: %[[#cond:]] = OpIEqual %[[#]] %[[#int_0]] %[[#tmp]]
|
||||
; CHECK: OpBranchConditional %[[#cond]] %[[#merge]] %[[#continue]]
|
||||
|
||||
; CHECK: %[[#continue]] = OpLabel
|
||||
; CHECK: OpBranch %[[#header]]
|
||||
continue:
|
||||
br label %header
|
||||
|
||||
; CHECK: %[[#merge]] = OpLabel
|
||||
; CHECK: OpReturn
|
||||
merge:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
declare token @llvm.experimental.convergence.entry() #0
|
||||
declare token @llvm.experimental.convergence.loop() #0
|
||||
|
||||
attributes #0 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
|
||||
attributes #1 = { convergent noinline norecurse nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1}
|
||||
|
||||
!0 = !{i32 1, !"wchar_size", i32 4}
|
||||
!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
|
||||
@@ -1,23 +1,23 @@
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s --match-full-lines
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan-compute"
|
||||
|
||||
define internal spir_func void @main() #0 {
|
||||
|
||||
; CHECK: OpDecorate %[[#builtin:]] BuiltIn SubgroupLocalInvocationId
|
||||
; CHECK-DAG: %[[#int_ty:]] = OpTypeInt 32 0
|
||||
; CHECK-DAG: %[[#int_fpty:]] = OpTypePointer Function %[[#int_ty]]
|
||||
; CHECK-DAG: OpName %[[#idx:]] "idx"
|
||||
; CHECK-DAG: OpDecorate %[[#builtin:]] BuiltIn SubgroupLocalInvocationId
|
||||
; CHECK-DAG: %[[#int_ty:]] = OpTypeInt 32 0
|
||||
; CHECK-DAG: %[[#int_ipty:]] = OpTypePointer Input %[[#int_ty]]
|
||||
; CHECK-DAG: %[[#bool_ty:]] = OpTypeBool
|
||||
; CHECK-DAG: %[[#int_0:]] = OpConstant %[[#int_ty]] 0
|
||||
; CHECK-DAG: %[[#int_10:]] = OpConstant %[[#int_ty]] 10
|
||||
; CHECK-DAG: %[[#builtin]] = OpVariable %[[#int_ipty]] Input
|
||||
; CHECK-DAG: %[[#bool_ty:]] = OpTypeBool
|
||||
; CHECK-DAG: %[[#int_0:]] = OpConstant %[[#int_ty]] 0
|
||||
; CHECK-DAG: %[[#int_10:]] = OpConstant %[[#int_ty]] 10
|
||||
; CHECK-DAG: %[[#builtin]] = OpVariable %[[#int_ipty]] Input
|
||||
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK: %[[#idx:]] = OpVariable %[[#int_fpty]] Function
|
||||
; CHECK: OpStore %[[#idx]] %[[#int_0]] Aligned 4
|
||||
; CHECK: %[[#idx]] = OpVariable %[[#]] Function
|
||||
; ACHECK: OpStore %[[#idx]] %[[#int_0]] Aligned 4
|
||||
; CHECK: OpBranch %[[#while_cond:]]
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
@@ -37,12 +37,12 @@ while.cond:
|
||||
%cmp = icmp ne i32 %2, 10
|
||||
br i1 %cmp, label %while.body, label %while.end
|
||||
|
||||
; CHECK: %[[#while_body]] = OpLabel
|
||||
; CHECK-NEXT: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#builtin]] Aligned 1
|
||||
; CHECK-NEXT: OpStore %[[#idx]] %[[#tmp]] Aligned 4
|
||||
; CHECK-NEXT: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#idx]] Aligned 4
|
||||
; CHECK-NEXT: %[[#cmp1:]] = OpIEqual %[[#bool_ty]] %[[#tmp]] %[[#int_0]]
|
||||
; CHECK: OpBranchConditional %[[#cmp1]] %[[#new_end]] %[[#if_end]]
|
||||
; CHECK: %[[#while_body]] = OpLabel
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#]] %[[#builtin]] Aligned 1
|
||||
; CHECK: OpStore %[[#idx]] %[[#tmp]] Aligned 4
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#idx]] Aligned 4
|
||||
; CHECK: %[[#cmp1:]] = OpIEqual %[[#bool_ty]] %[[#tmp]] %[[#int_0]]
|
||||
; CHECK: OpBranchConditional %[[#cmp1]] %[[#new_end]] %[[#if_end]]
|
||||
while.body:
|
||||
%3 = call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %1) ]
|
||||
store i32 %3, ptr %idx, align 4
|
||||
@@ -50,14 +50,14 @@ while.body:
|
||||
%cmp1 = icmp eq i32 %4, 0
|
||||
br i1 %cmp1, label %if.then, label %if.end
|
||||
|
||||
; CHECK: %[[#if_end]] = OpLabel
|
||||
; CHECK: OpBranch %[[#while_cond]]
|
||||
|
||||
; CHECK: %[[#new_end]] = OpLabel
|
||||
; CHECK: OpBranch %[[#while_end:]]
|
||||
|
||||
if.then:
|
||||
br label %while.end
|
||||
|
||||
; CHECK: %[[#if_end]] = OpLabel
|
||||
; CHECK: OpBranch %[[#while_cond]]
|
||||
if.end:
|
||||
br label %while.cond
|
||||
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s --match-full-lines
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan-compute"
|
||||
|
||||
define internal spir_func void @main() #0 {
|
||||
|
||||
; CHECK: OpDecorate %[[#builtin:]] BuiltIn SubgroupLocalInvocationId
|
||||
|
||||
; CHECK-DAG: OpName %[[#idx:]] "idx"
|
||||
; CHECK-DAG: OpDecorate %[[#builtin:]] BuiltIn SubgroupLocalInvocationId
|
||||
; CHECK-DAG: %[[#int_ty:]] = OpTypeInt 32 0
|
||||
; CHECK-DAG: %[[#pint_ty:]] = OpTypePointer Function %[[#int_ty]]
|
||||
; CHECK-DAG: %[[#bool_ty:]] = OpTypeBool
|
||||
; CHECK-DAG: %[[#int_0:]] = OpConstant %[[#int_ty]] 0
|
||||
; CHECK-DAG: %[[#int_10:]] = OpConstant %[[#int_ty]] 10
|
||||
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK: %[[#idx:]] = OpVariable %[[#pint_ty]] Function
|
||||
; CHECK: %[[#idx]] = OpVariable %[[#]] Function
|
||||
; CHECK: OpStore %[[#idx]] %[[#int_0]] Aligned 4
|
||||
; CHECK: OpBranch %[[#while_cond:]]
|
||||
entry:
|
||||
@@ -48,17 +47,18 @@ while.body:
|
||||
%cmp1 = icmp eq i32 %4, 0
|
||||
br i1 %cmp1, label %if.then, label %if.end
|
||||
|
||||
; CHECK: %[[#if_end]] = OpLabel
|
||||
; CHECK: OpBranch %[[#while_cond]]
|
||||
|
||||
; CHECK: %[[#if_then]] = OpLabel
|
||||
; CHECK-NEXT: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#builtin]] Aligned 1
|
||||
; CHECK-NEXT: OpStore %[[#idx]] %[[#tmp]] Aligned 4
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#builtin]] Aligned 1
|
||||
; CHECK: OpStore %[[#idx]] %[[#tmp]] Aligned 4
|
||||
; CHECK: OpBranch %[[#new_end]]
|
||||
if.then:
|
||||
%5 = call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %1) ]
|
||||
store i32 %5, ptr %idx, align 4
|
||||
br label %while.end
|
||||
|
||||
; CHECK: %[[#if_end]] = OpLabel
|
||||
; CHECK: OpBranch %[[#while_cond]]
|
||||
if.end:
|
||||
br label %while.cond
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s --match-full-lines
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan-compute"
|
||||
|
||||
define internal spir_func void @main() #0 {
|
||||
|
||||
; CHECK: OpDecorate %[[#builtin:]] BuiltIn SubgroupLocalInvocationId
|
||||
; CHECK-DAG: OpName %[[#idx:]] "idx"
|
||||
; CHECK-DAG: OpName %[[#reg_0:]] "reg"
|
||||
; CHECK-DAG: OpDecorate %[[#builtin:]] BuiltIn SubgroupLocalInvocationId
|
||||
; CHECK-DAG: %[[#int_ty:]] = OpTypeInt 32 0
|
||||
; CHECK-DAG: %[[#pint_ty:]] = OpTypePointer Function %[[#int_ty]]
|
||||
; CHECK-DAG: %[[#bool_ty:]] = OpTypeBool
|
||||
; CHECK-DAG: %[[#int_0:]] = OpConstant %[[#int_ty]] 0
|
||||
; CHECK-DAG: %[[#int_1:]] = OpConstant %[[#int_ty]] 1
|
||||
@@ -16,7 +17,7 @@ define internal spir_func void @main() #0 {
|
||||
; CHECK-DAG: %[[#int_10:]] = OpConstant %[[#int_ty]] 10
|
||||
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK: %[[#idx:]] = OpVariable %[[#pint_ty]] Function
|
||||
; CHECK: %[[#idx]] = OpVariable %[[#]] Function
|
||||
; CHECK: OpStore %[[#idx]] %[[#int_0]] Aligned 4
|
||||
; CHECK: OpBranch %[[#while_cond:]]
|
||||
entry:
|
||||
@@ -26,6 +27,7 @@ entry:
|
||||
br label %while.cond
|
||||
|
||||
; CHECK: %[[#while_cond]] = OpLabel
|
||||
; CHECK: OpStore %[[#reg_0]] %[[#]] Aligned 4
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#idx]] Aligned 4
|
||||
; CHECK: %[[#cmp:]] = OpINotEqual %[[#bool_ty]] %[[#tmp]] %[[#int_10]]
|
||||
; CHECK: OpLoopMerge %[[#new_end:]] %[[#if_end2:]] None
|
||||
@@ -37,10 +39,11 @@ while.cond:
|
||||
br i1 %cmp, label %while.body, label %while.end
|
||||
|
||||
; CHECK: %[[#while_body]] = OpLabel
|
||||
; CHECK-NEXT: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#builtin]] Aligned 1
|
||||
; CHECK-NEXT: OpStore %[[#idx]] %[[#tmp]] Aligned 4
|
||||
; CHECK-NEXT: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#idx]] Aligned 4
|
||||
; CHECK-NEXT: %[[#cmp1:]] = OpIEqual %[[#bool_ty]] %[[#tmp]] %[[#int_0]]
|
||||
; CHECK: OpStore %[[#reg_0]] %[[#]] Aligned 4
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#]] %[[#builtin]] Aligned 1
|
||||
; CHECK: OpStore %[[#idx]] %[[#tmp]] Aligned 4
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#idx]] Aligned 4
|
||||
; CHECK: %[[#cmp1:]] = OpIEqual %[[#bool_ty]] %[[#tmp]] %[[#int_0]]
|
||||
; CHECK: OpBranchConditional %[[#cmp1]] %[[#new_end]] %[[#if_end:]]
|
||||
while.body:
|
||||
%3 = call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %1) ]
|
||||
@@ -50,10 +53,11 @@ while.body:
|
||||
br i1 %cmp1, label %if.then, label %if.end
|
||||
|
||||
; CHECK: %[[#if_end]] = OpLabel
|
||||
; CHECK-NEXT: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#builtin]] Aligned 1
|
||||
; CHECK-NEXT: OpStore %[[#idx]] %[[#tmp]] Aligned 4
|
||||
; CHECK-NEXT: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#idx]] Aligned 4
|
||||
; CHECK-NEXT: %[[#cmp2:]] = OpIEqual %[[#bool_ty]] %[[#tmp]] %[[#int_0]]
|
||||
; CHECK: OpStore %[[#reg_0]] %[[#]] Aligned 4
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#builtin]] Aligned 1
|
||||
; CHECK: OpStore %[[#idx]] %[[#tmp]] Aligned 4
|
||||
; CHECK: %[[#tmp:]] = OpLoad %[[#int_ty]] %[[#idx]] Aligned 4
|
||||
; CHECK: %[[#cmp2:]] = OpIEqual %[[#bool_ty]] %[[#tmp]] %[[#int_0]]
|
||||
; CHECK: OpBranchConditional %[[#cmp2]] %[[#new_end]] %[[#if_end2]]
|
||||
if.end:
|
||||
%5 = call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %1) ]
|
||||
@@ -62,14 +66,15 @@ if.end:
|
||||
%cmp2 = icmp eq i32 %6, 0
|
||||
br i1 %cmp2, label %if.then2, label %if.end2
|
||||
|
||||
; CHECK: %[[#if_end2]] = OpLabel
|
||||
; CHECK: OpBranch %[[#while_cond]]
|
||||
|
||||
; TODO: this OpSwitch is useless. Improve the "remove useless branches" step of the structurizer to
|
||||
; cleanup those.
|
||||
; CHECK: %[[#new_end]] = OpLabel
|
||||
; CHECK: %[[#route:]] = OpPhi %[[#int_ty]] %[[#int_0]] %[[#while_cond]] %[[#int_1]] %[[#while_body]] %[[#int_2]] %[[#if_end]]
|
||||
; CHECK: %[[#route:]] = OpLoad %[[#]] %[[#reg_0]] Aligned 4
|
||||
; CHECK: OpSwitch %[[#route]] %[[#while_end:]] 1 %[[#while_end:]] 2 %[[#while_end:]]
|
||||
|
||||
; CHECK: %[[#if_end2]] = OpLabel
|
||||
; CHECK: OpBranch %[[#while_cond]]
|
||||
if.end2:
|
||||
br label %while.cond
|
||||
|
||||
|
||||
45
llvm/test/CodeGen/SPIRV/structurizer/phi-exit.ll
Normal file
45
llvm/test/CodeGen/SPIRV/structurizer/phi-exit.ll
Normal file
@@ -0,0 +1,45 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s --match-full-lines
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
|
||||
define internal spir_func void @main() #1 {
|
||||
; CHECK: %[[#entry:]] = OpLabel
|
||||
; CHECK: OpBranch %[[#do_body:]]
|
||||
entry:
|
||||
%0 = call token @llvm.experimental.convergence.entry()
|
||||
%a = alloca i32, align 4
|
||||
br label %loop_body
|
||||
|
||||
loop_body:
|
||||
br i1 true, label %left, label %right
|
||||
|
||||
left:
|
||||
br i1 true, label %loop_exit, label %loop_continue
|
||||
|
||||
right:
|
||||
br i1 true, label %loop_exit, label %loop_continue
|
||||
|
||||
loop_continue:
|
||||
br label %loop_body
|
||||
|
||||
loop_exit:
|
||||
%r = phi i32 [ 0, %left ], [ 1, %right ]
|
||||
store i32 %r, ptr %a, align 4
|
||||
ret void
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare token @llvm.experimental.convergence.entry() #0
|
||||
declare token @llvm.experimental.convergence.loop() #0
|
||||
|
||||
attributes #0 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
|
||||
attributes #1 = { convergent noinline norecurse nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1}
|
||||
|
||||
!0 = !{i32 1, !"wchar_size", i32 4}
|
||||
!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s --match-full-lines
|
||||
; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: OpName %[[#reg_0:]] "reg2"
|
||||
; CHECK-DAG: OpName %[[#reg_1:]] "reg1"
|
||||
|
||||
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
|
||||
target triple = "spirv-unknown-vulkan1.3-compute"
|
||||
|
||||
@@ -37,36 +40,40 @@ while.body:
|
||||
]
|
||||
|
||||
; CHECK: %[[#case_1]] = OpLabel
|
||||
; CHECK: OpStore %[[#reg_0]] %[[#]]
|
||||
; CHECK: OpBranch %[[#switch_end]]
|
||||
sw.bb:
|
||||
store i32 1, ptr %a, align 4
|
||||
br label %while.end
|
||||
|
||||
; CHECK: %[[#case_2]] = OpLabel
|
||||
; CHECK: OpStore %[[#reg_0]] %[[#]]
|
||||
; CHECK: OpBranch %[[#switch_end]]
|
||||
sw.bb1:
|
||||
store i32 3, ptr %a, align 4
|
||||
br label %while.end
|
||||
|
||||
; CHECK: %[[#case_5]] = OpLabel
|
||||
; CHECK: OpStore %[[#reg_0]] %[[#]]
|
||||
; CHECK: OpBranch %[[#switch_end]]
|
||||
sw.bb2:
|
||||
store i32 5, ptr %a, align 4
|
||||
br label %while.end
|
||||
|
||||
; CHECK: %[[#switch_end]] = OpLabel
|
||||
; CHECK: %[[#phi:]] = OpPhi %[[#type:]] %[[#A:]] %[[#while_body]] %[[#B:]] %[[#case_5]] %[[#B:]] %[[#case_2]] %[[#B:]] %[[#case_1]]
|
||||
; CHECK: %[[#tmp:]] = OpIEqual %[[#type:]] %[[#A]] %[[#phi]]
|
||||
; CHECK: %[[#val:]] = OpLoad %[[#]] %[[#reg_0]]
|
||||
; CHECK: %[[#tmp:]] = OpIEqual %[[#type:]] %[[#]] %[[#val]]
|
||||
; CHECK: OpBranchConditional %[[#tmp]] %[[#sw_default:]] %[[#while_end]]
|
||||
|
||||
; CHECK: %[[#sw_default]] = OpLabel
|
||||
; CHECK: OpStore %[[#A:]] %[[#B:]] Aligned 4
|
||||
; CHECK: OpStore %[[#]] %[[#B:]] Aligned 4
|
||||
; CHECK: OpBranch %[[#for_cond:]]
|
||||
sw.default:
|
||||
store i32 0, ptr %i, align 4
|
||||
br label %for.cond
|
||||
|
||||
; CHECK: %[[#for_cond]] = OpLabel
|
||||
; CHECK: OpStore %[[#reg_1]] %[[#]]
|
||||
; CHECK: OpSelectionMerge %[[#for_merge:]] None
|
||||
; CHECK-NEXT: OpBranchConditional %[[#cond:]] %[[#for_merge]] %[[#for_end:]]
|
||||
for.cond:
|
||||
@@ -76,13 +83,14 @@ for.cond:
|
||||
br i1 %cmp, label %for.body, label %for.end
|
||||
|
||||
; CHECK: %[[#for_end]] = OpLabel
|
||||
; CHECK: OpStore %[[#reg_1]] %[[#]]
|
||||
; CHECK: OpBranch %[[#for_merge]]
|
||||
for.end:
|
||||
br label %while.end
|
||||
|
||||
; CHECK: %[[#for_merge]] = OpLabel
|
||||
; CHECK: %[[#phi:]] = OpPhi %[[#type:]] %[[#A:]] %[[#for_cond]] %[[#B:]] %[[#for_end]]
|
||||
; CHECK: %[[#tmp:]] = OpIEqual %[[#type:]] %[[#A]] %[[#phi]]
|
||||
; CHECK: %[[#val:]] = OpLoad %[[#]] %[[#reg_1]]
|
||||
; CHECK: %[[#tmp:]] = OpIEqual %[[#type:]] %[[#]] %[[#val]]
|
||||
; CHECK: OpBranchConditional %[[#tmp]] %[[#for_body:]] %[[#while_end]]
|
||||
|
||||
; CHECK: %[[#for_body]] = OpLabel
|
||||
|
||||
Reference in New Issue
Block a user