diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index 3098432ff0a..4d580decd44 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -2728,6 +2728,47 @@ nir_intrinsic_can_reorder(nir_intrinsic_instr *instr) (info->flags & NIR_INTRINSIC_CAN_REORDER); } +/* Return whether an instruction returns the same result regardless of where + * it's executed in the shader and regardless of whether it's executed multiple + * times. + */ +bool +nir_instr_can_speculate(nir_instr *instr) +{ + nir_intrinsic_instr *intr; + + switch (instr->type) { + case nir_instr_type_undef: + case nir_instr_type_load_const: + case nir_instr_type_alu: + case nir_instr_type_deref: + return true; + + case nir_instr_type_tex: + return false; + + case nir_instr_type_intrinsic: + intr = nir_instr_as_intrinsic(instr); + + if (!nir_intrinsic_can_reorder(intr)) + return false; + + if (nir_intrinsic_has_access(intr)) + return nir_intrinsic_access(intr) & ACCESS_CAN_SPECULATE; + + /* Intrinsics without ACCESS are speculatable if they can be reordered. */ + return true; + + case nir_instr_type_call: + case nir_instr_type_jump: + case nir_instr_type_phi: + case nir_instr_type_parallel_copy: + return false; + } + + return false; +} + nir_src * nir_get_shader_call_payload_src(nir_intrinsic_instr *call) { diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 31df58274fc..d5c31995844 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -2121,7 +2121,7 @@ void nir_rewrite_image_intrinsic(nir_intrinsic_instr *instr, /* Determine if an intrinsic can be arbitrarily reordered and eliminated. */ bool nir_intrinsic_can_reorder(nir_intrinsic_instr *instr); - +bool nir_instr_can_speculate(nir_instr *instr); bool nir_intrinsic_writes_external_memory(const nir_intrinsic_instr *instr); static inline bool diff --git a/src/compiler/nir/nir_opt_preamble.c b/src/compiler/nir/nir_opt_preamble.c index 5ee9e7b63a9..da86130c675 100644 --- a/src/compiler/nir/nir_opt_preamble.c +++ b/src/compiler/nir/nir_opt_preamble.c @@ -102,18 +102,10 @@ typedef struct { static bool instr_can_speculate(nir_instr *instr) { - /* Intrinsics with an ACCESS index can only be speculated if they are - * explicitly CAN_SPECULATE. - */ - if (instr->type == nir_instr_type_intrinsic) { - nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + if (instr->type == nir_instr_type_phi) + return true; - if (nir_intrinsic_has_access(intr)) - return nir_intrinsic_access(intr) & ACCESS_CAN_SPECULATE; - } - - /* For now, everything else can be speculated. TODO: Bindless textures. */ - return true; + return nir_instr_can_speculate(instr); } static float