@@ -826,3 +826,113 @@ def test_results_op_non_tree():
826826
827827 # Should handle the standalone results - no predicates expected for unused results
828828 assert len (predicates ) == 0
829+
830+
831+ def test_extract_operation_predicates_non_operation_op ():
832+ """Test that _extract_operation_predicates returns empty list when op_op is not an OperationOp"""
833+ body = Region ([Block ()])
834+ block = body .first_block
835+ with ImplicitBuilder (block ):
836+ # Create a non-OperationOp (e.g., TypeOp)
837+ type_op = pdl .TypeOp (f32 )
838+ op_op = pdl .OperationOp (None , type_values = (type_op .result ,))
839+ pdl .RewriteOp (None , name = "rewrite" )
840+
841+ p = PatternAnalyzer ()
842+ op_pos = OperationPosition (depth = 0 )
843+ inputs : dict [SSAValue , Position ] = {}
844+
845+ # Call _extract_operation_predicates with a non-OperationOp
846+ predicates = p ._extract_operation_predicates (type_op , op_pos , inputs ) # pyright: ignore[reportPrivateUsage]
847+
848+ # Should return no predicates
849+ assert len (predicates ) == 0 # Root position, so no is_not_null predicate
850+
851+ # Test with non-root position
852+ non_root_pos = OperationPosition (depth = 1 )
853+ predicates = p ._extract_operation_predicates (op_op , non_root_pos , inputs ) # pyright: ignore[reportPrivateUsage]
854+
855+ # Should return only the is_not_null predicate
856+ assert len (predicates ) == 5
857+ assert predicates [0 ].q == IsNotNullQuestion ()
858+ assert predicates [0 ].a == TrueAnswer ()
859+ assert predicates [0 ].position == non_root_pos
860+
861+
862+ def test_extract_operation_predicates_with_ignore_operand ():
863+ """Test extract_tree_predicates with ignore_operand parameter"""
864+ body = Region ([Block ()])
865+ block = body .first_block
866+ with ImplicitBuilder (block ):
867+ # Create operands with types to ensure they generate predicates
868+ operand_type = pdl .TypeOp (i32 )
869+ operand1 = pdl .OperandOp (value_type = operand_type .result )
870+ operand2 = pdl .OperandOp (value_type = operand_type .result )
871+ operand3 = pdl .OperandOp (value_type = operand_type .result )
872+
873+ # Create operation with multiple operands
874+ op = pdl .OperationOp (
875+ "test_op" ,
876+ operand_values = (operand1 .value , operand2 .value , operand3 .value ),
877+ )
878+
879+ pdl .RewriteOp (None , name = "rewrite" )
880+
881+ p = PatternAnalyzer ()
882+ op_pos = OperationPosition (depth = 0 )
883+
884+ # Extract predicates without ignore_operand
885+ predicates_all = p .extract_tree_predicates (op .op , op_pos , {})
886+
887+ # Extract predicates with ignore_operand=1 (ignore second operand)
888+ predicates_ignore = p .extract_tree_predicates (op .op , op_pos , {}, ignore_operand = 1 )
889+
890+ # Should have fewer predicates when ignoring an operand
891+ # The ignore_operand parameter should result in different predicate generation
892+ assert len (predicates_ignore ) < len (predicates_all )
893+
894+ ignored = set ((p .q , p .a , p .position ) for p in predicates_all ).difference (
895+ set ((p .q , p .a , p .position ) for p in predicates_ignore )
896+ )
897+ assert (
898+ EqualToQuestion (TypePosition (op_pos .get_operand (1 ))),
899+ TrueAnswer (),
900+ TypePosition (op_pos .get_operand (0 )),
901+ ) in ignored
902+ assert (IsNotNullQuestion (), TrueAnswer (), op_pos .get_operand (1 )) in ignored
903+
904+
905+ def test_extract_operand_tree_predicates_with_value_type ():
906+ """Test _extract_operand_tree_predicates where defining_op has value_type"""
907+ body = Region ([Block ()])
908+ block = body .first_block
909+ with ImplicitBuilder (block ):
910+ # Create a type for the operand
911+ operand_type = pdl .TypeOp (i32 )
912+
913+ # Create an OperandOp with a value_type
914+ operand_op = pdl .OperandOp (value_type = operand_type .result )
915+
916+ pdl .RewriteOp (None , name = "rewrite" )
917+
918+ p = PatternAnalyzer ()
919+ operand_pos = OperationPosition (depth = 0 ).get_operand (0 )
920+ inputs : dict [SSAValue , Position ] = {}
921+
922+ # Extract operand tree predicates
923+ predicates = p ._extract_operand_tree_predicates ( # pyright: ignore[reportPrivateUsage]
924+ operand_op .value , operand_pos , inputs
925+ )
926+
927+ # Should have is_not_null predicate and type constraint predicate
928+ assert len (predicates ) == 2
929+
930+ # First predicate should be is_not_null for the operand
931+ assert predicates [0 ].q == IsNotNullQuestion ()
932+ assert predicates [0 ].a == TrueAnswer ()
933+ assert predicates [0 ].position == operand_pos
934+
935+ # Second predicate should be type constraint for the operand's type
936+ assert predicates [1 ].q == TypeConstraintQuestion ()
937+ assert predicates [1 ].a == TypeAnswer (i32 )
938+ assert isinstance (predicates [1 ].position , TypePosition )
0 commit comments