Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 117 additions & 3 deletions llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,95 @@ namespace llvm::SPIRV {
} // namespace llvm::SPIRV

namespace {
// This class keeps track of which functions reference which global variables.
class GlobalVariableUsers {
template <typename T1, typename T2>
using OneToManyMapTy = DenseMap<T1, SmallPtrSet<T2, 4>>;

OneToManyMapTy<const GlobalVariable *, const Function *> GlobalIsUsedByFun;

void collectGlobalUsers(
const GlobalVariable *GV,
OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
&GlobalIsUsedByGlobal) {
SmallVector<const Value *> Stack = {GV->user_begin(), GV->user_end()};
while (!Stack.empty()) {
const Value *V = Stack.pop_back_val();

if (const Instruction *I = dyn_cast<Instruction>(V)) {
GlobalIsUsedByFun[GV].insert(I->getFunction());
continue;
}

if (const GlobalVariable *UserGV = dyn_cast<GlobalVariable>(V)) {
GlobalIsUsedByGlobal[GV].insert(UserGV);
continue;
}

if (const Constant *C = dyn_cast<Constant>(V))
Stack.append(C->user_begin(), C->user_end());
}
}

bool propagateGlobalToGlobalUsers(
OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
&GlobalIsUsedByGlobal) {
SmallVector<const GlobalVariable *> OldUsersGlobals;
bool Changed = false;
for (auto &[GV, UserGlobals] : GlobalIsUsedByGlobal) {
OldUsersGlobals.assign(UserGlobals.begin(), UserGlobals.end());
for (const GlobalVariable *UserGV : OldUsersGlobals) {
auto It = GlobalIsUsedByGlobal.find(UserGV);
if (It == GlobalIsUsedByGlobal.end())
continue;
Changed |= set_union(UserGlobals, It->second);
}
}
return Changed;
}

void propagateGlobalToFunctionReferences(
OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
&GlobalIsUsedByGlobal) {
for (auto &[GV, UserGlobals] : GlobalIsUsedByGlobal) {
auto &UserFunctions = GlobalIsUsedByFun[GV];
for (const GlobalVariable *UserGV : UserGlobals) {
auto It = GlobalIsUsedByFun.find(UserGV);
if (It == GlobalIsUsedByFun.end())
continue;
set_union(UserFunctions, It->second);
}
}
}

public:
void init(Module &M) {
// Collect which global variables are referenced by which global variables
// and which functions reference each global variables.
OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
GlobalIsUsedByGlobal;
GlobalIsUsedByFun.clear();
for (GlobalVariable &GV : M.globals())
collectGlobalUsers(&GV, GlobalIsUsedByGlobal);

// Compute indirect references by iterating until a fixed point is reached.
while (propagateGlobalToGlobalUsers(GlobalIsUsedByGlobal))
(void)0;

propagateGlobalToFunctionReferences(GlobalIsUsedByGlobal);
}

using FunctionSetType = typename decltype(GlobalIsUsedByFun)::mapped_type;
const FunctionSetType &
getTransitiveUserFunctions(const GlobalVariable &GV) const {
auto It = GlobalIsUsedByFun.find(&GV);
if (It != GlobalIsUsedByFun.end())
return It->second;

static const FunctionSetType Empty{};
return Empty;
}
};

static bool isaGEP(const Value *V) {
return isa<StructuredGEPInst>(V) || isa<GetElementPtrInst>(V);
Expand All @@ -78,6 +167,7 @@ class SPIRVEmitIntrinsics
DenseMap<Instruction *, Constant *> AggrConsts;
DenseMap<Instruction *, Type *> AggrConstTypes;
DenseSet<Instruction *> AggrStores;
GlobalVariableUsers GVUsers;
std::unordered_set<Value *> Named;

// map of function declarations to <pointer arg index => element type>
Expand Down Expand Up @@ -208,7 +298,6 @@ class SPIRVEmitIntrinsics
bool postprocessTypes(Module &M);
bool processFunctionPointers(Module &M);
void parseFunDeclarations(Module &M);

void useRoundingMode(ConstrainedFPIntrinsic *FPI, IRBuilder<> &B);

void emitUnstructuredLoopControls(Function &F, IRBuilder<> &B);
Expand Down Expand Up @@ -2150,13 +2239,37 @@ Instruction *SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) {
return &I;
}

void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV,
IRBuilder<> &B) {
static bool
shouldEmitIntrinsicsForGlobalValue(const GlobalVariableUsers &GVUsers,
const GlobalVariable &GV,
const Function *F) {
// Skip special artificial variables.
static const StringSet<> ArtificialGlobals{"llvm.global.annotations",
"llvm.compiler.used", "llvm.used"};

if (ArtificialGlobals.contains(GV.getName()))
return false;

auto &UserFunctions = GVUsers.getTransitiveUserFunctions(GV);
if (UserFunctions.contains(F))
return true;

// Do not emit the intrinsics in this function, it's going to be emitted on
// the functions that reference it.
if (!UserFunctions.empty())
return false;

// Emit definitions for globals that are not referenced by any function on the
// first function definition.
const Module &M = *F->getParent();
const Function &FirstDefinition = *M.getFunctionDefs().begin();
return F == &FirstDefinition;
}

void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV,
IRBuilder<> &B) {

if (!shouldEmitIntrinsicsForGlobalValue(GVUsers, GV, CurrF))
return;

Constant *Init = nullptr;
Expand Down Expand Up @@ -3173,6 +3286,7 @@ bool SPIRVEmitIntrinsics::runOnModule(Module &M) {

parseFunDeclarations(M);
insertConstantsForFPFastMathDefault(M);
GVUsers.init(M);

TodoType.clear();
for (auto &F : M)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,54 @@
; CHECK: OpEntryPoint Kernel %[[#KERNEL_FLOAT_V:]] "k_float_controls_float_v"
; CHECK: OpEntryPoint Kernel %[[#KERNEL_ALL_V:]] "k_float_controls_all_v"

; CHECK-DAG: %[[#INT32_TYPE:]] = OpTypeInt 32 0
; CHECK-DAG: %[[#HALF_TYPE:]] = OpTypeFloat 16
; CHECK-DAG: %[[#FLOAT_TYPE:]] = OpTypeFloat 32
; CHECK-DAG: %[[#DOUBLE_TYPE:]] = OpTypeFloat 64
; CHECK-DAG: %[[#CONST0:]] = OpConstantNull %[[#INT32_TYPE]]
; CHECK-DAG: %[[#CONST131079:]] = OpConstant %[[#INT32_TYPE]] 131079

; CHECK-DAG: %[[#HALF_V_TYPE:]] = OpTypeVector %[[#HALF_TYPE]]
; CHECK-DAG: %[[#FLOAT_V_TYPE:]] = OpTypeVector %[[#FLOAT_TYPE]]
; CHECK-DAG: %[[#DOUBLE_V_TYPE:]] = OpTypeVector %[[#DOUBLE_TYPE]]

; We expect 130179 for float type.
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_FLOAT]] FPFastMathDefault %[[#FLOAT_TYPE:]] %[[#CONST131079:]]
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault %[[#FLOAT_TYPE:]] %[[#CONST131079]]
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_FLOAT]] FPFastMathDefault %[[#FLOAT_TYPE]] %[[#CONST131079]]
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault %[[#FLOAT_TYPE]] %[[#CONST131079]]
; We expect 0 for the rest of types because it's SignedZeroInfNanPreserve.
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault %[[#HALF_TYPE:]] %[[#CONST0:]]
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault %[[#DOUBLE_TYPE:]] %[[#CONST0]]
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault %[[#HALF_TYPE]] %[[#CONST0]]
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL]] FPFastMathDefault %[[#DOUBLE_TYPE]] %[[#CONST0]]

; We expect 130179 for float type.
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_FLOAT_V]] FPFastMathDefault %[[#FLOAT_TYPE:]] %[[#CONST131079]]
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault %[[#FLOAT_TYPE:]] %[[#CONST131079]]
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_FLOAT_V]] FPFastMathDefault %[[#FLOAT_TYPE]] %[[#CONST131079]]
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault %[[#FLOAT_TYPE]] %[[#CONST131079]]
; We expect 0 for the rest of types because it's SignedZeroInfNanPreserve.
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault %[[#DOUBLE_TYPE:]] %[[#CONST0]]
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault %[[#HALF_TYPE:]] %[[#CONST0]]

; CHECK-DAG: OpDecorate %[[#addRes:]] FPFastMathMode NotNaN|NotInf|NSZ|AllowReassoc
; CHECK-DAG: OpDecorate %[[#addResH:]] FPFastMathMode None
; CHECK-DAG: OpDecorate %[[#addResF:]] FPFastMathMode NotNaN|NotInf|NSZ|AllowReassoc
; CHECK-DAG: OpDecorate %[[#addResD:]] FPFastMathMode None
; CHECK-DAG: OpDecorate %[[#addRes_V:]] FPFastMathMode NotNaN|NotInf|NSZ|AllowReassoc
; CHECK-DAG: OpDecorate %[[#addResH_V:]] FPFastMathMode None
; CHECK-DAG: OpDecorate %[[#addResF_V:]] FPFastMathMode NotNaN|NotInf|NSZ|AllowReassoc
; CHECK-DAG: OpDecorate %[[#addResD_V:]] FPFastMathMode None
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault %[[#DOUBLE_TYPE]] %[[#CONST0]]
; CHECK-DAG: OpExecutionModeId %[[#KERNEL_ALL_V]] FPFastMathDefault %[[#HALF_TYPE]] %[[#CONST0]]

; CHECK-DAG: %[[#INT32_TYPE:]] = OpTypeInt 32 0
; CHECK-DAG: %[[#HALF_TYPE]] = OpTypeFloat 16
; CHECK-DAG: %[[#FLOAT_TYPE]] = OpTypeFloat 32
; CHECK-DAG: %[[#DOUBLE_TYPE]] = OpTypeFloat 64
; CHECK-DAG: %[[#CONST0]] = OpConstantNull %[[#INT32_TYPE]]
; CHECK-DAG: %[[#CONST131079]] = OpConstant %[[#INT32_TYPE]] 131079
; CHECK-DAG: OpName %[[#G_addResH:]] "G_addResH"
; CHECK-DAG: OpName %[[#G_addResF:]] "G_addResF"
; CHECK-DAG: OpName %[[#G_addResD:]] "G_addResD"
; CHECK-DAG: OpName %[[#G_addResV:]] "G_addResV"
; CHECK-DAG: OpName %[[#G_addResH_V:]] "G_addResH_V"
; CHECK-DAG: OpName %[[#G_addResF_V:]] "G_addResF_V"
; CHECK-DAG: OpName %[[#G_addResD_V:]] "G_addResD_V"

; CHECK-DAG: %[[#HALF_V_TYPE:]] = OpTypeVector %[[#HALF_TYPE]]
; CHECK-DAG: %[[#FLOAT_V_TYPE:]] = OpTypeVector %[[#FLOAT_TYPE]]
; CHECK-DAG: %[[#DOUBLE_V_TYPE:]] = OpTypeVector %[[#DOUBLE_TYPE]]
; CHECK-DAG: OpStore %[[#G_addResH]] %[[#addResH:]]
; CHECK-DAG: OpStore %[[#G_addResF]] %[[#addResF:]]
; CHECK-DAG: OpStore %[[#G_addResD]] %[[#addResD:]]
; CHECK-DAG: OpStore %[[#G_addResV]] %[[#addResV:]]
; CHECK-DAG: OpStore %[[#G_addResH_V]] %[[#addResH_V:]]
; CHECK-DAG: OpStore %[[#G_addResF_V]] %[[#addResF_V:]]
; CHECK-DAG: OpStore %[[#G_addResD_V]] %[[#addResD_V:]]

; CHECK-DAG: OpDecorate %[[#addResH]] FPFastMathMode None
; CHECK-DAG: OpDecorate %[[#addResF]] FPFastMathMode NotNaN|NotInf|NSZ|AllowReassoc
; CHECK-DAG: OpDecorate %[[#addResD]] FPFastMathMode None
; CHECK-DAG: OpDecorate %[[#addResV]] FPFastMathMode NotNaN|NotInf|NSZ|AllowReassoc
; CHECK-DAG: OpDecorate %[[#addResH_V]] FPFastMathMode None
; CHECK-DAG: OpDecorate %[[#addResF_V]] FPFastMathMode NotNaN|NotInf|NSZ|AllowReassoc
; CHECK-DAG: OpDecorate %[[#addResD_V]] FPFastMathMode None

@G_addRes = global float 0.0
@G_addResH = global half 0.0
Expand All @@ -53,7 +68,8 @@

define dso_local dllexport spir_kernel void @k_float_controls_float(float %f) {
entry:
; CHECK-DAG: %[[#addRes]] = OpFAdd %[[#FLOAT_TYPE]]
; CHECK-DAG: %[[#addRes:]] = OpFAdd %[[#FLOAT_TYPE]]
; CHECK-DAG: OpDecorate %[[#addRes]] FPFastMathMode NotNaN|NotInf|NSZ|AllowReassoc
%addRes = fadd float %f, %f
store volatile float %addRes, ptr @G_addRes
ret void
Expand All @@ -75,7 +91,7 @@ entry:

define dso_local dllexport spir_kernel void @k_float_controls_float_v(<2 x float> %f) {
entry:
; CHECK-DAG: %[[#addRes_V]] = OpFAdd %[[#FLOAT_V_TYPE]]
; CHECK-DAG: %[[#addResV]] = OpFAdd %[[#FLOAT_V_TYPE]]
%addRes = fadd <2 x float> %f, %f
store volatile <2 x float> %addRes, ptr @G_addResV
ret void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@
; CHECK-DAG: Capability AtomicFloat16VectorNV
; CHECK: Extension "SPV_NV_shader_atomic_fp16_vector"
; CHECK-DAG: %[[TyF16:[0-9]+]] = OpTypeFloat 16
; CHECK: %[[TyF16Vec2:[0-9]+]] = OpTypeVector %[[TyF16]] 2
; CHECK: %[[TyF16Vec4:[0-9]+]] = OpTypeVector %[[TyF16]] 4
; CHECK: %[[TyF16Vec4Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec4]]
; CHECK: %[[TyF16Vec2Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec2]]
; CHECK: %[[TyInt32:[0-9]+]] = OpTypeInt 32 0
; CHECK: %[[ConstF16:[0-9]+]] = OpConstant %[[TyF16]] 20800{{$}}
; CHECK: %[[Const0F16Vec2:[0-9]+]] = OpConstantNull %[[TyF16Vec2]]
; CHECK: %[[f:[0-9]+]] = OpVariable %[[TyF16Vec2Ptr]] CrossWorkgroup %[[Const0F16Vec2]]
; CHECK: %[[Const0F16Vec4:[0-9]+]] = OpConstantNull %[[TyF16Vec4]]
; CHECK: %[[g:[0-9]+]] = OpVariable %[[TyF16Vec4Ptr]] CrossWorkgroup %[[Const0F16Vec4]]
; CHECK: %[[ConstF16Vec2:[0-9]+]] = OpConstantComposite %[[TyF16Vec2]] %[[ConstF16]] %[[ConstF16]]
; CHECK: %[[ScopeAllSvmDevices:[0-9]+]] = OpConstantNull %[[TyInt32]]
; CHECK: %[[MemSeqCst:[0-9]+]] = OpConstant %[[TyInt32]] 16{{$}}
; CHECK: %[[ConstF16Vec4:[0-9]+]] = OpConstantComposite %[[TyF16Vec4]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]]
; CHECK-DAG: %[[TyF16Vec2:[0-9]+]] = OpTypeVector %[[TyF16]] 2
; CHECK-DAG: %[[TyF16Vec4:[0-9]+]] = OpTypeVector %[[TyF16]] 4
; CHECK-DAG: %[[TyF16Vec4Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec4]]
; CHECK-DAG: %[[TyF16Vec2Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec2]]
; CHECK-DAG: %[[TyInt32:[0-9]+]] = OpTypeInt 32 0
; CHECK-DAG: %[[ConstF16:[0-9]+]] = OpConstant %[[TyF16]] 20800{{$}}
; CHECK-DAG: %[[Const0F16Vec2:[0-9]+]] = OpConstantNull %[[TyF16Vec2]]
; CHECK-DAG: %[[f:[0-9]+]] = OpVariable %[[TyF16Vec2Ptr]] CrossWorkgroup %[[Const0F16Vec2]]
; CHECK-DAG: %[[Const0F16Vec4:[0-9]+]] = OpConstantNull %[[TyF16Vec4]]
; CHECK-DAG: %[[g:[0-9]+]] = OpVariable %[[TyF16Vec4Ptr]] CrossWorkgroup %[[Const0F16Vec4]]
; CHECK-DAG: %[[ConstF16Vec2:[0-9]+]] = OpConstantComposite %[[TyF16Vec2]] %[[ConstF16]] %[[ConstF16]]
; CHECK-DAG: %[[ScopeAllSvmDevices:[0-9]+]] = OpConstantNull %[[TyInt32]]
; CHECK-DAG: %[[MemSeqCst:[0-9]+]] = OpConstant %[[TyInt32]] 16{{$}}
; CHECK-DAG: %[[ConstF16Vec4:[0-9]+]] = OpConstantComposite %[[TyF16Vec4]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]]

@f = common dso_local local_unnamed_addr addrspace(1) global <2 x half> <half 0.000000e+00, half 0.000000e+00>
@g = common dso_local local_unnamed_addr addrspace(1) global <4 x half> <half 0.000000e+00, half 0.000000e+00, half 0.000000e+00, half 0.000000e+00>
Expand All @@ -44,4 +44,4 @@ entry:
%addval = atomicrmw fadd ptr addrspace(1) @g, <4 x half> <half 42.000000e+00, half 42.000000e+00, half 42.000000e+00, half 42.000000e+00> seq_cst
%subval = atomicrmw fsub ptr addrspace(1) @g, <4 x half> <half 42.000000e+00, half 42.000000e+00, half 42.000000e+00, half 42.000000e+00> seq_cst
ret void
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@
; CHECK-DAG: Capability AtomicFloat16VectorNV
; CHECK: Extension "SPV_NV_shader_atomic_fp16_vector"
; CHECK-DAG: %[[TyF16:[0-9]+]] = OpTypeFloat 16
; CHECK: %[[TyF16Vec2:[0-9]+]] = OpTypeVector %[[TyF16]] 2
; CHECK: %[[TyF16Vec4:[0-9]+]] = OpTypeVector %[[TyF16]] 4
; CHECK: %[[TyF16Vec4Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec4]]
; CHECK: %[[TyF16Vec2Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec2]]
; CHECK: %[[TyInt32:[0-9]+]] = OpTypeInt 32 0
; CHECK: %[[ConstF16:[0-9]+]] = OpConstant %[[TyF16]] 20800{{$}}
; CHECK: %[[Const0F16Vec2:[0-9]+]] = OpConstantNull %[[TyF16Vec2]]
; CHECK: %[[f:[0-9]+]] = OpVariable %[[TyF16Vec2Ptr]] CrossWorkgroup %[[Const0F16Vec2]]
; CHECK: %[[Const0F16Vec4:[0-9]+]] = OpConstantNull %[[TyF16Vec4]]
; CHECK: %[[g:[0-9]+]] = OpVariable %[[TyF16Vec4Ptr]] CrossWorkgroup %[[Const0F16Vec4]]
; CHECK: %[[ConstF16Vec2:[0-9]+]] = OpConstantComposite %[[TyF16Vec2]] %[[ConstF16]] %[[ConstF16]]
; CHECK: %[[ScopeAllSvmDevices:[0-9]+]] = OpConstantNull %[[TyInt32]]
; CHECK: %[[MemSeqCst:[0-9]+]] = OpConstant %[[TyInt32]] 16{{$}}
; CHECK: %[[ConstF16Vec4:[0-9]+]] = OpConstantComposite %[[TyF16Vec4]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]]
; CHECK-DAG: %[[TyF16Vec2:[0-9]+]] = OpTypeVector %[[TyF16]] 2
; CHECK-DAG: %[[TyF16Vec4:[0-9]+]] = OpTypeVector %[[TyF16]] 4
; CHECK-DAG: %[[TyF16Vec4Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec4]]
; CHECK-DAG: %[[TyF16Vec2Ptr:[0-9]+]] = OpTypePointer {{[a-zA-Z]+}} %[[TyF16Vec2]]
; CHECK-DAG: %[[TyInt32:[0-9]+]] = OpTypeInt 32 0
; CHECK-DAG: %[[ConstF16:[0-9]+]] = OpConstant %[[TyF16]] 20800{{$}}
; CHECK-DAG: %[[Const0F16Vec2:[0-9]+]] = OpConstantNull %[[TyF16Vec2]]
; CHECK-DAG: %[[f:[0-9]+]] = OpVariable %[[TyF16Vec2Ptr]] CrossWorkgroup %[[Const0F16Vec2]]
; CHECK-DAG: %[[Const0F16Vec4:[0-9]+]] = OpConstantNull %[[TyF16Vec4]]
; CHECK-DAG: %[[g:[0-9]+]] = OpVariable %[[TyF16Vec4Ptr]] CrossWorkgroup %[[Const0F16Vec4]]
; CHECK-DAG: %[[ConstF16Vec2:[0-9]+]] = OpConstantComposite %[[TyF16Vec2]] %[[ConstF16]] %[[ConstF16]]
; CHECK-DAG: %[[ScopeAllSvmDevices:[0-9]+]] = OpConstantNull %[[TyInt32]]
; CHECK-DAG: %[[MemSeqCst:[0-9]+]] = OpConstant %[[TyInt32]] 16{{$}}
; CHECK-DAG: %[[ConstF16Vec4:[0-9]+]] = OpConstantComposite %[[TyF16Vec4]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]] %[[ConstF16]]

@f = common dso_local local_unnamed_addr addrspace(1) global <2 x half> <half 0.000000e+00, half 0.000000e+00>
@g = common dso_local local_unnamed_addr addrspace(1) global <4 x half> <half 0.000000e+00, half 0.000000e+00, half 0.000000e+00, half 0.000000e+00>
Expand All @@ -42,4 +42,4 @@ entry:
%minval = atomicrmw fmin ptr addrspace(1) @g, <4 x half> <half 42.000000e+00, half 42.000000e+00, half 42.000000e+00, half 42.000000e+00> seq_cst
%maxval = atomicrmw fmax ptr addrspace(1) @g, <4 x half> <half 42.000000e+00, half 42.000000e+00, half 42.000000e+00, half 42.000000e+00> seq_cst
ret void
}
}
Loading