Skip to content

Commit 62a555a

Browse files
committed
feat: implement tt.trans in triton tensor module
1 parent 51ca1ed commit 62a555a

1 file changed

Lines changed: 146 additions & 0 deletions

File tree

compiler/rustc_mlir/src/triton/tensor.rs

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,48 @@ pub fn broadcast<'ctx>(
17681768
.map_err(|e| Error::InvalidType { msg: format!("failed to build tt.broadcast: {e}") })
17691769
}
17701770

1771+
/// Build a `tt.trans` operation.
1772+
///
1773+
/// Rearranges the dimensions of a tensor according to a permutation order.
1774+
/// For example, a `tensor<1x2x4xf32>` transposed with `order = [2, 0, 1]`
1775+
/// produces a `tensor<4x1x2xf32>`. This op implements both `tl.trans()` and
1776+
/// `tl.permute()`.
1777+
///
1778+
/// Traits: `Pure`, `SameOperandsAndResultElementType`.
1779+
///
1780+
/// # Arguments
1781+
/// * `src` – source tensor to transpose.
1782+
/// * `order` – permutation of dimension indices (length == tensor rank).
1783+
/// * `result_ty` – result tensor type (same element type, dimensions permuted
1784+
/// according to `order`).
1785+
///
1786+
/// # Example
1787+
///
1788+
/// ```text
1789+
/// // Swap the two dimensions of a 2-D tensor:
1790+
/// %1 = tt.trans %src {order = array<i32: 1, 0>} : tensor<4x8xf32> -> tensor<8x4xf32>
1791+
/// ```
1792+
///
1793+
/// Assembly format (from TableGen):
1794+
/// ```text
1795+
/// $src attr-dict `:` type($src) `->` type($result)
1796+
/// ```
1797+
pub fn trans<'ctx>(
1798+
context: &'ctx Context,
1799+
location: Location<'ctx>,
1800+
src: Value<'ctx, '_>,
1801+
order: &[i32],
1802+
result_ty: Type<'ctx>,
1803+
) -> Result<Operation<'ctx>, Error> {
1804+
let order_attr = DenseI32ArrayAttribute::new(context, order);
1805+
OperationBuilder::new("tt.trans", location)
1806+
.add_operands(&[src])
1807+
.add_attributes(&[(Identifier::new(context, "order"), Attribute::from(order_attr))])
1808+
.add_results(&[result_ty])
1809+
.build()
1810+
.map_err(|e| Error::InvalidType { msg: format!("failed to build tt.trans: {e}") })
1811+
}
1812+
17711813
/// Build a `tt.bitcast` operation.
17721814
///
17731815
/// Reinterprets the bits of `src` as `result_ty` without any conversion.
@@ -6149,6 +6191,110 @@ mod tests {
61496191
assert!(output.contains("tensor<2x32x4xf32>"), "missing result tensor type:\n{output}");
61506192
}
61516193

