Skip to content

Commit 137eee9

Browse files
committed
Reduce the restrictions on pass TritonToUnstructured, and support tt.addptr+tt.load conversion scenarios within if, such as the scenario of decode_attn_stage2[vllm].
1 parent e7a375a commit 137eee9

2 files changed

Lines changed: 104 additions & 9 deletions

File tree

lib/Conversion/TritonToUnstructured/TritonToUnstructuredPass.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@
173173
#include <queue>
174174

175175
#define DEBUG_TYPE "triton-to-unstructured"
176+
#define DBGS() (llvm::dbgs() << "[" DEBUG_TYPE "]: ")
177+
#define LDBG(X) \
178+
LLVM_DEBUG(DBGS() << "[" << __FILE__ << ":" << __LINE__ << "]" << X << "\n")
176179

177180
using namespace mlir;
178181
using namespace triton;
@@ -320,8 +323,10 @@ class TritonToUnstructuredPass
320323
// Bail when we have an addptr in an scf.if as we do not know
321324
// if the pointer returning from both branches will have the
322325
// same source
323-
if (addptr->getParentOfType<scf::IfOp>()) {
326+
// TODO : check if ptr and load is in the same block
327+
if (!check_addrptr_in_same_block_with_its_users(addptr)) {
324328
return failure();
329+
// TODO: We Shall Need Another Pass Later To Deal With this situation
325330
}
326331

327332
OpBuilder b{addptr};
@@ -363,6 +368,9 @@ class TritonToUnstructuredPass
363368
})
364369
.Case<triton::SplatOp, triton::BroadcastOp,
365370
triton::ExpandDimsOp>([&](Operation *op) {
371+
if (!offsetMap.contains(op->getOperand(0))) {
372+
return failure();
373+
}
366374
auto res = op->getResult(0);
367375
auto resType = res.getType();
368376

@@ -418,6 +426,9 @@ class TritonToUnstructuredPass
418426
auto argIndex = use.getOperandNumber() - 3;
419427
auto init = forOp.getInitArgs()[argIndex];
420428

429+
if (!offsetMap.contains(init)) {
430+
return failure();
431+
}
421432
auto offsetInfo = offsetMap.at(init);
422433

423434
auto offsetType =
@@ -458,18 +469,20 @@ class TritonToUnstructuredPass
458469
})
459470
.Case<scf::YieldOp>([](auto) { return success(); })
460471
.Case<triton::CatOp>([](triton::CatOp op) {
461-
op->emitError("Do not support gather / scatter with multiple "
462-
"bases yet");
472+
op->emitError(
473+
"Do not support gather / scatter with multiple "
474+
"bases yet");
463475
return failure();
464476
})
465477
.Default([&](Operation *op) {
466478
op->emitError("unexpected op in ptr sequence");
467479
return failure();
468480
});
469481

470-
if (failed(res)) {
471-
return failure();
472-
}
482+
// if (failed(res)) { // NOTE: should here just report the failure and
483+
// // outside just continue
484+
// return failure();
485+
// }
473486
}
474487
}
475488

@@ -479,6 +492,9 @@ class TritonToUnstructuredPass
479492
auto res =
480493
llvm::TypeSwitch<Operation *, LogicalResult>(op)
481494
.Case<triton::LoadOp>([&](triton::LoadOp load) {
495+
if (!offsetMap.contains(load.getPtr())) {
496+
return failure();
497+
}
482498
auto offsetInfo = offsetMap.at(load.getPtr());
483499

484500
auto other = load.getOther();
@@ -500,6 +516,9 @@ class TritonToUnstructuredPass
500516
return success();
501517
})
502518
.Case<triton::StoreOp>([&](triton::StoreOp store) {
519+
if (!offsetMap.contains(store.getPtr())) {
520+
return failure();
521+
}
503522
auto offsetInfo = offsetMap.at(store.getPtr());
504523
b.create<tts::ScatterOp>(loc, offsetInfo.ptr, offsetInfo.offset,
505524
store.getValue(), store.getMask());
@@ -508,6 +527,9 @@ class TritonToUnstructuredPass
508527
})
509528
.Case<triton::MakeTensorPtrOp,
510529
tts::MakeTensorPtrOp>([&](auto makeTensorPtr) {
530+
if (!offsetMap.contains(makeTensorPtr.getBase())) {
531+
return failure();
532+
}
511533
// For block pointers, the base could come from a sequence of
512534
// `tt.addptr`. Accumulate the target offset with the offset
513535
// we have saved.
@@ -557,9 +579,9 @@ class TritonToUnstructuredPass
557579
return failure();
558580
});
559581

560-
if (failed(res)) {
561-
return failure();
562-
}
582+
// if (failed(res)) {
583+
// return failure();
584+
// }
563585
}
564586

