Skip to content

Commit 522dfea

Browse files
opt: Add support for OpExtInst to capability trim pass (#5836)
The grammar does track required capabilities for extended instruction set operations, so we just need to look them up.
1 parent c173df7 commit 522dfea

File tree

3 files changed

+106
-2
lines changed

3 files changed

+106
-2
lines changed

source/opt/trim_capabilities_pass.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "source/enum_set.h"
2929
#include "source/enum_string_mapping.h"
30+
#include "source/ext_inst.h"
3031
#include "source/opt/ir_context.h"
3132
#include "source/opt/reflect.h"
3233
#include "source/spirv_target_env.h"
@@ -49,6 +50,9 @@ constexpr uint32_t kOpTypeImageSampledIndex = kOpTypeImageMSIndex + 1;
4950
constexpr uint32_t kOpTypeImageFormatIndex = kOpTypeImageSampledIndex + 1;
5051
constexpr uint32_t kOpImageReadImageIndex = 0;
5152
constexpr uint32_t kOpImageSparseReadImageIndex = 0;
53+
constexpr uint32_t kOpExtInstSetInIndex = 0;
54+
constexpr uint32_t kOpExtInstInstructionInIndex = 1;
55+
constexpr uint32_t kOpExtInstImportNameInIndex = 0;
5256

5357
// DFS visit of the type defined by `instruction`.
5458
// If `condition` is true, children of the current node are visited.
@@ -514,6 +518,35 @@ void TrimCapabilitiesPass::addInstructionRequirementsForOperand(
514518
}
515519
}
516520

