diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index 736be8ca3212b..ea0074d22a441 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -28,6 +28,7 @@ let TargetPrefix = "spv" in { def int_spv_insertelt : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_any_ty, llvm_anyint_ty]>; def int_spv_const_composite : Intrinsic<[llvm_i32_ty], [llvm_vararg_ty]>; def int_spv_bitcast : Intrinsic<[llvm_any_ty], [llvm_any_ty]>; + def int_spv_ptrcast : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg>]>; def int_spv_switch : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>; def int_spv_cmpxchg : Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_vararg_ty]>; def int_spv_unreachable : Intrinsic<[], []>; diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp index 629db8e2eb4d0..0a8b5499a1fc2 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp @@ -211,8 +211,8 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx, MDString *MDKernelArgType = getKernelArgAttribute(F, ArgIdx, "kernel_arg_type"); - if (!MDKernelArgType || (MDKernelArgType->getString().ends_with("*") && - MDKernelArgType->getString().ends_with("_t"))) + if (!MDKernelArgType || (!MDKernelArgType->getString().ends_with("*") && + !MDKernelArgType->getString().ends_with("_t"))) return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual); if (MDKernelArgType->getString().ends_with("*")) @@ -438,7 +438,8 @@ bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, assert(Arg.Regs.size() == 1 && "Call arg has multiple VRegs"); ArgVRegs.push_back(Arg.Regs[0]); SPIRVType *SPIRVTy = GR->getOrCreateSPIRVType(Arg.Ty, MIRBuilder); - GR->assignSPIRVTypeToVReg(SPIRVTy, Arg.Regs[0], MIRBuilder.getMF()); + if (!GR->getSPIRVTypeForVReg(Arg.Regs[0])) + GR->assignSPIRVTypeToVReg(SPIRVTy, Arg.Regs[0], MIRBuilder.getMF()); } if (auto Res = SPIRV::lowerBuiltin( DemangledName, SPIRV::InstructionSet::OpenCL_std, MIRBuilder, diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index ec62a819b00ee..3feb661638a62 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -74,6 +74,10 @@ class SPIRVEmitIntrinsics void processInstrAfterVisit(Instruction *I); void insertAssignPtrTypeIntrs(Instruction *I); void insertAssignTypeIntrs(Instruction *I); + + DenseSet PtrCastInstrs; + void insertPtrCastInstr(Instruction *I); + void processGlobalValue(GlobalVariable &GV); public: @@ -255,7 +259,19 @@ Instruction *SPIRVEmitIntrinsics::visitGetElementPtrInst(GetElementPtrInst &I) { } Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) { - SmallVector Types = {I.getType(), I.getOperand(0)->getType()}; + Value *Source = I.getOperand(0); + + // SPIR-V, contrary to LLVM 17+ IR, supports bitcasts between pointers of + // varying element types. In case of IR coming from older versions of LLVM + // such bitcasts do not provide sufficient information, should be just skipped + // here, and handled in insertPtrCastInstr. + if (I.getType()->isPointerTy()) { + I.replaceAllUsesWith(Source); + I.eraseFromParent(); + return &I; + } + + SmallVector Types = {I.getType(), Source->getType()}; SmallVector Args(I.op_begin(), I.op_end()); auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_bitcast, {Types}, {Args}); std::string InstName = I.hasName() ? I.getName().str() : ""; @@ -265,6 +281,85 @@ Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) { return NewI; } +void SPIRVEmitIntrinsics::insertPtrCastInstr(Instruction *I) { + Value *Pointer; + Type *ExpectedElementType; + unsigned OperandToReplace; + if (StoreInst *SI = dyn_cast(I)) { + Pointer = SI->getPointerOperand(); + ExpectedElementType = SI->getValueOperand()->getType(); + OperandToReplace = 1; + } else if (LoadInst *LI = dyn_cast(I)) { + Pointer = LI->getPointerOperand(); + ExpectedElementType = LI->getType(); + OperandToReplace = 0; + } else if (GetElementPtrInst *GEPI = dyn_cast(I)) { + Pointer = GEPI->getPointerOperand(); + ExpectedElementType = GEPI->getSourceElementType(); + OperandToReplace = 0; + } else { + return; + } + + // If Pointer is the result of nop BitCastInst (ptr -> ptr), use the source + // pointer instead. The BitCastInst should be later removed when visited. + if (BitCastInst *BC = dyn_cast(Pointer)) + Pointer = BC->getOperand(0); + + // Do not emit spv_ptrcast if Pointer is a GlobalValue of expected type. + GlobalValue *GV = dyn_cast(Pointer); + if (GV && GV->getValueType() == ExpectedElementType) + return; + + setInsertPointSkippingPhis(*IRB, I); + Constant *ExpectedElementTypeConst = + Constant::getNullValue(ExpectedElementType); + ConstantAsMetadata *CM = + ValueAsMetadata::getConstant(ExpectedElementTypeConst); + MDTuple *TyMD = MDNode::get(F->getContext(), CM); + MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD); + unsigned AddressSpace = Pointer->getType()->getPointerAddressSpace(); + bool FirstPtrCastOrAssignPtrType = true; + + // Do not emit new spv_ptrcast if equivalent one already exists or when + // spv_assign_ptr_type already targets this pointer with the same element + // type. + for (auto User : Pointer->users()) { + if (auto *II = dyn_cast(User)) { + if ((II->getIntrinsicID() != Intrinsic::spv_assign_ptr_type && + II->getIntrinsicID() != Intrinsic::spv_ptrcast) || + II->getOperand(0) != Pointer) + continue; + + FirstPtrCastOrAssignPtrType = false; + if (II->getOperand(1) == VMD && + dyn_cast(II->getOperand(2))->getSExtValue() == + AddressSpace) + return; + } + } + + // Do not emit spv_ptrcast if it would cast to the default pointer element + // type (i8) of the same address space. + if (ExpectedElementType->isIntegerTy(8)) + return; + + // If this would be the first spv_ptrcast and there is no spv_assign_ptr_type + // for this pointer before, do not emit spv_ptrcast but emit + // spv_assign_ptr_type instead. + if (FirstPtrCastOrAssignPtrType && isa(Pointer)) { + buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {Pointer->getType()}, + ExpectedElementTypeConst, Pointer, + {IRB->getInt32(AddressSpace)}); + } else { + SmallVector Types = {Pointer->getType(), Pointer->getType()}; + SmallVector Args = {Pointer, VMD, IRB->getInt32(AddressSpace)}; + auto *PtrCastI = + IRB->CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args); + I->setOperand(OperandToReplace, PtrCastI); + } +} + Instruction *SPIRVEmitIntrinsics::visitInsertElementInst(InsertElementInst &I) { SmallVector Types = {I.getType(), I.getOperand(0)->getType(), I.getOperand(1)->getType(), @@ -522,6 +617,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) { for (auto &I : Worklist) { insertAssignPtrTypeIntrs(I); insertAssignTypeIntrs(I); + insertPtrCastInstr(I); } for (auto *I : Worklist) { @@ -529,7 +625,8 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) { if (!I->getType()->isVoidTy() || isa(I)) IRB->SetInsertPoint(I->getNextNode()); I = visit(*I); - processInstrAfterVisit(I); + if (I->getParent()) + processInstrAfterVisit(I); } return true; } diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp index f4076be2a7b77..c88745f637c5c 100644 --- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp @@ -125,12 +125,32 @@ static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR, SmallVector ToErase; for (MachineBasicBlock &MBB : MF) { for (MachineInstr &MI : MBB) { - if (!isSpvIntrinsic(MI, Intrinsic::spv_bitcast)) - continue; - assert(MI.getOperand(2).isReg()); - MIB.setInsertPt(*MI.getParent(), MI); - MIB.buildBitcast(MI.getOperand(0).getReg(), MI.getOperand(2).getReg()); - ToErase.push_back(&MI); + if (isSpvIntrinsic(MI, Intrinsic::spv_bitcast)) { + assert(MI.getOperand(2).isReg()); + MIB.setInsertPt(*MI.getParent(), MI); + MIB.buildBitcast(MI.getOperand(0).getReg(), MI.getOperand(2).getReg()); + ToErase.push_back(&MI); + } else if (isSpvIntrinsic(MI, Intrinsic::spv_ptrcast)) { + assert(MI.getOperand(2).isReg()); + MIB.setInsertPt(*MI.getParent(), MI); + Register Def = MI.getOperand(0).getReg(); + Register Source = MI.getOperand(2).getReg(); + SPIRVType *BaseTy = GR->getOrCreateSPIRVType( + getMDOperandAsType(MI.getOperand(3).getMetadata(), 0), MIB); + SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType( + BaseTy, MI, *MF.getSubtarget().getInstrInfo(), + addressSpaceToStorageClass(MI.getOperand(4).getImm())); + + // If the bitcast would be redundant, replace all uses with the source + // register. + if (GR->getSPIRVTypeForVReg(Source) == AssignedPtrType) { + MIB.getMRI()->replaceRegWith(Def, Source); + } else { + GR->assignSPIRVTypeToVReg(AssignedPtrType, Def, MF); + MIB.buildBitcast(Def, Source); + } + ToErase.push_back(&MI); + } } } for (MachineInstr *MI : ToErase) diff --git a/llvm/test/CodeGen/SPIRV/AtomicCompareExchange.ll b/llvm/test/CodeGen/SPIRV/AtomicCompareExchange.ll index 8d12414c66a8f..323afec7f35f8 100644 --- a/llvm/test/CodeGen/SPIRV/AtomicCompareExchange.ll +++ b/llvm/test/CodeGen/SPIRV/AtomicCompareExchange.ll @@ -10,47 +10,40 @@ ; CHECK-SPIRV-DAG: %[[#Struct:]] = OpTypeStruct %[[#Int]] %[[#Bool]] ; CHECK-SPIRV-DAG: %[[#UndefStruct:]] = OpUndef %[[#Struct]] -; CHECK-SPIRV: %[[#Pointer:]] = OpFunctionParameter %[[#]] -; CHECK-SPIRV: %[[#Value_ptr:]] = OpFunctionParameter %[[#]] -; CHECK-SPIRV: %[[#Comparator:]] = OpFunctionParameter %[[#]] - -; CHECK-SPIRV: %[[#Value:]] = OpLoad %[[#Int]] %[[#Value_ptr]] -; CHECK-SPIRV: %[[#Res:]] = OpAtomicCompareExchange %[[#Int]] %[[#Pointer]] %[[#MemScope_Device]] -; CHECK-SPIRV-SAME: %[[#MemSemEqual_SeqCst]] %[[#MemSemUnequal_Acquire]] %[[#Value]] %[[#Comparator]] +; CHECK-SPIRV: %[[#Value:]] = OpLoad %[[#Int]] %[[#Value_ptr:]] +; CHECK-SPIRV: %[[#Res:]] = OpAtomicCompareExchange %[[#Int]] %[[#Pointer:]] %[[#MemScope_Device]] +; CHECK-SPIRV-SAME: %[[#MemSemEqual_SeqCst]] %[[#MemSemUnequal_Acquire]] %[[#Value]] %[[#Comparator:]] ; CHECK-SPIRV: %[[#Success:]] = OpIEqual %[[#]] %[[#Res]] %[[#Comparator]] ; CHECK-SPIRV: %[[#Composite_0:]] = OpCompositeInsert %[[#Struct]] %[[#Res]] %[[#UndefStruct]] 0 ; CHECK-SPIRV: %[[#Composite_1:]] = OpCompositeInsert %[[#Struct]] %[[#Success]] %[[#Composite_0]] 1 ; CHECK-SPIRV: %[[#]] = OpCompositeExtract %[[#Bool]] %[[#Composite_1]] 1 -define dso_local spir_func void @test(i32* %ptr, i32* %value_ptr, i32 %comparator) local_unnamed_addr { +define dso_local spir_func void @test(ptr %ptr, ptr %value_ptr, i32 %comparator) local_unnamed_addr { entry: - %0 = load i32, i32* %value_ptr, align 4 - %1 = cmpxchg i32* %ptr, i32 %comparator, i32 %0 seq_cst acquire + %0 = load i32, ptr %value_ptr, align 4 + %1 = cmpxchg ptr %ptr, i32 %comparator, i32 %0 seq_cst acquire %2 = extractvalue { i32, i1 } %1, 1 br i1 %2, label %cmpxchg.continue, label %cmpxchg.store_expected cmpxchg.store_expected: ; preds = %entry %3 = extractvalue { i32, i1 } %1, 0 - store i32 %3, i32* %value_ptr, align 4 + store i32 %3, ptr %value_ptr, align 4 br label %cmpxchg.continue cmpxchg.continue: ; preds = %cmpxchg.store_expected, %entry ret void } -; CHECK-SPIRV: %[[#Ptr:]] = OpFunctionParameter %[[#]] -; CHECK-SPIRV: %[[#Store_ptr:]] = OpFunctionParameter %[[#]] - -; CHECK-SPIRV: %[[#Res_1:]] = OpAtomicCompareExchange %[[#Int]] %[[#Ptr]] %[[#MemScope_Device]] +; CHECK-SPIRV: %[[#Res_1:]] = OpAtomicCompareExchange %[[#Int]] %[[#Ptr:]] %[[#MemScope_Device]] ; CHECK-SPIRV-SAME: %[[#MemSemEqual_SeqCst]] %[[#MemSemUnequal_Acquire]] %[[#Constant_456]] %[[#Constant_128]] ; CHECK-SPIRV: %[[#Success_1:]] = OpIEqual %[[#]] %[[#Res_1]] %[[#Constant_128]] ; CHECK-SPIRV: %[[#Composite:]] = OpCompositeInsert %[[#Struct]] %[[#Res_1]] %[[#UndefStruct]] 0 ; CHECK-SPIRV: %[[#Composite_1:]] = OpCompositeInsert %[[#Struct]] %[[#Success_1]] %[[#Composite]] 1 -; CHECK-SPIRV: OpStore %[[#Store_ptr]] %[[#Composite_1]] +; CHECK-SPIRV: OpStore %[[#Store_ptr:]] %[[#Composite_1]] -define dso_local spir_func void @test2(i32* %ptr, {i32, i1}* %store_ptr) local_unnamed_addr { +define dso_local spir_func void @test2(ptr %ptr, ptr %store_ptr) local_unnamed_addr { entry: - %0 = cmpxchg i32* %ptr, i32 128, i32 456 seq_cst acquire - store { i32, i1 } %0, { i32, i1 }* %store_ptr, align 4 + %0 = cmpxchg ptr %ptr, i32 128, i32 456 seq_cst acquire + store { i32, i1 } %0, ptr %store_ptr, align 4 ret void } diff --git a/llvm/test/CodeGen/SPIRV/function/alloca-load-store.ll b/llvm/test/CodeGen/SPIRV/function/alloca-load-store.ll index 5e76eb11de633..2dddc4542c4f1 100644 --- a/llvm/test/CodeGen/SPIRV/function/alloca-load-store.ll +++ b/llvm/test/CodeGen/SPIRV/function/alloca-load-store.ll @@ -1,17 +1,16 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s -target triple = "spirv32-unknown-unknown" - ; CHECK-DAG: OpName %[[#BAR:]] "bar" ; CHECK-DAG: OpName %[[#FOO:]] "foo" ; CHECK-DAG: OpName %[[#GOO:]] "goo" ; CHECK-DAG: %[[#CHAR:]] = OpTypeInt 8 ; CHECK-DAG: %[[#INT:]] = OpTypeInt 32 -; CHECK-DAG: %[[#STACK_PTR:]] = OpTypePointer Function %[[#INT]] -; CHECK-DAG: %[[#GLOBAL_PTR:]] = OpTypePointer CrossWorkgroup %[[#CHAR]] +; CHECK-DAG: %[[#STACK_PTR_INT:]] = OpTypePointer Function %[[#INT]] +; CHECK-DAG: %[[#GLOBAL_PTR_INT:]] = OpTypePointer CrossWorkgroup %[[#INT]] +; CHECK-DAG: %[[#GLOBAL_PTR_CHAR:]] = OpTypePointer CrossWorkgroup %[[#CHAR]] ; CHECK-DAG: %[[#FN1:]] = OpTypeFunction %[[#INT]] %[[#INT]] -; CHECK-DAG: %[[#FN2:]] = OpTypeFunction %[[#INT]] %[[#INT]] %[[#GLOBAL_PTR]] +; CHECK-DAG: %[[#FN2:]] = OpTypeFunction %[[#INT]] %[[#INT]] %[[#GLOBAL_PTR_CHAR]] define i32 @bar(i32 %a) { %p = alloca i32 @@ -23,7 +22,7 @@ define i32 @bar(i32 %a) { ; CHECK: %[[#BAR]] = OpFunction %[[#INT]] None %[[#FN1]] ; CHECK: %[[#A:]] = OpFunctionParameter %[[#INT]] ; CHECK: OpLabel -; CHECK: %[[#P:]] = OpVariable %[[#STACK_PTR]] Function +; CHECK: %[[#P:]] = OpVariable %[[#STACK_PTR_INT]] Function ; CHECK: OpStore %[[#P]] %[[#A]] ; CHECK: %[[#B:]] = OpLoad %[[#INT]] %[[#P]] ; CHECK: OpReturnValue %[[#B]] @@ -40,7 +39,7 @@ define i32 @foo(i32 %a) { ; CHECK: %[[#FOO]] = OpFunction %[[#INT]] None %[[#FN1]] ; CHECK: %[[#A:]] = OpFunctionParameter %[[#INT]] ; CHECK: OpLabel -; CHECK: %[[#P:]] = OpVariable %[[#STACK_PTR]] Function +; CHECK: %[[#P:]] = OpVariable %[[#STACK_PTR_INT]] Function ; CHECK: OpStore %[[#P]] %[[#A]] Volatile ; CHECK: %[[#B:]] = OpLoad %[[#INT]] %[[#P]] Volatile ; CHECK: OpReturnValue %[[#B]] @@ -48,7 +47,7 @@ define i32 @foo(i32 %a) { ;; Test load and store in global address space. -define i32 @goo(i32 %a, i32 addrspace(1)* %p) { +define i32 @goo(i32 %a, ptr addrspace(1) %p) { store i32 %a, i32 addrspace(1)* %p %b = load i32, i32 addrspace(1)* %p ret i32 %b @@ -56,9 +55,10 @@ define i32 @goo(i32 %a, i32 addrspace(1)* %p) { ; CHECK: %[[#GOO]] = OpFunction %[[#INT]] None %[[#FN2]] ; CHECK: %[[#A:]] = OpFunctionParameter %[[#INT]] -; CHECK: %[[#P:]] = OpFunctionParameter %[[#GLOBAL_PTR]] +; CHECK: %[[#P:]] = OpFunctionParameter %[[#GLOBAL_PTR_CHAR]] ; CHECK: OpLabel -; CHECK: OpStore %[[#P]] %[[#A]] +; CHECK: %[[#C:]] = OpBitcast %[[#GLOBAL_PTR_INT]] %[[#P]] +; CHECK: OpStore %[[#C]] %[[#A]] ; CHECK: %[[#B:]] = OpLoad %[[#INT]] %[[#P]] ; CHECK: OpReturnValue %[[#B]] ; CHECK: OpFunctionEnd diff --git a/llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll b/llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll index 9fa94b8484631..5fa4a7a93ee0b 100644 --- a/llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll +++ b/llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll @@ -9,7 +9,8 @@ ; CHECK: %[[#]] = OpFunction %[[#]] None %[[#]] ; CHECK-NEXT: %[[#PTR:]] = OpFunctionParameter %[[#]] ; CHECK-NEXT: %[[#]] = OpLabel -; CHECK-NEXT: OpStore %[[#PTR]] %[[#UNDEF]] Aligned 4 +; CHECK-NEXT: %[[#BC:]] = OpBitcast %[[#]] %[[#PTR]] +; CHECK-NEXT: OpStore %[[#BC]] %[[#UNDEF]] Aligned 4 ; CHECK-NEXT: OpReturn ; CHECK-NEXT: OpFunctionEnd diff --git a/llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll b/llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll index 6a274732417d4..24dad10382ada 100644 --- a/llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll +++ b/llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll @@ -8,7 +8,8 @@ ; CHECK: %[[#]] = OpFunction %[[#]] None %[[#]] ; CHECK-NEXT: %[[#PTR:]] = OpFunctionParameter %[[#]] ; CHECK-NEXT: %[[#]] = OpLabel -; CHECK-NEXT: OpStore %[[#PTR]] %[[#UNDEF]] Aligned 4 +; CHECK-NEXT: %[[#BC:]] = OpBitcast %[[#]] %[[#PTR]] +; CHECK-NEXT: OpStore %[[#BC]] %[[#UNDEF]] Aligned 4 ; CHECK-NEXT: OpReturn ; CHECK-NEXT: OpFunctionEnd diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memset.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memset.ll index 3d7d9fbf90759..e7a986980f250 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memset.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memset.ll @@ -25,9 +25,7 @@ ; CHECK: %[[#VarNull:]] = OpVariable %[[#]] UniformConstant %[[#ConstNull]] ; CHECK-DAG: %[[#Int8PtrConst:]] = OpTypePointer UniformConstant %[[#Int8]] -; CHECK: %[[#Target:]] = OpBitcast %[[#Int8Ptr]] %[[#]] -; CHECK: %[[#Source:]] = OpBitcast %[[#Int8PtrConst]] %[[#VarNull]] -; CHECK: OpCopyMemorySized %[[#Target]] %[[#Source]] %[[#Const12]] Aligned 4 +; CHECK: OpCopyMemorySized %[[#Target:]] %[[#Source:]] %[[#Const12]] Aligned 4 ; CHECK: %[[#SourceComp:]] = OpBitcast %[[#Int8PtrConst]] %[[#VarComp]] ; CHECK: OpCopyMemorySized %[[#]] %[[#SourceComp]] %[[#Const4]] Aligned 4 diff --git a/llvm/test/CodeGen/SPIRV/opaque_pointers.ll b/llvm/test/CodeGen/SPIRV/opaque_pointers.ll index aaddea1372721..30c9d8dc774e2 100644 --- a/llvm/test/CodeGen/SPIRV/opaque_pointers.ll +++ b/llvm/test/CodeGen/SPIRV/opaque_pointers.ll @@ -1,19 +1,23 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK ; CHECK-DAG: %[[#Int8Ty:]] = OpTypeInt 8 0 -; CHECK-DAG: %[[#PtrTy:]] = OpTypePointer Function %[[#Int8Ty]] -; CHECK-DAG: %[[#Int64Ty:]] = OpTypeInt 64 0 -; CHECK-DAG: %[[#FTy:]] = OpTypeFunction %[[#Int64Ty]] %[[#PtrTy]] +; CHECK-DAG: %[[#PtrInt8Ty:]] = OpTypePointer Function %[[#Int8Ty]] ; CHECK-DAG: %[[#Int32Ty:]] = OpTypeInt 32 0 +; CHECK-DAG: %[[#PtrInt32Ty:]] = OpTypePointer Function %[[#Int32Ty]] +; CHECK-DAG: %[[#Int64Ty:]] = OpTypeInt 64 0 +; CHECK-DAG: %[[#PtrInt64Ty:]] = OpTypePointer Function %[[#Int64Ty]] +; CHECK-DAG: %[[#FTy:]] = OpTypeFunction %[[#Int64Ty]] %[[#PtrInt8Ty]] ; CHECK-DAG: %[[#Const:]] = OpConstant %[[#Int32Ty]] 0 ; CHECK: OpFunction %[[#Int64Ty]] None %[[#FTy]] -; CHECK: %[[#Parm:]] = OpFunctionParameter %[[#PtrTy]] -; CHECK: OpStore %[[#Parm]] %[[#Const]] Aligned 4 -; CHECK: %[[#Res:]] = OpLoad %[[#Int64Ty]] %[[#Parm]] Aligned 8 +; CHECK: %[[#Parm:]] = OpFunctionParameter %[[#PtrInt8Ty]] +; CHECK-DAG: %[[#Bitcast1:]] = OpBitcast %[[#PtrInt32Ty]] %[[#Parm]] +; CHECK: OpStore %[[#Bitcast1]] %[[#Const]] Aligned 4 +; CHECK-DAG: %[[#Bitcast2:]] = OpBitcast %[[#PtrInt64Ty]] %[[#Parm]] +; CHECK: %[[#Res:]] = OpLoad %[[#Int64Ty]] %[[#Bitcast2]] Aligned 4 ; CHECK: OpReturnValue %[[#Res]] define i64 @test(ptr %p) { - store i32 0, ptr %p - %v = load i64, ptr %p + store i32 0, ptr %p, align 4 + %v = load i64, ptr %p, align 4 ret i64 %v } diff --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-bitcast-to-generic.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-bitcast-to-generic.ll new file mode 100644 index 0000000000000..9e136ce887468 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-bitcast-to-generic.ll @@ -0,0 +1,19 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s + +; CHECK-DAG: %[[#IMAGE:]] = OpTypeImage %2 2D 0 0 0 0 Unknown ReadOnly + +; CHECK: %[[#PARAM:]] = OpFunctionParameter %[[#IMAGE:]] +; CHECK-NOT: OpBitcast +; CHECK: %[[#]] = OpImageQuerySizeLod %[[#]] %[[#PARAM]] %[[#]] + +define spir_kernel void @test(ptr addrspace(1) %srcimg) #0 !kernel_arg_addr_space !1 !kernel_arg_access_qual !2 !kernel_arg_type !3 !kernel_arg_type_qual !4 !kernel_arg_base_type !3 { + %call = call spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_ro(ptr addrspace(1) %srcimg) + ret void +} + +declare spir_func <2 x i32> @_Z13get_image_dim14ocl_image2d_ro(ptr addrspace(1)) + +!1 = !{i32 1} +!2 = !{!"read_only"} +!3 = !{!"image2d_t"} +!4 = !{!""} diff --git a/llvm/test/CodeGen/SPIRV/sitofp-with-bool.ll b/llvm/test/CodeGen/SPIRV/sitofp-with-bool.ll index 4dda0aadced49..06f27e2cb1f90 100644 --- a/llvm/test/CodeGen/SPIRV/sitofp-with-bool.ll +++ b/llvm/test/CodeGen/SPIRV/sitofp-with-bool.ll @@ -1,9 +1,11 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s -; CHECK: %[[#int_32:]] = OpTypeInt 32 0 -; CHECK: %[[#bool:]] = OpTypeBool -; CHECK: %[[#zero:]] = OpConstant %[[#int_32]] 0 -; CHECK: %[[#one:]] = OpConstant %[[#int_32]] 1 +; CHECK-DAG: %[[#int_32:]] = OpTypeInt 32 0 +; CHECK-DAG: %[[#float:]] = OpTypeFloat 32 +; CHECK-DAG: %[[#bool:]] = OpTypeBool +; CHECK-DAG: %[[#zero:]] = OpConstant %[[#int_32]] 0 +; CHECK-DAG: %[[#one:]] = OpConstant %[[#int_32]] 1 +; CHECK-DAG: %[[#ptr:]] = OpTypePointer CrossWorkgroup %[[#float]] ; CHECK: OpFunction ; CHECK: %[[#A:]] = OpFunctionParameter %[[#]] @@ -11,9 +13,10 @@ ; CHECK: %[[#cmp_res:]] = OpSGreaterThan %[[#bool]] %[[#B]] %[[#zero]] ; CHECK: %[[#select_res:]] = OpSelect %[[#int_32]] %[[#cmp_res]] %[[#one]] %[[#zero]] ; CHECK: %[[#stof_res:]] = OpConvertSToF %[[#]] %[[#select_res]] -; CHECK: OpStore %[[#A]] %[[#stof_res]] +; CHECK: %[[#bitcast:]] = OpBitcast %[[#ptr]] %[[#A]] +; CHECK: OpStore %[[#bitcast]] %[[#stof_res]] -define dso_local spir_kernel void @K(float addrspace(1)* nocapture %A, i32 %B) local_unnamed_addr { +define dso_local spir_kernel void @K(ptr addrspace(1) nocapture %A, i32 %B) local_unnamed_addr { entry: %cmp = icmp sgt i32 %B, 0 %conv = sitofp i1 %cmp to float diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpPhi_ArgumentsPlaceholders.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpPhi_ArgumentsPlaceholders.ll index 9252e264cec8e..c98fef3631e04 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpPhi_ArgumentsPlaceholders.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpPhi_ArgumentsPlaceholders.ll @@ -13,6 +13,7 @@ ;; } ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; XFAIL: * %struct.Node = type { %struct.Node.0 addrspace(1)* } %struct.Node.0 = type opaque diff --git a/llvm/test/CodeGen/SPIRV/transcoding/spec_const.ll b/llvm/test/CodeGen/SPIRV/transcoding/spec_const.ll index 9fd7460885241..c47dccb35e14d 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/spec_const.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/spec_const.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; XFAIL: * ; CHECK-SPIRV-NOT: OpCapability Matrix ; CHECK-SPIRV-NOT: OpCapability Shader diff --git a/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll b/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll index 3c45fdd0481dc..a07af76c22324 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll @@ -19,10 +19,8 @@ ; CHECK-SPIRV: %[[#arr:]] = OpVariable %[[#i32x3_ptr]] Function ; CHECK-SPIRV: %[[#arr2:]] = OpVariable %[[#i32x3_ptr]] Function -; CHECK-SPIRV: %[[#arr_i8_ptr:]] = OpBitcast %[[#i8_ptr]] %[[#arr]] -; CHECK-SPIRV: OpCopyMemorySized %[[#arr_i8_ptr]] %[[#test_arr]] %[[#twelve]] Aligned 4 -; CHECK-SPIRV: %[[#arr2_i8_ptr:]] = OpBitcast %[[#i8_ptr]] %[[#arr2]] -; CHECK-SPIRV: OpCopyMemorySized %[[#arr2_i8_ptr]] %[[#test_arr2]] %[[#twelve]] Aligned 4 +; CHECK-SPIRV: OpCopyMemorySized %[[#arr]] %[[#test_arr]] %[[#twelve]] Aligned 4 +; CHECK-SPIRV: OpCopyMemorySized %[[#arr2]] %[[#test_arr2]] %[[#twelve]] Aligned 4 @__const.test.arr = private unnamed_addr addrspace(2) constant [3 x i32] [i32 1, i32 2, i32 3], align 4 diff --git a/llvm/test/CodeGen/SPIRV/uitofp-with-bool.ll b/llvm/test/CodeGen/SPIRV/uitofp-with-bool.ll index 2fe0dc91e7b4c..8a3c2853d9914 100644 --- a/llvm/test/CodeGen/SPIRV/uitofp-with-bool.ll +++ b/llvm/test/CodeGen/SPIRV/uitofp-with-bool.ll @@ -66,6 +66,7 @@ ; SPV-DAG: %[[#ones_16:]] = OpConstantComposite %[[#vec_16]] %[[#one_16]] %[[#one_16]] ; SPV-DAG: %[[#ones_32:]] = OpConstantComposite %[[#vec_32]] %[[#one_32]] %[[#one_32]] ; SPV-DAG: %[[#ones_64:]] = OpConstantComposite %[[#vec_64]] %[[#one_64]] %[[#one_64]] +; SPV-DAG: %[[#pointer:]] = OpTypePointer CrossWorkgroup %[[#float]] ; SPV-DAG: OpFunction ; SPV-DAG: %[[#A:]] = OpFunctionParameter %[[#]] @@ -81,7 +82,8 @@ entry: ; SPV-DAG: %[[#select_res:]] = OpSelect %[[#int_32]] %[[#cmp_res]] %[[#one_32]] %[[#zero_32]] ; SPV-DAG: %[[#utof_res:]] = OpConvertUToF %[[#float]] %[[#select_res]] %conv = uitofp i1 %cmp to float -; SPV-DAG: OpStore %[[#A]] %[[#utof_res]] +; SPV-DAG: %[[#bitcast:]] = OpBitcast %[[#pointer]] %[[#A]] +; SPV-DAG: OpStore %[[#bitcast]] %[[#utof_res]] store float %conv, float addrspace(1)* %A, align 4; ; SPV-DAG: %[[#s1]] = OpSelect %[[#int_8]] %[[#i1s]] %[[#mone_8]] %[[#zero_8]]