brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.1 KiB · 3f2fff9 Raw
152 lines · plain
1// RUN: mlir-opt %s --gpu-lower-to-xevm-pipeline="xegpu-op-level=workgroup" \2// RUN: | mlir-runner \3// RUN:   --shared-libs=%mlir_levelzero_runtime \4// RUN:   --shared-libs=%mlir_runner_utils \5// RUN:   --entry-point-result=void \6// RUN: | FileCheck %s7 8#a = #xegpu.layout<sg_layout = [8, 4], sg_data = [32, 32], inst_data = [8, 16]>9#b = #xegpu.layout<sg_layout = [8, 4], sg_data = [32, 64], inst_data = [16, 16]>10#c = #xegpu.layout<sg_layout = [8, 4], sg_data = [32, 64], inst_data = [8, 16]>11#a_prefetch = #xegpu.layout<sg_layout = [32, 1], sg_data = [8, 32], inst_data = [8, 16]>12#b_prefetch = #xegpu.layout<sg_layout = [4, 8], sg_data = [8, 32], inst_data = [8, 16]>13module @gemm attributes {gpu.container_module} {14  func.func @test(%A: memref<256x256xf16>, %B: memref<256x256xf16>, %C: memref<256x256xf32>) -> memref<256x256xf32> attributes {llvm.emit_c_interface} {15    %c1 = arith.constant 1 : index16    %c4 = arith.constant 4 : index17    %c8 = arith.constant 8 : index18    %c16 = arith.constant 16 : index19    %c32 = arith.constant 32 : index20    %c64 = arith.constant 64 : index21    %c128 = arith.constant 128 : index22    %c512 = arith.constant 512 : index23    %A_gpu = gpu.alloc () : memref<256x256xf16>24    gpu.memcpy %A_gpu, %A : memref<256x256xf16>, memref<256x256xf16>25    %B_gpu = gpu.alloc () : memref<256x256xf16>26    gpu.memcpy %B_gpu, %B : memref<256x256xf16>, memref<256x256xf16>27    %C_gpu = gpu.alloc () : memref<256x256xf32>28    gpu.memcpy %C_gpu, %C : memref<256x256xf32>, memref<256x256xf32>29    // NOTE: Here we can't use [8, 64] wi threads following30    // the SG thread layout of [8, 4]. Because runtime will linearize31    // the x dimension first (we need y dimension to be linearized first).32    // So just use linearized thread layout of [512, 1] wi threads.33    gpu.launch_func  @test_kernel::@test_kernel blocks in (%c1, %c1, %c1) threads in (%c512, %c1, %c1) args(%A_gpu : memref<256x256xf16>, %B_gpu : memref<256x256xf16>, %C_gpu : memref<256x256xf32>)34    gpu.wait // Wait for the kernel to finish.35    gpu.memcpy %C, %C_gpu : memref<256x256xf32>, memref<256x256xf32>36    gpu.dealloc %A_gpu : memref<256x256xf16>37    gpu.dealloc %B_gpu : memref<256x256xf16>38    gpu.dealloc %C_gpu : memref<256x256xf32>39    return %C : memref<256x256xf32>40  }41 42  gpu.module @test_kernel   {43    gpu.func @test_kernel(%A: memref<256x256xf16>, %B: memref<256x256xf16>, %C: memref<256x256xf32>) kernel  {44      %c0 = arith.constant 0 : index45      %c1 = arith.constant 1 : index46      %c32 = arith.constant 32 : index47      %c64 = arith.constant 64 : index48      %c96 = arith.constant 96 : index49      %c256 = arith.constant 256 : index50      %c4096 = arith.constant 4096 : index51      %block_id_x = gpu.block_id x52      %block_id_y = gpu.block_id y53      %m = arith.muli %block_id_x, %c256 : index54      %n = arith.muli %block_id_y, %c256 : index55      %c_tdesc = xegpu.create_nd_tdesc %C : memref<256x256xf32> -> !xegpu.tensor_desc<256x256xf32, #c>56      %c_init_value = xegpu.load_nd %c_tdesc[%m, %n] : !xegpu.tensor_desc<256x256xf32, #c> -> vector<256x256xf32>57      %a_tdesc = xegpu.create_nd_tdesc %A : memref<256x256xf16> -> !xegpu.tensor_desc<256x32xf16, #a>58      %b_tdesc = xegpu.create_nd_tdesc %B : memref<256x256xf16> -> !xegpu.tensor_desc<32x256xf16, #b>59      // Prefetch A 3 times.60      %a_prefetch_tdesc = xegpu.create_nd_tdesc %A : memref<256x256xf16> -> !xegpu.tensor_desc<256x32xf16, #a_prefetch>61      xegpu.prefetch_nd %a_prefetch_tdesc[%m, %c0] : !xegpu.tensor_desc<256x32xf16, #a_prefetch>62      xegpu.prefetch_nd %a_prefetch_tdesc[%m, %c32] : !xegpu.tensor_desc<256x32xf16, #a_prefetch>63      xegpu.prefetch_nd %a_prefetch_tdesc[%m, %c64] : !xegpu.tensor_desc<256x32xf16, #a_prefetch>64       // Prefetch B 3 times.65      %b_prefetch_tdesc = xegpu.create_nd_tdesc %B : memref<256x256xf16> -> !xegpu.tensor_desc<32x256xf16, #b_prefetch>66      xegpu.prefetch_nd %b_prefetch_tdesc[%c0, %n] : !xegpu.tensor_desc<32x256xf16, #b_prefetch>67      xegpu.prefetch_nd %b_prefetch_tdesc[%c32, %n] : !xegpu.tensor_desc<32x256xf16, #b_prefetch>68      xegpu.prefetch_nd %b_prefetch_tdesc[%c64, %n] : !xegpu.tensor_desc<32x256xf16, #b_prefetch>69 70      %out = scf.for %k = %c0 to %c256 step %c3271        iter_args(%c_value = %c_init_value)72        -> (vector<256x256xf32>) {73        %a_value = xegpu.load_nd %a_tdesc[%m, %k]  : !xegpu.tensor_desc<256x32xf16, #a> -> vector<256x32xf16>74        %b_value = xegpu.load_nd %b_tdesc[%k, %n] : !xegpu.tensor_desc<32x256xf16, #b> -> vector<32x256xf16>75        // Prefetch next tiles.76        %prefetch_offset = arith.addi %k, %c96 : index77        xegpu.prefetch_nd %a_prefetch_tdesc[%m, %prefetch_offset] : !xegpu.tensor_desc<256x32xf16, #a_prefetch>78        xegpu.prefetch_nd %b_prefetch_tdesc[%prefetch_offset, %n] : !xegpu.tensor_desc<32x256xf16, #b_prefetch>79        %c_new_value = xegpu.dpas %a_value, %b_value, %c_value {layout_result_0 = #c}80          : vector<256x32xf16>, vector<32x256xf16>, vector<256x256xf32> -> vector<256x256xf32>81        scf.yield %c_new_value : vector<256x256xf32>82      }83      xegpu.store_nd %out, %c_tdesc[%m, %n] : vector<256x256xf32>, !xegpu.tensor_desc<256x256xf32, #c>84      gpu.return85    }86  }87 88  func.func @main() attributes {llvm.emit_c_interface} {89    %c0 = arith.constant 0 : index90    %c1 = arith.constant 1 : index91    %c1_f16 = arith.constant 1.0 : f1692    %c2_f16 = arith.constant 2.0 : f1693    %c256 = arith.constant 256 : index94    %cf_0 = arith.constant 0.0 : f1695    %cf_1 = arith.constant 1.0 : f1696    %A = memref.alloc() : memref<256x256xf16>97    %B = memref.alloc() : memref<256x256xf16>98    %C = memref.alloc() : memref<256x256xf32>99    %C_ref = memref.alloc() : memref<256x256xf32>100    %c_gen_int = arith.constant 0 : i1101    %cf_lower = arith.constant -0.5 : f32102    %cf_upper = arith.constant 0.5 : f32103    // Intialize matrix A ; A[i, j] = j104    scf.for %i = %c0 to %c256 step %c1 {105      scf.for %j = %c0 to %c256 step %c1 {106        %t = index.castu %j : index to i16107        %val = arith.uitofp %t : i16 to f16108        memref.store %val, %A[%i, %j] : memref<256x256xf16>109      }110    }111 112    // Initialize the B matrix113    // Make matrix B an identity matrix114    scf.for %i = %c0 to %c256 step %c1 {115      scf.for %j = %c0 to %c256 step %c1 {116        %i_i32 = index.castu %i : index to i32117        %j_i32 = index.castu %j : index to i32118        %i_j_same = arith.cmpi eq, %i_i32, %j_i32 : i32119 120        scf.if %i_j_same {121          memref.store %cf_1, %B[%i, %j] : memref<256x256xf16>122        } else {123          memref.store %cf_0, %B[%i, %j] : memref<256x256xf16>124        }125      }126    }127 128    // Initialize matrix C and C_ref ; C[i, j] = 0129    %c0_f32 = arith.constant 0.0 : f32130    scf.for %i = %c0 to %c256 step %c1 {131      scf.for %j = %c0 to %c256 step %c1 {132        memref.store %c0_f32, %C[%i, %j] : memref<256x256xf32>133        memref.store %c0_f32, %C_ref[%i, %j] : memref<256x256xf32>134      }135    }136 137    // Run GPU version.138    %2 = call @test(%A, %B, %C) : (memref<256x256xf16>, memref<256x256xf16>, memref<256x256xf32>) -> memref<256x256xf32>139    %gpu_result_cast = memref.cast %2 : memref<256x256xf32> to memref<*xf32>140    // CHECK: Unranked Memref base@ = 0x{{[0-9a-f]+}}141    // CHECK-COUNT-256: [0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,   36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,   49,   50,   51,   52,   53,   54,   55,   56,   57,   58,   59,   60,   61,   62,   63,   64,   65,   66,   67,   68,   69,   70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   80,   81,   82,   83,   84,   85,   86,   87,   88,   89,   90,   91,   92,   93,   94,   95,   96,   97,   98,   99,   100,   101,   102,   103,   104,   105,   106,   107,   108,   109,   110,   111,   112,   113,   114,   115,   116,   117,   118,   119,   120,   121,   122,   123,   124,   125,   126,   127,   128,   129,   130,   131,   132,   133,   134,   135,   136,   137,   138,   139,   140,   141,   142,   143,   144,   145,   146,   147,   148,   149,   150,   151,   152,   153,   154,   155,   156,   157,   158,   159,   160,   161,   162,   163,   164,   165,   166,   167,   168,   169,   170,   171,   172,   173,   174,   175,   176,   177,   178,   179,   180,   181,   182,   183,   184,   185,   186,   187,   188,   189,   190,   191,   192,   193,   194,   195,   196,   197,   198,   199,   200,   201,   202,   203,   204,   205,   206,   207,   208,   209,   210,   211,   212,   213,   214,   215,   216,   217,   218,   219,   220,   221,   222,   223,   224,   225,   226,   227,   228,   229,   230,   231,   232,   233,   234,   235,   236,   237,   238,   239,   240,   241,   242,   243,   244,   245,   246,   247,   248,   249,   250,   251,   252,   253,   254,   255]142    call @printMemrefF32(%gpu_result_cast) : (memref<*xf32>) -> ()143 144    memref.dealloc %A : memref<256x256xf16>145    memref.dealloc %B : memref<256x256xf16>146    memref.dealloc %C : memref<256x256xf32>147    memref.dealloc %C_ref : memref<256x256xf32>148    return149  }150  func.func private @printMemrefF32(memref<*xf32>) attributes {llvm.emit_c_interface}151}152