521+
void TrimCapabilitiesPass::addInstructionRequirementsForExtInst(
522+
Instruction* instruction, CapabilitySet* capabilities) const {
523+
assert(instruction->opcode() == spv::Op::OpExtInst &&
524+
"addInstructionRequirementsForExtInst must be passed an OpExtInst "
525+
"instruction");
526+
527+
const auto* def_use_mgr = context()->get_def_use_mgr();
528+
529+
const Instruction* extInstImport = def_use_mgr->GetDef(
530+
instruction->GetSingleWordInOperand(kOpExtInstSetInIndex));
531+
uint32_t extInstruction =
532+
instruction->GetSingleWordInOperand(kOpExtInstInstructionInIndex);
533+
534+
const Operand& extInstSet =
535+
extInstImport->GetInOperand(kOpExtInstImportNameInIndex);
536+
537+
spv_ext_inst_type_t instructionSet =
538+
spvExtInstImportTypeGet(extInstSet.AsString().c_str());
539+
540+
spv_ext_inst_desc desc = {};
541+
auto result =
542+
context()->grammar().lookupExtInst(instructionSet, extInstruction, &desc);
543+
if (result != SPV_SUCCESS) {
544+
return;
545+
}
546+
547+
addSupportedCapabilitiesToSet(desc, capabilities);
548+
}
549+
517550
void TrimCapabilitiesPass::addInstructionRequirements(
518551
Instruction* instruction, CapabilitySet* capabilities,
519552
ExtensionSet* extensions) const {
@@ -523,8 +556,12 @@ void TrimCapabilitiesPass::addInstructionRequirements(
523556
return;
524557
}
525558

526-
addInstructionRequirementsForOpcode(instruction->opcode(), capabilities,
527-
extensions);
559+
if (instruction->opcode() == spv::Op::OpExtInst) {
560+
addInstructionRequirementsForExtInst(instruction, capabilities);
561+
} else {
562+
addInstructionRequirementsForOpcode(instruction->opcode(), capabilities,
563+
extensions);
564+
}
528565

529566
// Second case: one of the opcode operand is gated by a capability.
530567
const uint32_t operandCount = instruction->NumOperands();

source/opt/trim_capabilities_pass.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class TrimCapabilitiesPass : public Pass {
9090
spv::Capability::ImageMSArray,
9191
spv::Capability::Int16,
9292
spv::Capability::Int64,
93+
spv::Capability::InterpolationFunction,
9394
spv::Capability::Linkage,
9495
spv::Capability::MinLod,
9596
spv::Capability::PhysicalStorageBufferAddresses,
@@ -160,6 +161,9 @@ class TrimCapabilitiesPass : public Pass {
160161
CapabilitySet* capabilities,
161162
ExtensionSet* extensions) const;
162163

164+
void addInstructionRequirementsForExtInst(Instruction* instruction,
165+
CapabilitySet* capabilities) const;
166+
163167
// Given an `instruction`, determines the capabilities it requires, and output
164168
// them in `capabilities`. The returned capabilities form a subset of
165169
// kSupportedCapabilities.

test/opt/trim_capabilities_pass_test.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3149,6 +3149,69 @@ TEST_P(TrimCapabilitiesPassTestSubgroupClustered_Unsigned,
31493149
EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
31503150
}
31513151

3152+
TEST_F(TrimCapabilitiesPassTest, InterpolationFunction_RemovedIfNotUsed) {
3153+
const std::string kTest = R"(
3154+
OpCapability Shader
3155+
OpCapability InterpolationFunction
3156+
; CHECK-NOT: OpCapability InterpolationFunction
3157+
OpMemoryModel Logical GLSL450
3158+
OpEntryPoint Fragment %main "main" %out_var_SV_Target
3159+
OpExecutionMode %main OriginUpperLeft
3160+
OpSource HLSL 660
3161+
OpName %out_var_SV_Target "out.var.SV_Target"
3162+
OpName %main "main"
3163+
OpDecorate %out_var_SV_Target Location 0
3164+
%float = OpTypeFloat 32
3165+
%v4float = OpTypeVector %float 4
3166+
%_ptr_Output_v4float = OpTypePointer Output %v4float
3167+
%void = OpTypeVoid
3168+
%7 = OpTypeFunction %void
3169+
%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
3170+
%main = OpFunction %void None %7
3171+
%8 = OpLabel
3172+
OpReturn
3173+
OpFunctionEnd
3174+
)";
3175+
const auto result =
3176+
SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false);
3177+
EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
3178+
}
3179+
3180+
TEST_F(TrimCapabilitiesPassTest,
3181+
InterpolationFunction_RemainsWithInterpolateAtCentroid) {
3182+
const std::string kTest = R"(
3183+
OpCapability Shader
3184+
OpCapability InterpolationFunction
3185+
; CHECK: OpCapability InterpolationFunction
3186+
%std450 = OpExtInstImport "GLSL.std.450"
3187+
OpMemoryModel Logical GLSL450
3188+
OpEntryPoint Fragment %main "main" %out_var_SV_Target %gl_PointCoord
3189+
OpExecutionMode %main OriginUpperLeft
3190+
OpSource HLSL 660
3191+
OpName %out_var_SV_Target "out.var.SV_Target"
3192+
OpName %main "main"
3193+
OpDecorate %out_var_SV_Target Location 0
3194+
OpDecorate %gl_PointCoord BuiltIn PointCoord
3195+
%float = OpTypeFloat 32
3196+
%v2float = OpTypeVector %float 2
3197+
%v4float = OpTypeVector %float 4
3198+
%_ptr_Output_v4float = OpTypePointer Output %v4float
3199+
%_ptr_Input_v2float = OpTypePointer Input %v2float
3200+
%void = OpTypeVoid
3201+
%7 = OpTypeFunction %void
3202+
%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
3203+
%gl_PointCoord = OpVariable %_ptr_Input_v2float Input
3204+
%main = OpFunction %void None %7
3205+
%8 = OpLabel
3206+
%9 = OpExtInst %v4float %std450 InterpolateAtCentroid %gl_PointCoord
3207+
OpReturn
3208+
OpFunctionEnd
3209+
)";
3210+
const auto result =
3211+
SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false);
3212+
EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange);
3213+
}
3214+
31523215
INSTANTIATE_TEST_SUITE_P(
31533216
TrimCapabilitiesPassTestSubgroupClustered_Unsigned_I,
31543217
TrimCapabilitiesPassTestSubgroupClustered_Unsigned,

0 commit comments

Comments
 (0)