diff options
author | Vyacheslav Levytskyy <vyacheslav.levytskyy@intel.com> | 2024-06-26 19:38:51 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-26 19:38:51 +0200 |
commit | 0d9172ecaca2b0834e65343aa24d7cfa4f6d841d (patch) | |
tree | 32d75d01308c74ddd02e2e23304b102b4abb1c79 | |
parent | 581fd2fa573e39607ea164c0b4a8057baeb62c69 (diff) | |
download | llvm-0d9172ecaca2b0834e65343aa24d7cfa4f6d841d.zip llvm-0d9172ecaca2b0834e65343aa24d7cfa4f6d841d.tar.gz llvm-0d9172ecaca2b0834e65343aa24d7cfa4f6d841d.tar.bz2 |
[SPIR-V] Improve pattern matching and tracking of constant integers (#96615)
This PR fixes the issue
https://github.com/llvm/llvm-project/issues/96614 by improve pattern
matching and tracking of constant integers. The attached test is
successful if it doesn't crash and generate valid SPIR-V code for both
32 and 64 bits targets.
5 files changed, 61 insertions, 14 deletions
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index f5b6bcd..9be736c 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -1802,15 +1802,18 @@ bool SPIRVInstructionSelector::selectOpUndef(Register ResVReg, static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI) { assert(MO.isReg()); const SPIRVType *TypeInst = MRI->getVRegDef(MO.getReg()); - if (TypeInst->getOpcode() != SPIRV::ASSIGN_TYPE) - return false; - assert(TypeInst->getOperand(1).isReg()); - MachineInstr *ImmInst = MRI->getVRegDef(TypeInst->getOperand(1).getReg()); - return ImmInst->getOpcode() == TargetOpcode::G_CONSTANT; + if (TypeInst->getOpcode() == SPIRV::ASSIGN_TYPE) { + assert(TypeInst->getOperand(1).isReg()); + MachineInstr *ImmInst = MRI->getVRegDef(TypeInst->getOperand(1).getReg()); + return ImmInst->getOpcode() == TargetOpcode::G_CONSTANT; + } + return TypeInst->getOpcode() == SPIRV::OpConstantI; } static int64_t foldImm(const MachineOperand &MO, MachineRegisterInfo *MRI) { const SPIRVType *TypeInst = MRI->getVRegDef(MO.getReg()); + if (TypeInst->getOpcode() == SPIRV::OpConstantI) + return TypeInst->getOperand(2).getImm(); MachineInstr *ImmInst = MRI->getVRegDef(TypeInst->getOperand(1).getReg()); assert(ImmInst->getOpcode() == TargetOpcode::G_CONSTANT); return ImmInst->getOperand(1).getCImm()->getZExtValue(); diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp index 2df96c4..0ea2f17 100644 --- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp @@ -415,6 +415,7 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI = MF.getRegInfo(); SmallVector<MachineInstr *, 10> ToErase; + DenseMap<MachineInstr *, Register> RegsAlreadyAddedToDT; for (MachineBasicBlock *MBB : post_order(&MF)) { if (MBB->empty()) @@ -466,6 +467,7 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, // %rctmp = G_CONSTANT ty Val // %rc = ASSIGN_TYPE %rctmp, %cty Register Reg = MI.getOperand(0).getReg(); + bool NeedAssignType = true; if (MRI.hasOneUse(Reg)) { MachineInstr &UseMI = *MRI.use_instr_begin(Reg); if (isSpvIntrinsic(UseMI, Intrinsic::spv_assign_type) || @@ -478,7 +480,20 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, Ty = TargetExtIt == TargetExtConstTypes.end() ? MI.getOperand(1).getCImm()->getType() : TargetExtIt->second; - GR->add(MI.getOperand(1).getCImm(), &MF, Reg); + const ConstantInt *OpCI = MI.getOperand(1).getCImm(); + Register PrimaryReg = GR->find(OpCI, &MF); + if (!PrimaryReg.isValid()) { + GR->add(OpCI, &MF, Reg); + } else if (PrimaryReg != Reg && + MRI.getType(Reg) == MRI.getType(PrimaryReg)) { + auto *RCReg = MRI.getRegClassOrNull(Reg); + auto *RCPrimary = MRI.getRegClassOrNull(PrimaryReg); + if (!RCReg || RCPrimary == RCReg) { + RegsAlreadyAddedToDT[&MI] = PrimaryReg; + ToErase.push_back(&MI); + NeedAssignType = false; + } + } } else if (MIOp == TargetOpcode::G_FCONSTANT) { Ty = MI.getOperand(1).getFPImm()->getType(); } else { @@ -497,7 +512,8 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, MI.getNumExplicitOperands() - MI.getNumExplicitDefs(); Ty = VectorType::get(ElemTy, NumElts, false); } - insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MRI); + if (NeedAssignType) + insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MRI); } else if (MIOp == TargetOpcode::G_GLOBAL_VALUE) { propagateSPIRVType(&MI, GR, MRI, MIB); } @@ -508,8 +524,12 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR, --MII; } } - for (MachineInstr *MI : ToErase) + for (MachineInstr *MI : ToErase) { + auto It = RegsAlreadyAddedToDT.find(MI); + if (RegsAlreadyAddedToDT.contains(MI)) + MRI.replaceRegWith(MI->getOperand(0).getReg(), It->second); MI->eraseFromParent(); + } // Address the case when IRTranslator introduces instructions with new // registers without SPIRVType associated. diff --git a/llvm/test/CodeGen/SPIRV/const-nested-vecs.ll b/llvm/test/CodeGen/SPIRV/const-nested-vecs.ll index 7b2b205..9234106 100644 --- a/llvm/test/CodeGen/SPIRV/const-nested-vecs.ll +++ b/llvm/test/CodeGen/SPIRV/const-nested-vecs.ll @@ -1,8 +1,8 @@ -; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV64 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} -; TODO: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV -; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV32 +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#Var:]] "var" ; CHECK-SPIRV: OpName %[[#GVar:]] "g_var" @@ -24,8 +24,9 @@ ; CHECK-SPIRV-DAG: %[[#PtrArr2V2CharTy:]] = OpTypePointer CrossWorkgroup %[[#Arr2V2CharTy]] ; CHECK-SPIRV-DAG: %[[#IntZero:]] = OpConstantNull %[[#IntTy]] ; CHECK-SPIRV-DAG: %[[#LongZero:]] = OpConstantNull %[[#LongTy]] -; CHECK-SPIRV-DAG: %[[#ConstLong2:]] = OpConstant %[[#LongTy]] 2 -; CHECK-SPIRV-DAG: %[[#PvarInit:]] = OpSpecConstantOp %[[#PtrCharTy]] 70 %[[#VarV2Char:]] %[[#IntZero]] %[[#ConstLong2]] +; CHECK-SPIRV64-DAG: %[[#ConstLong2:]] = OpConstant %[[#LongTy]] 2 +; CHECK-SPIRV64-DAG: %[[#PvarInit:]] = OpSpecConstantOp %[[#PtrCharTy]] 70 %[[#VarV2Char:]] %[[#IntZero]] %[[#ConstLong2]] +; CHECK-SPIRV32-DAG: %[[#PvarInit:]] = OpSpecConstantOp %[[#PtrCharTy]] 70 %[[#VarV2Char:]] %[[#IntZero]] %[[#Const2]] ; CHECK-SPIRV-DAG: %[[#PtrPtrCharTy:]] = OpTypePointer CrossWorkgroup %[[#PtrCharTy]] ; CHECK-SPIRV-DAG: %[[#AVar]] = OpVariable %[[#PtrArr2V2CharTy]] CrossWorkgroup %[[#Arr2V2Char]] ; CHECK-SPIRV-DAG: %[[#PVar]] = OpVariable %[[#PtrPtrCharTy]] CrossWorkgroup %[[#PvarInit]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/global-zeroinitializer.ll b/llvm/test/CodeGen/SPIRV/pointers/global-zeroinitializer.ll index fdfcbba..679b0e4 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/global-zeroinitializer.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/global-zeroinitializer.ll @@ -16,7 +16,6 @@ ; CHECK: OpFunction @var = addrspace(1) global <2 x i8> zeroinitializer -;@var = addrspace(1) global <2 x i8> <i8 1, i8 1> define spir_kernel void @foo() { entry: diff --git a/llvm/test/CodeGen/SPIRV/pointers/irtrans-added-int-const-32-64.ll b/llvm/test/CodeGen/SPIRV/pointers/irtrans-added-int-const-32-64.ll new file mode 100644 index 0000000..ebc3fbf --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/irtrans-added-int-const-32-64.ll @@ -0,0 +1,24 @@ +; The goal of the test is to check that collisions between explicit integer constants and +; integer constants added automatically by IR Translator are resolved correctly both for +; 32- and 64-bits platforms. The test is successful if it doesn't crash and generate valid +; SPIR-V code for both 32 and 64 bits targets. + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV64 +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV32 +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV64-DAG: %[[#IntTy:]] = OpTypeInt 64 0 +; CHECK-SPIRV32-DAG: %[[#IntTy:]] = OpTypeInt 32 0 +; CHECK-SPIRV-DAG: %[[#Const2:]] = OpConstant %[[#IntTy]] 2 +; CHECK-SPIRV-DAG: %[[#]] = OpSpecConstantOp %[[#]] 70 %[[#]] %[[#]] %[[#Const2]] +; CHECK-SPIRV: OpFunction + +@a_var = addrspace(1) global [2 x i8] [i8 1, i8 1] +@p_var = addrspace(1) global ptr addrspace(1) getelementptr (i8, ptr addrspace(1) @a_var, i64 2) + +define spir_func void @foo() { +entry: + ret void +} |