565587
for (auto op : toDelete) {
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// RUN: triton-shared-opt --triton-to-unstructured %s | FileCheck %s
2+
// https://github.com/vllm-project/vllm/blob/a5dd03c1ebc5e4f56f3c9d3dc0436e9c582c978f/vllm/attention/ops/triton_decode_attention.py#L472
3+
4+
// -----// IR Dump Before TritonToUnstructured (triton-to-unstructured) //----- //
5+
module {
6+
tt.func public @_fwd_kernel_stage2(%arg0: !tt.ptr<f32> {tt.divisibility = 16 : i32}, %arg1: !tt.ptr<f32> {tt.divisibility = 16 : i32}, %arg2: !tt.ptr<i32> {tt.divisibility = 16 : i32}, %arg3: i32 {tt.divisibility = 16 : i32}, %arg4: i32, %arg5: i32, %arg6: i32 {tt.divisibility = 16 : i32}, %arg7: i32 {tt.divisibility = 16 : i32}) attributes {noinline = false} {
7+
%c3_i32 = arith.constant 3 : i32
8+
%c1_i32 = arith.constant 1 : i32
9+
%c4_i32 = arith.constant 4 : i32
10+
%c0_i32 = arith.constant 0 : i32
11+
%cst = arith.constant dense<0.000000e+00> : tensor<32xf32>
12+
%cst_0 = arith.constant 0xFF800000 : f32
13+
%cst_1 = arith.constant 0.000000e+00 : f32
14+
%c32_i32 = arith.constant 32 : i32
15+
%0 = tt.get_program_id x : i32
16+
%1 = tt.get_program_id y : i32
17+
%2 = tt.addptr %arg2, %0 : !tt.ptr<i32>, i32
18+
%3 = tt.load %2 : !tt.ptr<i32>
19+
%4 = arith.muli %0, %arg3 : i32
20+
%5 = arith.muli %1, %arg4 : i32
21+
%6 = arith.addi %4, %5 : i32
22+
%7 = arith.index_cast %6 : i32 to index
23+
%8 = arith.addi %6, %c32_i32 : i32
24+
%9 = arith.addi %3, %c3_i32 : i32
25+
%10 = arith.divsi %9, %c4_i32 : i32
26+
%11:3 = scf.for %arg8 = %c0_i32 to %c4_i32 step %c1_i32 iter_args(%arg9 = %cst_1, %arg10 = %cst_0, %arg11 = %cst) -> (f32, f32, tensor<32xf32>) : i32 {
27+
%20 = arith.muli %10, %arg8 : i32
28+
%21 = arith.addi %20, %10 : i32
29+
%22 = arith.minsi %21, %3 : i32
30+
%23 = arith.cmpi sgt, %22, %20 : i32
31+
%24:3 = scf.if %23 -> (f32, f32, tensor<32xf32>) {
32+
%25 = arith.muli %arg8, %arg5 : i32
33+
%26 = arith.index_cast %25 : i32 to index
34+
%27 = arith.addi %7, %26 : index
35+
%28 = tts.make_tptr %arg0 to sizes: [32], strides: [1], offsets: [%27], shape: [0], order: [] : <f32> to tensor<32x!tt.ptr<f32>>
36+
%29 = "tts.load"(%28, %cst_1) <{operandSegmentSizes = array<i32: 1, 0, 1>, static_mask_dims = array<i64: 32>}> : (tensor<32x!tt.ptr<f32>>, f32) -> tensor<32xf32>
37+
%30 = tt.addptr %arg0, %8 : !tt.ptr<f32>, i32
38+
%31 = tt.addptr %30, %25 : !tt.ptr<f32>, i32
39+
%32 = tt.load %31 : !tt.ptr<f32>
40+
%33 = arith.maxnumf %32, %arg10 : f32
41+
%34 = arith.subf %arg10, %33 : f32
42+
%35 = math.exp %34 : f32
43+
%36 = tt.splat %35 : f32 -> tensor<32xf32>
44+
%37 = arith.mulf %arg11, %36 : tensor<32xf32>
45+
%38 = arith.subf %32, %33 : f32
46+
%39 = math.exp %38 : f32
47+
%40 = tt.splat %39 : f32 -> tensor<32xf32>
48+
%41 = arith.mulf %40, %29 : tensor<32xf32>
49+
%42 = arith.addf %37, %41 : tensor<32xf32>
50+
%43 = arith.mulf %arg9, %35 : f32
51+
%44 = arith.addf %43, %39 : f32
52+
scf.yield %44, %33, %42 : f32, f32, tensor<32xf32>
53+
} else {
54+
scf.yield %arg9, %arg10, %arg11 : f32, f32, tensor<32xf32>
55+
}
56+
scf.yield %24#0, %24#1, %24#2 : f32, f32, tensor<32xf32>
57+
}
58+
%12 = arith.muli %0, %arg6 : i32
59+
%13 = arith.index_cast %12 : i32 to index
60+
%14 = arith.muli %1, %arg7 : i32
61+
%15 = arith.index_cast %14 : i32 to index
62+
%16 = arith.addi %13, %15 : index
63+
%17 = tts.make_tptr %arg1 to sizes: [32], strides: [1], offsets: [%16], shape: [0], order: [] : <f32> to tensor<32x!tt.ptr<f32>>
64+
%18 = tt.splat %11#0 : f32 -> tensor<32xf32>
65+
%19 = arith.divf %11#2, %18 : tensor<32xf32>
66+
"tts.store"(%17, %19) <{static_mask_dims = array<i64: 32>}> : (tensor<32x!tt.ptr<f32>>, tensor<32xf32>) -> ()
67+
tt.return
68+
}
69+
}
70+
71+
// CHECK-NOT: tt.addptr
72+
// CHECK-NOT: tt.load
73+
// CHECK-NOT: tt.store

0 commit comments

Comments
 (0)