44#include < mlir/Dialect/StandardOps/IR/Ops.h>
55#include < mlir/IR/BlockAndValueMapping.h>
66
7+ #include " plier/transforms/block_utils.hpp"
8+
79namespace
810{
911bool checkMemrefType (mlir::Value value)
1012{
1113 if (auto type = value.getType ().dyn_cast <mlir::MemRefType>())
1214 {
13- auto shape = type.getShape ();
14- return shape.empty () || (1 == shape.size () && 1 == shape[0 ]);
15+ // auto shape = type.getShape();
16+ // return shape.empty() || (1 == shape.size() && 1 == shape[0]);
17+ return true ;
1518 }
1619 return false ;
1720}
1821
19- bool checkForPotentialAliases (mlir::Value value )
22+ bool isOutsideBlock (mlir::ValueRange values, mlir::Block& block )
2023{
21- auto def_op = value. getDefiningOp ();
22- if ( nullptr == def_op )
24+ auto blockArgs = block. getArguments ();
25+ for ( auto val : values )
2326 {
24- return false ;
27+ if (llvm::find (blockArgs, val) != blockArgs.end ())
28+ {
29+ return false ;
30+ }
31+ auto op = val.getDefiningOp ();
32+ if (op && block.findAncestorOpInBlock (*op))
33+ {
34+ return false ;
35+ }
2536 }
26- if (auto effects = mlir::dyn_cast<mlir::MemoryEffectOpInterface>(def_op))
37+ return true ;
38+ }
39+
40+ bool checkForPotentialAliases (mlir::Value value, mlir::Operation* parent)
41+ {
42+ assert (parent->getRegions ().size () == 1 );
43+ assert (llvm::hasNItems (parent->getRegions ().front (), 1 ));
44+ if (auto effects = mlir::dyn_cast_or_null<mlir::MemoryEffectOpInterface>(value.getDefiningOp ()))
2745 {
28- if (!effects.hasEffect <mlir::MemoryEffects::Allocate>())
46+ if (!effects.onlyHasEffect <mlir::MemoryEffects::Allocate>())
2947 {
3048 return false ;
3149 }
@@ -34,13 +52,53 @@ bool checkForPotentialAliases(mlir::Value value)
3452 {
3553 return false ;
3654 }
55+
56+ mlir::LoadOp load;
57+ mlir::StoreOp store;
58+ auto & parentBlock = parent->getRegions ().front ().front ();
3759 for (auto user : value.getUsers ())
3860 {
3961 if (mlir::isa<mlir::ViewLikeOpInterface>(user))
4062 {
4163 // TODO: very conservative
4264 return false ;
4365 }
66+ auto relation = plier::relativeTo (user, parent);
67+ if (plier::OpRelation::Unknown == relation)
68+ {
69+ return false ;
70+ }
71+ if (plier::OpRelation::In == relation)
72+ {
73+ if (auto effects = mlir::dyn_cast_or_null<mlir::MemoryEffectOpInterface>(user))
74+ {
75+ if (user->getBlock () != &parentBlock)
76+ {
77+ return false ;
78+ }
79+ if (effects.hasEffect <mlir::MemoryEffects::Read>())
80+ {
81+ if (load || !mlir::isa<mlir::LoadOp>(user))
82+ {
83+ return false ;
84+ }
85+ load = mlir::cast<mlir::LoadOp>(user);
86+ }
87+ if (effects.hasEffect <mlir::MemoryEffects::Write>())
88+ {
89+ if (store || !mlir::isa<mlir::StoreOp>(user))
90+ {
91+ return false ;
92+ }
93+ store = mlir::cast<mlir::StoreOp>(user);
94+ }
95+ }
96+ }
97+ }
98+ if (!load || !store || !load->isBeforeInBlock (store) ||
99+ load.indices () != store.indices () || !isOutsideBlock (load.indices (), parentBlock))
100+ {
101+ return false ;
44102 }
45103 return true ;
46104}
@@ -59,63 +117,35 @@ bool checkSupportedOps(mlir::Value value, mlir::Operation* parent)
59117
60118bool checkMemref (mlir::Value value, mlir::Operation* parent)
61119{
62- return checkMemrefType (value) && checkForPotentialAliases (value) &&
120+ return checkMemrefType (value) &&
121+ checkForPotentialAliases (value, parent) &&
63122 checkSupportedOps (value, parent);
64123}
65124
66- mlir::Value createScalarLoad (
67- mlir::PatternRewriter &builder, mlir::Location loc, mlir::Value memref)
125+ mlir::Value createScalarLoad (mlir::PatternRewriter &builder, mlir::Location loc, mlir::Value memref, mlir::ValueRange indices)
68126{
69- auto shape = memref.getType ().cast <mlir::MemRefType>().getShape ();
70- if (shape.empty ())
71- {
72- return builder.create <mlir::LoadOp>(loc, memref);
73- }
74- else if (llvm::all_of (shape, [](auto s) { return s == 1 ; }))
75- {
76- auto index = builder.create <mlir::ConstantIndexOp>(loc, 0 );
77- llvm::SmallVector<mlir::Value> indices (shape.size (), index);
78- return builder.create <mlir::LoadOp>(loc, memref, indices);
79- }
80- else
81- {
82- llvm_unreachable (" Invalid shape" );
83- }
127+ return builder.create <mlir::LoadOp>(loc, memref, indices);
84128}
85129
86130void createScalarStore (
87131 mlir::PatternRewriter &builder, mlir::Location loc, mlir::Value val,
88- mlir::Value memref)
132+ mlir::Value memref, mlir::ValueRange indices )
89133{
90- auto shape = memref.getType ().cast <mlir::MemRefType>().getShape ();
91- if (shape.empty ())
92- {
93- builder.create <mlir::StoreOp>(loc, val, memref);
94- }
95- else if (llvm::all_of (shape, [](auto s) { return s == 1 ; }))
96- {
97- auto index = builder.create <mlir::ConstantIndexOp>(loc, 0 );
98- llvm::SmallVector<mlir::Value> indices (shape.size (), index);
99- builder.create <mlir::StoreOp>(loc, val, memref, indices);
100- }
101- else
102- {
103- llvm_unreachable (" Invalid shape" );
104- }
134+ builder.create <mlir::StoreOp>(loc, val, memref, indices);
105135}
106136}
107137
108138mlir::LogicalResult plier::CanonicalizeReduction::matchAndRewrite (mlir::scf::ForOp op, mlir::PatternRewriter& rewriter) const
109139{
110- llvm::SmallVector<mlir::Value> to_process;
140+ llvm::SmallVector<std::pair< mlir::Value, mlir::ValueRange> > to_process;
111141 for (auto & current : op.getLoopBody ().front ())
112142 {
113143 if (auto load = mlir::dyn_cast<mlir::LoadOp>(current))
114144 {
115145 auto memref = load.memref ();
116146 if (checkMemref (memref, op))
117147 {
118- to_process.emplace_back ( memref);
148+ to_process.push_back ({ memref, load. indices ()} );
119149 }
120150 }
121151 }
@@ -124,9 +154,9 @@ mlir::LogicalResult plier::CanonicalizeReduction::matchAndRewrite(mlir::scf::For
124154 {
125155 auto loc = op.getLoc ();
126156 auto init_args = llvm::to_vector<8 >(op.initArgs ());
127- for (auto val : to_process)
157+ for (auto it : to_process)
128158 {
129- init_args.emplace_back (createScalarLoad (rewriter, loc, val ));
159+ init_args.emplace_back (createScalarLoad (rewriter, loc, it. first , it. second ));
130160 }
131161 auto prev_args_offset = op.initArgs ().size ();
132162 auto body = [&](mlir::OpBuilder &builder, mlir::Location loc, mlir::Value iter, mlir::ValueRange iter_vals)
@@ -142,7 +172,7 @@ mlir::LogicalResult plier::CanonicalizeReduction::matchAndRewrite(mlir::scf::For
142172 auto get_iter_index = [&](auto op)->unsigned
143173 {
144174 auto arg = op.memref ();
145- for (auto it : llvm::enumerate (to_process))
175+ for (auto it : llvm::enumerate (llvm::make_first_range ( to_process) ))
146176 {
147177 if (arg == it.value ())
148178 {
@@ -189,7 +219,7 @@ mlir::LogicalResult plier::CanonicalizeReduction::matchAndRewrite(mlir::scf::For
189219 {
190220 auto index = prev_args_offset + it.index ();
191221 auto result = results[static_cast <unsigned >(index)];
192- createScalarStore (rewriter, loc, result, it.value ());
222+ createScalarStore (rewriter, loc, result, it.value (). first , it. value (). second );
193223 }
194224 rewriter.replaceOp (op, results.take_front (prev_args_offset));
195225 return mlir::success ();
0 commit comments