6194+
/// Verify that `trans` emits the correct `tt.trans` IR for a 2-D swap.
6195+
///
6196+
/// Transposes `tensor<4x8xf32>` with order `[1, 0]` to `tensor<8x4xf32>`.
6197+
///
6198+
/// Expected assembly fragment:
6199+
/// ```text
6200+
/// %0 = tt.trans %arg0 {order = array<i32: 1, 0>} : tensor<4x8xf32> -> tensor<8x4xf32>
6201+
/// ```
6202+
#[test]
6203+
fn test_trans_2d() {
6204+
let context = create_test_context();
6205+
load_triton_dialect(&context);
6206+
6207+
let location = Location::unknown(&context);
6208+
let module = Module::new(location);
6209+
6210+
let f32_type = melior::ir::Type::float32(&context);
6211+
let src_ty: Type = tensor_type(&[4, 8], f32_type).into();
6212+
let result_ty: Type = tensor_type(&[8, 4], f32_type).into();
6213+
6214+
let func_op = create_func(
6215+
&context,
6216+
location,
6217+
"test_trans_2d",
6218+
"public",
6219+
&[src_ty],
6220+
&[result_ty],
6221+
0,
6222+
)
6223+
.unwrap();
6224+
6225+
let block = Block::new(&[(src_ty, location)]);
6226+
let src: Value = block.argument(0).unwrap().into();
6227+
6228+
let trans_op: Operation<'_> =
6229+
super::trans(&context, location, src, &[1, 0], result_ty).unwrap();
6230+
let result_val: Value = trans_op.result(0).unwrap().into();
6231+
let ret_op = ReturnOperation::builder(&context, location).srcs(&[result_val]).build();
6232+
6233+
block.append_operation(trans_op);
6234+
block.append_operation(ret_op.into());
6235+
func_op.body().unwrap().append_block(block);
6236+
module.body().append_operation(func_op.into());
6237+
6238+
let output = module.as_operation().to_string();
6239+
6240+
assert!(output.contains("tt.trans"), "missing op mnemonic:\n{output}");
6241+
assert!(output.contains("tensor<4x8xf32>"), "missing src tensor type:\n{output}");
6242+
assert!(output.contains("tensor<8x4xf32>"), "missing result tensor type:\n{output}");
6243+
assert!(output.contains("order"), "missing order attribute:\n{output}");
6244+
}
6245+
6246+
/// Verify that `trans` emits the correct `tt.trans` IR for a 3-D permutation.
6247+
///
6248+
/// Permutes `tensor<1x2x4xf32>` with order `[2, 0, 1]` to `tensor<4x1x2xf32>`.
6249+
///
6250+
/// Expected assembly fragment:
6251+
/// ```text
6252+
/// %0 = tt.trans %arg0 {order = array<i32: 2, 0, 1>} : tensor<1x2x4xf32> -> tensor<4x1x2xf32>
6253+
/// ```
6254+
#[test]
6255+
fn test_trans_3d_permute() {
6256+
let context = create_test_context();
6257+
load_triton_dialect(&context);
6258+
6259+
let location = Location::unknown(&context);
6260+
let module = Module::new(location);
6261+
6262+
let f32_type = melior::ir::Type::float32(&context);
6263+
let src_ty: Type = tensor_type(&[1, 2, 4], f32_type).into();
6264+
let result_ty: Type = tensor_type(&[4, 1, 2], f32_type).into();
6265+
6266+
let func_op = create_func(
6267+
&context,
6268+
location,
6269+
"test_trans_3d_permute",
6270+
"public",
6271+
&[src_ty],
6272+
&[result_ty],
6273+
0,
6274+
)
6275+
.unwrap();
6276+
6277+
let block = Block::new(&[(src_ty, location)]);
6278+
let src: Value = block.argument(0).unwrap().into();
6279+
6280+
let trans_op: Operation<'_> =
6281+
super::trans(&context, location, src, &[2, 0, 1], result_ty).unwrap();
6282+
let result_val: Value = trans_op.result(0).unwrap().into();
6283+
let ret_op = ReturnOperation::builder(&context, location).srcs(&[result_val]).build();
6284+
6285+
block.append_operation(trans_op);
6286+
block.append_operation(ret_op.into());
6287+
func_op.body().unwrap().append_block(block);
6288+
module.body().append_operation(func_op.into());
6289+
6290+
let output = module.as_operation().to_string();
6291+
6292+
assert!(output.contains("tt.trans"), "missing op mnemonic:\n{output}");
6293+
assert!(output.contains("tensor<1x2x4xf32>"), "missing src tensor type:\n{output}");
6294+
assert!(output.contains("tensor<4x1x2xf32>"), "missing result tensor type:\n{output}");
6295+
assert!(output.contains("order"), "missing order attribute:\n{output}");
6296+
}
6297+
61526298
/// Verify that `bitcast` emits the correct `tt.bitcast` IR for a scalar cast.
61536299
///
61546300
/// Casts `f32` to `i32` (same bitwidth, scalar).

0 commit comments

Comments
 (0)