@@ -1541,26 +1541,25 @@ static LogicalResult verifyPrivateVarList(OpType &op) {
1541
1541
}
1542
1542
1543
1543
LogicalResult ParallelOp::verify () {
1544
- // Check that it is a valid loop wrapper if it's taking that role.
1545
- if (isa<DistributeOp>((*this )->getParentOp ())) {
1546
- if (!isWrapper ())
1547
- return emitOpError () << " must take a loop wrapper role if nested inside "
1548
- " of 'omp.distribute'" ;
1544
+ auto distributeChildOps = getOps<DistributeOp>();
1545
+ if (!distributeChildOps.empty ()) {
1549
1546
if (!isComposite ())
1550
1547
return emitError ()
1551
- << " 'omp.composite' attribute missing from composite wrapper " ;
1548
+ << " 'omp.composite' attribute missing from composite operation " ;
1552
1549
1553
- if (LoopWrapperInterface nested = getNestedWrapper ()) {
1554
- // Check for the allowed leaf constructs that may appear in a composite
1555
- // construct directly after PARALLEL.
1556
- if (!isa<WsloopOp>(nested))
1557
- return emitError () << " only supported nested wrapper is 'omp.wsloop'" ;
1558
- } else {
1559
- return emitOpError () << " must not wrap an 'omp.loop_nest' directly" ;
1550
+ auto *ompDialect = getContext ()->getLoadedDialect <OpenMPDialect>();
1551
+ Operation &distributeOp = **distributeChildOps.begin ();
1552
+ for (Operation &childOp : getOps ()) {
1553
+ if (&childOp == &distributeOp || ompDialect != childOp.getDialect ())
1554
+ continue ;
1555
+
1556
+ if (!childOp.hasTrait <OpTrait::IsTerminator>())
1557
+ return emitError () << " unexpected OpenMP operation inside of composite "
1558
+ " 'omp.parallel'" ;
1560
1559
}
1561
1560
} else if (isComposite ()) {
1562
1561
return emitError ()
1563
- << " 'omp.composite' attribute present in non-composite wrapper " ;
1562
+ << " 'omp.composite' attribute present in non-composite operation " ;
1564
1563
}
1565
1564
1566
1565
if (getAllocateVars ().size () != getAllocatorVars ().size ())
@@ -1721,6 +1720,32 @@ void printWsloop(OpAsmPrinter &p, Operation *op, Region ®ion,
1721
1720
p.printRegion (region, /* printEntryBlockArgs=*/ false );
1722
1721
}
1723
1722
1723
+ static LogicalResult verifyLoopWrapperInterface (Operation *op) {
1724
+ if (op->getNumRegions () != 1 )
1725
+ return op->emitOpError () << " loop wrapper contains multiple regions" ;
1726
+
1727
+ Region ®ion = op->getRegion (0 );
1728
+ if (!region.hasOneBlock ())
1729
+ return op->emitOpError () << " loop wrapper contains multiple blocks" ;
1730
+
1731
+ if (::llvm::range_size (region.getOps ()) != 2 )
1732
+ return op->emitOpError ()
1733
+ << " loop wrapper does not contain exactly two nested ops" ;
1734
+
1735
+ Operation &firstOp = *region.op_begin ();
1736
+ Operation &secondOp = *(std::next (region.op_begin ()));
1737
+
1738
+ if (!secondOp.hasTrait <OpTrait::IsTerminator>())
1739
+ return op->emitOpError ()
1740
+ << " second nested op in loop wrapper is not a terminator" ;
1741
+
1742
+ if (!::llvm::isa<LoopNestOp, LoopWrapperInterface>(firstOp))
1743
+ return op->emitOpError () << " first nested op in loop wrapper is not "
1744
+ " another loop wrapper or `omp.loop_nest`" ;
1745
+
1746
+ return success ();
1747
+ }
1748
+
1724
1749
void WsloopOp::build (OpBuilder &builder, OperationState &state,
1725
1750
ArrayRef<NamedAttribute> attributes) {
1726
1751
build (builder, state, /* allocate_vars=*/ {}, /* allocator_vars=*/ {},
@@ -1751,15 +1776,12 @@ void WsloopOp::build(OpBuilder &builder, OperationState &state,
1751
1776
}
1752
1777
1753
1778
LogicalResult WsloopOp::verify () {
1754
- if (! isWrapper ())
1755
- return emitOpError () << " must be a loop wrapper " ;
1779
+ if (verifyLoopWrapperInterface (* this ). failed ())
1780
+ return failure () ;
1756
1781
1757
- auto wrapper =
1758
- llvm::dyn_cast_if_present<LoopWrapperInterface>((*this )->getParentOp ());
1759
1782
bool isCompositeChildLeaf =
1760
- wrapper && wrapper.isWrapper () &&
1761
- (!llvm::isa<ParallelOp>(wrapper) ||
1762
- llvm::isa_and_present<DistributeOp>(wrapper->getParentOp ()));
1783
+ llvm::dyn_cast_if_present<LoopWrapperInterface>((*this )->getParentOp ());
1784
+
1763
1785
if (LoopWrapperInterface nested = getNestedWrapper ()) {
1764
1786
if (!isComposite ())
1765
1787
return emitError ()
@@ -1813,18 +1835,14 @@ LogicalResult SimdOp::verify() {
1813
1835
if (verifyNontemporalClause (*this , getNontemporalVars ()).failed ())
1814
1836
return failure ();
1815
1837
1816
- if (! isWrapper ())
1817
- return emitOpError () << " must be a loop wrapper " ;
1838
+ if (verifyLoopWrapperInterface (* this ). failed ())
1839
+ return failure () ;
1818
1840
1819
1841
if (getNestedWrapper ())
1820
1842
return emitOpError () << " must wrap an 'omp.loop_nest' directly" ;
1821
1843
1822
- auto wrapper =
1823
- llvm::dyn_cast_if_present<LoopWrapperInterface>((*this )->getParentOp ());
1824
1844
bool isCompositeChildLeaf =
1825
- wrapper && wrapper.isWrapper () &&
1826
- (!llvm::isa<ParallelOp>(wrapper) ||
1827
- llvm::isa_and_present<DistributeOp>(wrapper->getParentOp ()));
1845
+ llvm::dyn_cast_if_present<LoopWrapperInterface>((*this )->getParentOp ());
1828
1846
1829
1847
if (!isComposite () && isCompositeChildLeaf)
1830
1848
return emitError ()
@@ -1859,18 +1877,22 @@ LogicalResult DistributeOp::verify() {
1859
1877
return emitError (
1860
1878
" expected equal sizes for allocate and allocator variables" );
1861
1879
1862
- if (! isWrapper ())
1863
- return emitOpError () << " must be a loop wrapper " ;
1880
+ if (verifyLoopWrapperInterface (* this ). failed ())
1881
+ return failure () ;
1864
1882
1865
1883
if (LoopWrapperInterface nested = getNestedWrapper ()) {
1866
1884
if (!isComposite ())
1867
1885
return emitError ()
1868
1886
<< " 'omp.composite' attribute missing from composite wrapper" ;
1869
1887
// Check for the allowed leaf constructs that may appear in a composite
1870
1888
// construct directly after DISTRIBUTE.
1871
- if (!isa<ParallelOp, SimdOp>(nested))
1872
- return emitError () << " only supported nested wrappers are 'omp.parallel' "
1873
- " and 'omp.simd'" ;
1889
+ if (isa<WsloopOp>(nested)) {
1890
+ if (!llvm::dyn_cast_if_present<ParallelOp>((*this )->getParentOp ()))
1891
+ return emitError () << " an 'omp.wsloop' nested wrapper is only allowed "
1892
+ " when 'omp.parallel' is the direct parent" ;
1893
+ } else if (!isa<SimdOp>(nested))
1894
+ return emitError () << " only supported nested wrappers are 'omp.simd' and "
1895
+ " 'omp.wsloop'" ;
1874
1896
} else if (isComposite ()) {
1875
1897
return emitError ()
1876
1898
<< " 'omp.composite' attribute present in non-composite wrapper" ;
@@ -2063,8 +2085,8 @@ LogicalResult TaskloopOp::verify() {
2063
2085
" may not appear on the same taskloop directive" );
2064
2086
}
2065
2087
2066
- if (! isWrapper ())
2067
- return emitOpError () << " must be a loop wrapper " ;
2088
+ if (verifyLoopWrapperInterface (* this ). failed ())
2089
+ return failure () ;
2068
2090
2069
2091
if (LoopWrapperInterface nested = getNestedWrapper ()) {
2070
2092
if (!isComposite ())
@@ -2161,11 +2183,8 @@ LogicalResult LoopNestOp::verify() {
2161
2183
<< " range argument type does not match corresponding IV type" ;
2162
2184
}
2163
2185
2164
- auto wrapper =
2165
- llvm::dyn_cast_if_present<LoopWrapperInterface>((*this )->getParentOp ());
2166
-
2167
- if (!wrapper || !wrapper.isWrapper ())
2168
- return emitOpError () << " expects parent op to be a valid loop wrapper" ;
2186
+ if (!llvm::dyn_cast_if_present<LoopWrapperInterface>((*this )->getParentOp ()))
2187
+ return emitOpError () << " expects parent op to be a loop wrapper" ;
2169
2188
2170
2189
return success ();
2171
2190
}
@@ -2175,8 +2194,6 @@ void LoopNestOp::gatherWrappers(
2175
2194
Operation *parent = (*this )->getParentOp ();
2176
2195
while (auto wrapper =
2177
2196
llvm::dyn_cast_if_present<LoopWrapperInterface>(parent)) {
2178
- if (!wrapper.isWrapper ())
2179
- break ;
2180
2197
wrappers.push_back (wrapper);
2181
2198
parent = parent->getParentOp ();
2182
2199
}
0 commit comments