@@ -562,6 +562,57 @@ static LogicalResult verifyConvOpErrorIf(T op) {
562
562
return success ();
563
563
}
564
564
565
+ // Verify whether same type and shape of the given two types.
566
+ static LogicalResult errorIfTypeOrShapeMismatch (Operation *op, Type type1,
567
+ StringRef name1, Type type2,
568
+ StringRef name2) {
569
+ auto shapeType1 = dyn_cast<ShapedType>(type1);
570
+ auto shapeType2 = dyn_cast<ShapedType>(type2);
571
+ if (!shapeType1 || !shapeType2)
572
+ return failure ();
573
+
574
+ auto elemType1 = shapeType1.getElementType ();
575
+ auto elemType2 = shapeType2.getElementType ();
576
+ if (elemType1 != elemType2)
577
+ return op->emitOpError ()
578
+ << " require same element type for " << name1 << " (" << elemType1
579
+ << " ) and " << name2 << " (" << elemType2 << " )" ;
580
+
581
+ if (failed (verifyCompatibleShape (type1, type2)))
582
+ return op->emitOpError ()
583
+ << " require same shapes for " << name1 << " (" << type1 << " ) and "
584
+ << name2 << " (" << type2 << " )" ;
585
+
586
+ return success ();
587
+ }
588
+
589
+ // Verify whether same length, type, and shape of the given two tensor lists.
590
+ static LogicalResult errorIfTypeOrShapeMismatch (Operation *op, ValueRange list1,
591
+ StringRef name1,
592
+ ValueRange list2,
593
+ StringRef name2) {
594
+ if (list1.size () != list2.size ())
595
+ return op->emitOpError ()
596
+ << " require same number of values in " << name1 << " ("
597
+ << list1.size () << " ) and " << name2 << " (" << list2.size () << " )" ;
598
+
599
+ for (auto [type1, type2] :
600
+ llvm::zip_equal (list1.getTypes (), list2.getTypes ())) {
601
+ if (errorIfTypeOrShapeMismatch (op, type1, name1, type2, name2).failed ())
602
+ return failure ();
603
+ }
604
+
605
+ return success ();
606
+ }
607
+
608
+ static inline LogicalResult errorIfShapeNotSizeOne (Operation *op, Type type) {
609
+ ShapeAdaptor shapeAdaptor (type);
610
+ if (!shapeAdaptor.hasRank () || !shapeAdaptor.hasStaticShape ())
611
+ return success ();
612
+
613
+ return shapeAdaptor.getNumElements () == 1 ? success () : failure ();
614
+ }
615
+
565
616
// verify that inType and outType have same element types
566
617
template <typename T>
567
618
static LogicalResult verifySameElementTypes (T op, Type inType, Type outType) {
@@ -3473,6 +3524,84 @@ void IfOp::print(OpAsmPrinter &p) {
3473
3524
p.printOptionalAttrDict ((*this )->getAttrs ());
3474
3525
}
3475
3526
3527
+ LogicalResult IfOp::verify () {
3528
+ if (errorIfTypeOrShapeMismatch (*this , getThenGraph ().front ().getArguments (),
3529
+ " 'then_graph' arguments" , getInputList (),
3530
+ " 'input_list'" )
3531
+ .failed ())
3532
+ return failure ();
3533
+
3534
+ if (errorIfTypeOrShapeMismatch (*this , getElseGraph ().front ().getArguments (),
3535
+ " 'else_graph' arguments" , getInputList (),
3536
+ " 'input_list'" )
3537
+ .failed ())
3538
+ return failure ();
3539
+
3540
+ auto thenYield = cast<tosa::YieldOp>(getThenGraph ().front ().getTerminator ());
3541
+ if (errorIfTypeOrShapeMismatch (*this , thenYield.getInputs (),
3542
+ " 'then_graph' results" , getOutputList (),
3543
+ " 'output_list'" )
3544
+ .failed ())
3545
+ return failure ();
3546
+
3547
+ auto elseYield = cast<tosa::YieldOp>(getElseGraph ().front ().getTerminator ());
3548
+ if (errorIfTypeOrShapeMismatch (*this , elseYield.getInputs (),
3549
+ " 'else_graph' results" , getOutputList (),
3550
+ " 'output_list'" )
3551
+ .failed ())
3552
+ return failure ();
3553
+
3554
+ auto condType = getCondition ().getType ();
3555
+ if (errorIfShapeNotSizeOne (*this , condType).failed ())
3556
+ return emitOpError () << " 'condition' must be a size 1 tensor, got "
3557
+ << condType;
3558
+
3559
+ return success ();
3560
+ }
3561
+
3562
+ LogicalResult WhileOp::verify () {
3563
+ if (errorIfTypeOrShapeMismatch (*this , getInputList (), " 'input_list'" ,
3564
+ getOutputList (), " 'output_list'" )
3565
+ .failed ())
3566
+ return failure ();
3567
+
3568
+ if (errorIfTypeOrShapeMismatch (*this , getCondGraph ().front ().getArguments (),
3569
+ " 'cond_graph' arguments" , getInputList (),
3570
+ " 'input_list'" )
3571
+ .failed ())
3572
+ return failure ();
3573
+
3574
+ if (errorIfTypeOrShapeMismatch (*this , getBodyGraph ().front ().getArguments (),
3575
+ " 'body_graph' arguments" , getInputList (),
3576
+ " 'input_list'" )
3577
+ .failed ())
3578
+ return failure ();
3579
+
3580
+ auto bodyYield = cast<tosa::YieldOp>(getBodyGraph ().front ().getTerminator ());
3581
+ if (errorIfTypeOrShapeMismatch (*this , bodyYield.getInputs (),
3582
+ " 'body_graph' results" , getInputList (),
3583
+ " 'input_list'" )
3584
+ .failed ())
3585
+ return failure ();
3586
+
3587
+ // Condition block output must be a single element tensor with a single bool
3588
+ // value.
3589
+ auto condYield = cast<tosa::YieldOp>(getCondGraph ().front ().getTerminator ());
3590
+ if (condYield.getInputs ().size () != 1 )
3591
+ return emitOpError () << " require 'cond_graph' only have one result" ;
3592
+
3593
+ auto condOutType = condYield.getInputs ()[0 ].getType ();
3594
+ if (errorIfShapeNotSizeOne (*this , condOutType).failed ())
3595
+ return emitOpError () << " 'cond_graph' result must be a size 1 tensor, got "
3596
+ << condOutType;
3597
+
3598
+ if (!getElementTypeOrSelf (condOutType).isInteger (1 ))
3599
+ return emitOpError () << " 'cond_graph' result must be a boolean tensor, got "
3600
+ << condOutType;
3601
+
3602
+ return success ();
3603
+ }
3604
+
3476
3605
LogicalResult ReverseOp::verify () {
3477
3606
if (verifySameElementTypes (*this , /* inType = */ getInput1 ().getType (),
3478
3607
/* outType = */ getOutput ().getType ())
0 commit comments