Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

149 lines
7.5 KiB
MLIR

// RUN: mlir-opt -test-xegpu-recover-temporary-layouts -split-input-file %s | FileCheck %s
// -----
// Test scf.for: Recovery should propagate layout from the store_nd consumer
// of the loop result back to the scf.for result, scf.yield operands, and
// the arith.constant init value. Tensor desc types start without layouts
// and only anchor ops (load_nd, store_nd, dpas) carry layout attributes.
gpu.module @test_for {
// CHECK-LABEL: gpu.func @for_basic
gpu.func @for_basic(%arg0: memref<8x128xf16>, %arg1: memref<128x16xf16>, %arg2: memref<8x16xf32>) {
%c0 = arith.constant 0 : index
%c128 = arith.constant 128 : index
%c16 = arith.constant 16 : index
// CHECK: xegpu.create_nd_tdesc
// CHECK-SAME: -> !xegpu.tensor_desc<8x16xf16, #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>>
%0 = xegpu.create_nd_tdesc %arg0 : memref<8x128xf16>
-> !xegpu.tensor_desc<8x16xf16>
// CHECK: xegpu.create_nd_tdesc
// CHECK-SAME: -> !xegpu.tensor_desc<16x16xf16, #xegpu.layout<lane_layout = [1, 16], lane_data = [2, 1]>>
%1 = xegpu.create_nd_tdesc %arg1 : memref<128x16xf16>
-> !xegpu.tensor_desc<16x16xf16>
// Recovery propagates layout from dpas (via store_nd) back to arith.constant.
// CHECK: arith.constant {layout_result_0 = #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>}
// CHECK-SAME: dense<0.000000e+00> : vector<8x16xf32>
%cst = arith.constant dense<0.000000e+00> : vector<8x16xf32>
// CHECK: scf.for
%2 = scf.for %arg3 = %c0 to %c128 step %c16
iter_args(%arg6 = %cst) -> (vector<8x16xf32>) {
%4 = xegpu.load_nd %0[%c0, %c0] {layout = #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>}
: !xegpu.tensor_desc<8x16xf16> -> vector<8x16xf16>
%5 = xegpu.load_nd %1[%c0, %c0] {layout = #xegpu.layout<lane_layout = [1, 16], lane_data = [2, 1]>}
: !xegpu.tensor_desc<16x16xf16> -> vector<16x16xf16>
%6 = xegpu.dpas %4, %5, %arg6
{layout_a = #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>,
layout_b = #xegpu.layout<lane_layout = [1, 16], lane_data = [2, 1]>,
layout_cd = #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>}
: vector<8x16xf16>, vector<16x16xf16>, vector<8x16xf32> -> vector<8x16xf32>
// Recovery propagates layout to scf.yield vector operand.
// CHECK: scf.yield {layout_operand_0 = #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>}
scf.yield %6
: vector<8x16xf32>
// Recovery sets layout_result_0 on the scf.for for the vector result.
// CHECK: layout_result_0 = #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>
}
// CHECK: xegpu.create_nd_tdesc
// CHECK-SAME: -> !xegpu.tensor_desc<8x16xf32, #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>>
%3 = xegpu.create_nd_tdesc %arg2 : memref<8x16xf32>
-> !xegpu.tensor_desc<8x16xf32>
xegpu.store_nd %2, %3[%c0, %c0] {layout = #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>}
: vector<8x16xf32>, !xegpu.tensor_desc<8x16xf32>
gpu.return
}
}
// -----
// Test scf.while: Recovery should propagate layout from the store_nd consumer
// of the while result back through scf.condition (which branches to parent).
// The scf.yield in the "do" region branches to the "before" region (not
// parent), so propagateRegionResultsToYieldOperands skips it.
gpu.module @test_while {
// CHECK-LABEL: gpu.func @while_basic
gpu.func @while_basic(%arg0: memref<1024xf32>, %arg1: memref<1024xf32>) {
%c1_i32 = arith.constant 1 : i32
%c10_i32 = arith.constant 10 : i32
%c0_i32 = arith.constant 0 : i32
// CHECK: xegpu.create_nd_tdesc
// CHECK-SAME: -> !xegpu.tensor_desc<256xf32, #xegpu.layout<sg_layout = [16], sg_data = [16]>>
%0 = xegpu.create_nd_tdesc %arg0 : memref<1024xf32>
-> !xegpu.tensor_desc<256xf32>
%1 = xegpu.load_nd %0[0] {layout = #xegpu.layout<sg_layout = [16], sg_data = [16]>}
: !xegpu.tensor_desc<256xf32> -> vector<256xf32>
// CHECK: xegpu.create_nd_tdesc
// CHECK-SAME: -> !xegpu.tensor_desc<256xf32, #xegpu.layout<sg_layout = [16], sg_data = [16]>>
%2 = xegpu.create_nd_tdesc %arg1 : memref<1024xf32>
-> !xegpu.tensor_desc<256xf32>
// CHECK: scf.while
%3:2 = scf.while (%arg2 = %1, %arg3 = %c0_i32)
: (vector<256xf32>, i32) -> (vector<256xf32>, i32) {
%4 = arith.cmpi slt, %arg3, %c10_i32 : i32
// Recovery propagates layout to scf.condition vector operand.
// CHECK: scf.condition
// CHECK-SAME: {layout_operand_1 = #xegpu.layout<sg_layout = [16], sg_data = [16]>}
scf.condition(%4) %arg2, %arg3 : vector<256xf32>, i32
} do {
^bb0(%arg2: vector<256xf32>, %arg3: i32):
xegpu.store_nd %arg2, %2[0] {layout = #xegpu.layout<sg_layout = [16], sg_data = [16]>}
: vector<256xf32>, !xegpu.tensor_desc<256xf32>
%4 = arith.addi %arg3, %c1_i32 : i32
%6 = xegpu.load_nd %0[256] {layout = #xegpu.layout<sg_layout = [16], sg_data = [16]>}
: !xegpu.tensor_desc<256xf32> -> vector<256xf32>
// Recovery propagates layout to scf.yield in the "do" region via
// sibling region propagation (from "before" region arg back to "do" yield).
// CHECK: scf.yield {layout_operand_0 = #xegpu.layout<sg_layout = [16], sg_data = [16]>}
scf.yield %6, %4 : vector<256xf32>, i32
// Recovery sets layout_result_0 on the scf.while for the vector result.
// CHECK: } attributes {layout_operand_0 = #xegpu.layout<sg_layout = [16], sg_data = [16]>,
// CHECK-SAME: layout_result_0 = #xegpu.layout<sg_layout = [16], sg_data = [16]>}
}
xegpu.store_nd %3#0, %2[0] {layout = #xegpu.layout<sg_layout = [16], sg_data = [16]>}
: vector<256xf32>, !xegpu.tensor_desc<256xf32>
gpu.return
}
}
// -----
// Test scf.if: Recovery should propagate layout from the dpas consumer of the
// if result back to the scf.if result and both yield operands.
gpu.module @test_if {
// CHECK-LABEL: gpu.func @if_basic
gpu.func @if_basic(
%arg0: !xegpu.tensor_desc<8x16xf16>,
%arg1: !xegpu.tensor_desc<16x16xf16>,
%arg2: i1,
%arg3: !xegpu.tensor_desc<8x16xf32>) {
%0 = xegpu.load_nd %arg0[0, 0] {layout = #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>}
: !xegpu.tensor_desc<8x16xf16> -> vector<8x16xf16>
// CHECK: scf.if
%1 = scf.if %arg2 -> (vector<16x16xf16>) {
%3 = xegpu.load_nd %arg1[0, 0] {layout = #xegpu.layout<lane_layout = [1, 16], lane_data = [2, 1]>}
: !xegpu.tensor_desc<16x16xf16>
-> vector<16x16xf16>
// Recovery propagates layout to scf.yield operand in "then" region.
// CHECK: scf.yield {layout_operand_0 = #xegpu.layout<lane_layout = [1, 16], lane_data = [2, 1]>}
scf.yield %3 : vector<16x16xf16>
} else {
%3 = xegpu.load_nd %arg1[0, 0] {layout = #xegpu.layout<lane_layout = [1, 16], lane_data = [2, 1]>}
: !xegpu.tensor_desc<16x16xf16>
-> vector<16x16xf16>
// Recovery propagates layout to scf.yield operand in "else" region.
// CHECK: scf.yield {layout_operand_0 = #xegpu.layout<lane_layout = [1, 16], lane_data = [2, 1]>}
scf.yield %3 : vector<16x16xf16>
// Recovery sets layout_result_0 on the scf.if for the vector result.
// CHECK: } {layout_result_0 = #xegpu.layout<lane_layout = [1, 16], lane_data = [2, 1]>}
}
%2 = xegpu.dpas %0, %1
{layout_a = #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>,
layout_b = #xegpu.layout<lane_layout = [1, 16], lane_data = [2, 1]>,
layout_cd = #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>}
: vector<8x16xf16>, vector<16x16xf16> -> vector<8x16xf32>
xegpu.store_nd %2, %arg3[0, 0] {layout = #xegpu.layout<lane_layout = [1, 16], lane_data = [1, 1]>}
: vector<8x16xf32>, !xegpu.tensor_desc<8x16xf32>
gpu.return
}
}