2020 * THE SOFTWARE.
2121 */
2222
23+ #include " TritonControlFlowOpt/ControlFlowRewrite.h"
2324#include " TritonToUnstructure/UnstructureConversionPass.h"
2425#include " Utils/Utils.h"
2526
@@ -37,6 +38,25 @@ static bool isScalarPointerType(Type type) {
3738 return pointerType && !isa<ShapedType>(pointerType.getPointeeType ());
3839}
3940
41+ static bool isPointerDescriptorBoundarySlot (Operation *loop, unsigned slot) {
42+ if (!loop)
43+ return false ;
44+ auto slots = dyn_cast_or_null<DenseI32ArrayAttr>(
45+ loop->getAttr (controlflow::kPointerDescriptorBoundaryAttr ));
46+ return slots &&
47+ llvm::is_contained (slots.asArrayRef (), static_cast <int32_t >(slot));
48+ }
49+
50+ // Only scalar pointers owned by the CFO descriptor schema cross a loop as a
51+ // complete i64 address. Ordinary scalar pointers retain the established
52+ // base-plus-relative-offset representation.
53+ static bool useCompleteScalarAddress (Operation *loop, unsigned slot,
54+ Type type) {
55+ return loop && isa<scf::ForOp, scf::WhileOp>(loop) &&
56+ isScalarPointerType (type) &&
57+ isPointerDescriptorBoundarySlot (loop, slot);
58+ }
59+
4060// A scalar-pointer SCF slot is represented by one complete i64 address on all
4161// structural edges. Region-local pointer users are rebuilt immediately, so no
4262// pointer type crosses the control-flow boundary.
@@ -221,11 +241,12 @@ int getPtrTensorRank(Type type) {
221241}
222242
223243SmallVector<Value> constructOperands (ValueRange operands, Value tempVar,
224- IRMapping mapping, OpBuilder &builder) {
244+ IRMapping mapping, OpBuilder &builder,
245+ Operation *loop) {
225246 SmallVector<Value> newOperands;
226- for (Value originalOperand : operands) {
247+ for (auto [slot, originalOperand] : llvm::enumerate ( operands) ) {
227248 Value mappedOperand = mapping.lookupOrDefault (originalOperand);
228- if (isScalarPointerType ( originalOperand.getType ()))
249+ if (useCompleteScalarAddress (loop, slot, originalOperand.getType ()))
229250 mappedOperand = materializeScalarPointerAddress (mappedOperand, builder,
230251 originalOperand.getLoc ());
231252 newOperands.push_back (mappedOperand);
@@ -236,10 +257,10 @@ SmallVector<Value> constructOperands(ValueRange operands, Value tempVar,
236257 return newOperands;
237258}
238259
239- SmallVector<Type> constructTypes (TypeRange types) {
260+ SmallVector<Type> constructTypes (TypeRange types, Operation *loop ) {
240261 SmallVector<Type> newTypes;
241- for (auto type : types) {
242- newTypes.push_back (isScalarPointerType ( type)
262+ for (auto [slot, type] : llvm::enumerate ( types) ) {
263+ newTypes.push_back (useCompleteScalarAddress (loop, slot, type)
243264 ? IntegerType::get (type.getContext (), 64 )
244265 : type);
245266 if (auto ptrType = dyn_cast<triton::PointerType>(type)) {
@@ -269,17 +290,18 @@ void replacePtrArguments(triton::FuncOp funcOp,
269290 // replacement immediately before the old op and erase the old op last.
270291 rewriter.setInsertionPoint (op);
271292 if (auto forOp = dyn_cast<scf::ForOp>(op)) {
272- SmallVector<Value> newInitArgs =
273- constructOperands ( forOp.getInitArgs (), tempVar, mapping, rewriter);
293+ SmallVector<Value> newInitArgs = constructOperands (
294+ forOp.getInitArgs (), tempVar, mapping, rewriter, forOp );
274295 newOp = rewriter.create <scf::ForOp>(
275296 forOp.getLoc (), forOp.getLowerBound (), forOp.getUpperBound (),
276297 forOp.getStep (), newInitArgs,
277298 [&](OpBuilder &b, Location loc, Value iv, ValueRange args) {
278299 mapping.map (forOp.getInductionVar (), iv);
279300 auto newArgIter = args.begin ();
280- for (auto oldArg : forOp.getRegionIterArgs ()) {
301+ for (auto [slot, oldArg] :
302+ llvm::enumerate (forOp.getRegionIterArgs ())) {
281303 Value mappedArg = *newArgIter;
282- if (isScalarPointerType ( oldArg.getType ()))
304+ if (useCompleteScalarAddress (forOp, slot, oldArg.getType ()))
283305 mappedArg =
284306 rebuildScalarPointer (mappedArg, oldArg.getType (), b, loc);
285307 mapping.map (oldArg, mappedArg);
@@ -290,20 +312,23 @@ void replacePtrArguments(triton::FuncOp funcOp,
290312 b.clone (bodyOp, mapping);
291313 }
292314 auto yieldOp = cast<scf::YieldOp>(forOp.getBody ()->getTerminator ());
293- b.create <scf::YieldOp>(
294- yieldOp.getLoc (),
295- constructOperands (yieldOp.getOperands (), tempVar, mapping, b));
315+ b.create <scf::YieldOp>(yieldOp.getLoc (),
316+ constructOperands (yieldOp.getOperands (),
317+ tempVar, mapping, b,
318+ forOp));
296319 });
297320 } else if (auto whileOp = dyn_cast<scf::WhileOp>(op)) {
298- SmallVector<Value> newInits =
299- constructOperands ( whileOp.getInits (), tempVar, mapping, rewriter);
321+ SmallVector<Value> newInits = constructOperands (
322+ whileOp.getInits (), tempVar, mapping, rewriter, whileOp );
300323 newOp = rewriter.create <scf::WhileOp>(
301- whileOp.getLoc (), constructTypes (whileOp->getResultTypes ()), newInits,
324+ whileOp.getLoc (), constructTypes (whileOp->getResultTypes (), whileOp),
325+ newInits,
302326 [&](OpBuilder &b, Location loc, ValueRange args) {
303327 auto newArgIter = args.begin ();
304- for (auto oldArg : whileOp.getBeforeArguments ()) {
328+ for (auto [slot, oldArg] :
329+ llvm::enumerate (whileOp.getBeforeArguments ())) {
305330 Value mappedArg = *newArgIter;
306- if (isScalarPointerType ( oldArg.getType ()))
331+ if (useCompleteScalarAddress (whileOp, slot, oldArg.getType ()))
307332 mappedArg =
308333 rebuildScalarPointer (mappedArg, oldArg.getType (), b, loc);
309334 mapping.map (oldArg, mappedArg);
@@ -317,13 +342,15 @@ void replacePtrArguments(triton::FuncOp funcOp,
317342 b.create <scf::ConditionOp>(
318343 conditionOp.getLoc (),
319344 mapping.lookup (conditionOp.getCondition ()),
320- constructOperands (conditionOp.getArgs (), tempVar, mapping, b));
345+ constructOperands (conditionOp.getArgs (), tempVar, mapping, b,
346+ whileOp));
321347 },
322348 [&](OpBuilder &b, Location loc, ValueRange args) {
323349 auto newArgIter = args.begin ();
324- for (auto oldArg : whileOp.getAfterArguments ()) {
350+ for (auto [slot, oldArg] :
351+ llvm::enumerate (whileOp.getAfterArguments ())) {
325352 Value mappedArg = *newArgIter;
326- if (isScalarPointerType ( oldArg.getType ()))
353+ if (useCompleteScalarAddress (whileOp, slot, oldArg.getType ()))
327354 mappedArg =
328355 rebuildScalarPointer (mappedArg, oldArg.getType (), b, loc);
329356 mapping.map (oldArg, mappedArg);
@@ -334,9 +361,10 @@ void replacePtrArguments(triton::FuncOp funcOp,
334361 b.clone (bodyOp, mapping);
335362 }
336363 auto yieldOp = whileOp.getYieldOp ();
337- b.create <scf::YieldOp>(
338- yieldOp.getLoc (),
339- constructOperands (yieldOp.getOperands (), tempVar, mapping, b));
364+ b.create <scf::YieldOp>(yieldOp.getLoc (),
365+ constructOperands (yieldOp.getOperands (),
366+ tempVar, mapping, b,
367+ whileOp));
340368 });
341369 } else if (auto ifOp = dyn_cast<scf::IfOp>(op);
342370 ifOp && ifOp->getNumResults () > 0 ) {
@@ -347,18 +375,20 @@ void replacePtrArguments(triton::FuncOp funcOp,
347375 b.clone (bodyOp, mapping);
348376 }
349377 auto yieldOp = ifOp.thenYield ();
350- b.create <scf::YieldOp>(
351- yieldOp.getLoc (),
352- constructOperands (yieldOp.getOperands (), tempVar, mapping, b));
378+ b.create <scf::YieldOp>(yieldOp.getLoc (),
379+ constructOperands (yieldOp.getOperands (),
380+ tempVar, mapping, b,
381+ /* loop=*/ nullptr ));
353382 },
354383 [&](OpBuilder &b, Location loc) {
355384 for (auto &bodyOp : ifOp.elseBlock ()->without_terminator ()) {
356385 b.clone (bodyOp, mapping);
357386 }
358387 auto yieldOp = ifOp.elseYield ();
359- b.create <scf::YieldOp>(
360- yieldOp.getLoc (),
361- constructOperands (yieldOp.getOperands (), tempVar, mapping, b));
388+ b.create <scf::YieldOp>(yieldOp.getLoc (),
389+ constructOperands (yieldOp.getOperands (),
390+ tempVar, mapping, b,
391+ /* loop=*/ nullptr ));
362392 });
363393 } else if (auto loopOp = dyn_cast<LoopLikeOpInterface>(op)) {
364394 llvm_unreachable (" Unsupported loop op" );
@@ -370,9 +400,9 @@ void replacePtrArguments(triton::FuncOp funcOp,
370400 os << " Converting\n " << *op << " \n to\n " << *newOp << " \n " ;
371401 });
372402 auto resIter = newOp->result_begin ();
373- for (auto res : op->getResults ()) {
403+ for (auto [slot, res] : llvm::enumerate ( op->getResults () )) {
374404 Value replacement = *resIter;
375- if (isScalarPointerType ( res.getType ())) {
405+ if (useCompleteScalarAddress (op, slot, res.getType ())) {
376406 rewriter.setInsertionPointAfter (newOp);
377407 replacement = rebuildScalarPointer (replacement, res.getType (),
378408 rewriter, res.getLoc ());
0 commit comments