[Matrix] Tighten LangRef definitions and Verifier checks.

This tightens the matrix intrinsic definitions in LLVM LangRef and adds
correspondings checks to the IR Verifier.

Differential Revision: https://reviews.llvm.org/D83477
This commit is contained in:
Sjoerd Meijer 2020-07-09 13:30:50 +01:00
parent 7a1bcf9f9a
commit f4d29d6e8c
3 changed files with 217 additions and 61 deletions

View File

@ -15524,6 +15524,7 @@ The argument to this intrinsic must be a vector of floating-point values.
Syntax:
"""""""
This is an overloaded intrinsic.
::
@ -15548,17 +15549,20 @@ Matrix Intrinsics
-----------------
Operations on matrixes requiring shape information (like number of rows/columns
or the memory layout) can be expressed using the matrix intrinsics. Matrixes are
embedded in a flat vector and the intrinsics take the dimensions as arguments.
Currently column-major layout is assumed. The intrinsics support both integer
and floating point matrixes.
or the memory layout) can be expressed using the matrix intrinsics. These
intrinsics require matrix dimensions to be passed as immediate arguments, and
matrixes are passed and returned as vectors. This means that for a ``R`` x
``C`` matrix, element ``i`` of column ``j`` is at index ``j * R + i`` in the
corresponding vector, with indices starting at 0. Currently column-major layout
is assumed. The intrinsics support both integer and floating point matrixes.
'``llvm.matrix.transpose.*``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
This is an overloaded intrinsic.
::
@ -15567,21 +15571,24 @@ Syntax:
Overview:
"""""""""
The '``llvm.matrix.transpose.*``' intrinsic treats %In as containing a matrix
with <Rows> rows and <Cols> columns and returns the transposed matrix embedded in
the result vector.
The '``llvm.matrix.transpose.*``' intrinsics treat %In as a <Rows> x <Cols> matrix
and return the transposed matrix in the result vector.
Arguments:
""""""""""
The <Rows> and <Cols> arguments must be constant integers. The vector argument
%In and the returned vector must have <Rows> * <Cols> elements.
First argument %In is vector that corresponds to a <Rows> x <Cols> matrix.
Thus, arguments <Rows> and <Cols> correspond to the number of rows and columns,
respectively, and must be positive, constant integers. The returned vector must
have <Rows> * <Cols> elements, and have the same float or integer element type
as %In.
'``llvm.matrix.multiply.*``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
This is an overloaded intrinsic.
::
@ -15590,18 +15597,19 @@ Syntax:
Overview:
"""""""""
The '``llvm.matrix.multiply.*``' intrinsic treats %A as a matrix with <OuterRows>
rows and <Inner> columns, %B as a matrix with <Inner> rows and <OuterColumns>
columns and multiplies them. The result matrix is returned embedded in the
result vector.
The '``llvm.matrix.multiply.*``' intrinsics treat %A as a <OuterRows> x <Inner>
matrix, %B as a <Inner> x <OuterColumns> matrix, and multiplies them. The result
matrix is returned in the result vector.
Arguments:
""""""""""
The <OuterRows>, <Inner> and <OuterColumns> arguments must be constant
integers. The vector argument %A must have <OuterRows> * <Inner> elements, %B
must have <Inner> * <OuterColumns> elements and the returned vector must have
<OuterRows> * <OuterColumns> elements.
The first vector argument %A corresponds to a matrix with <OuterRows> * <Inner>
elements, and the second argument %B to a matrix with <Inner> * <OuterColumns>
elements. Arguments <OuterRows>, <Inner> and <OuterColumns> must be positive,
constant integers. The returned vector must have <OuterRows> * <OuterColumns>
elements. Vectors %A, %B, and the returned vector all have the same float or
integer element type.
'``llvm.matrix.column.major.load.*``' Intrinsic
@ -15609,6 +15617,7 @@ must have <Inner> * <OuterColumns> elements and the returned vector must have
Syntax:
"""""""
This is an overloaded intrinsic.
::
@ -15618,22 +15627,26 @@ Syntax:
Overview:
"""""""""
The '``llvm.matrix.column.major.load.*``' intrinsic loads a matrix with <Rows>
rows and <Cols> columns, using a stride of %Stride between columns. For two
consecutive columns A and B, %Stride refers to the distance (the number of
elements) between the start of column A and the start of column B. The result
matrix is returned embedded in the result vector. This allows for convenient
loading of sub matrixes. If <IsVolatile> is true, the intrinsic is considered
a :ref:`volatile memory access <volatile>`.
If the %Ptr argument is known to be aligned to some boundary, this can be
specified as an attribute on the argument.
The '``llvm.matrix.column.major.load.*``' intrinsics load a <Rows> x <Cols>
matrix using a stride of %Stride to compute the start address of the different
columns. This allows for convenient loading of sub matrixes. If <IsVolatile>
is true, the intrinsic is considered a :ref:`volatile memory access
<volatile>`. The result matrix is returned in the result vector. If the %Ptr
argument is known to be aligned to some boundary, this can be specified as an
attribute on the argument.
Arguments:
""""""""""
The <IsVolatile>, <Rows> and <Cols> arguments must be constant integers. The
returned vector must have <Rows> * <Cols> elements. %Stride must be >= <Rows>.
The first argument %Ptr is a pointer type to the returned vector type, and
correponds to the start address to load from. The second argument %Stride is a
postive, constant integer with %Stride ``>=`` <Rows>. %Stride is used to compute
the column memory addresses. I.e., for a column ``C``, its start memory
addresses is calculated with %Ptr + ``C`` * %Stride. The third Argument
<IsVolatile> is a boolean value. The fourth and fifth arguments, <Rows> and
<Cols>, correspond to the number of rows and columns, respectively, and must be
positive, constant integers. The returned vector must have <Rows> * <Cols>
elements.
The :ref:`align <attr_align>` parameter attribute can be provided
for the %Ptr arguments.
@ -15653,12 +15666,10 @@ Syntax:
Overview:
"""""""""
The '``llvm.matrix.column.major.store.*``' intrinsic stores the matrix with
<Rows> rows and <Cols> columns embedded in %In, using a stride of %Stride
between columns. For two consecutive columns A and B, %Stride refers to the
distance (the number of elements) between the start of column A and the start
of column B. If <IsVolatile> is true, the intrinsic is considered a
:ref:`volatile memory access <volatile>`.
The '``llvm.matrix.column.major.store.*``' intrinsics store the <Rows> x <Cols>
matrix in %In to memory using a stride of %Stride between columns. If
<IsVolatile> is true, the intrinsic is considered a :ref:`volatile memory
access <volatile>`.
If the %Ptr argument is known to be aligned to some boundary, this can be
specified as an attribute on the argument.
@ -15666,8 +15677,15 @@ specified as an attribute on the argument.
Arguments:
""""""""""
The <IsVolatile>, <Rows>, <Cols> arguments must be constant integers. The
vector argument %In must have <Rows> * <Cols> elements. %Stride must be >= <Rows>.
The first argument %In is a vector that corresponds to a <Rows> x <Cols> matrix
to be stored to memory. The second argument %Ptr is a pointer to the vector
type of %In, and is the start address of the matrix in memory. The third
argument %Stride is a positive, constant integer with %Stride ``>=`` <Rows>.
%Stride is used to compute the column memory addresses. I.e., for a column
``C``, its start memory addresses is calculated with %Ptr + ``C`` * %Stride.
The fourth argument <IsVolatile> is a boolean value. The arguments <Rows> and
<Cols> correspond to the number of rows and columns, respectively, and must be
positive, constant integers.
The :ref:`align <attr_align>` parameter attribute can be provided
for the %Ptr arguments.

View File

@ -5006,36 +5006,77 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
case Intrinsic::matrix_transpose:
case Intrinsic::matrix_column_major_load:
case Intrinsic::matrix_column_major_store: {
Function *IF = Call.getCalledFunction();
ConstantInt *Stride = nullptr;
ConstantInt *NumRows;
ConstantInt *NumColumns;
VectorType *TypeToCheck;
VectorType *ResultTy;
Type *Op0ElemTy = nullptr;
Type *Op1ElemTy = nullptr;
switch (ID) {
case Intrinsic::matrix_multiply:
NumRows = cast<ConstantInt>(Call.getArgOperand(2));
NumColumns = cast<ConstantInt>(Call.getArgOperand(4));
TypeToCheck = cast<VectorType>(Call.getType());
ResultTy = cast<VectorType>(Call.getType());
Op0ElemTy =
cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType();
Op1ElemTy =
cast<VectorType>(Call.getArgOperand(1)->getType())->getElementType();
break;
case Intrinsic::matrix_transpose:
NumRows = cast<ConstantInt>(Call.getArgOperand(1));
NumColumns = cast<ConstantInt>(Call.getArgOperand(2));
TypeToCheck = cast<VectorType>(Call.getType());
ResultTy = cast<VectorType>(Call.getType());
Op0ElemTy =
cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType();
break;
case Intrinsic::matrix_column_major_load:
case Intrinsic::matrix_column_major_load: {
Stride = dyn_cast<ConstantInt>(Call.getArgOperand(1));
NumRows = cast<ConstantInt>(Call.getArgOperand(3));
NumColumns = cast<ConstantInt>(Call.getArgOperand(4));
TypeToCheck = cast<VectorType>(Call.getType());
ResultTy = cast<VectorType>(Call.getType());
auto *VecTy = cast<VectorType>(
cast<PointerType>(Call.getArgOperand(0)->getType())->getElementType());
Op0ElemTy = VecTy->getElementType();
}
break;
case Intrinsic::matrix_column_major_store:
case Intrinsic::matrix_column_major_store: {
Stride = dyn_cast<ConstantInt>(Call.getArgOperand(2));
NumRows = cast<ConstantInt>(Call.getArgOperand(4));
NumColumns = cast<ConstantInt>(Call.getArgOperand(5));
TypeToCheck = cast<VectorType>(Call.getArgOperand(0)->getType());
ResultTy = cast<VectorType>(Call.getArgOperand(0)->getType());
Op0ElemTy =
cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType();
auto *VecTy = cast<VectorType>(
cast<PointerType>(Call.getArgOperand(1)->getType())->getElementType());
Op1ElemTy = VecTy->getElementType();
}
break;
default:
llvm_unreachable("unexpected intrinsic");
}
Assert(TypeToCheck->getNumElements() ==
Assert(ResultTy->getElementType()->isIntegerTy() ||
ResultTy->getElementType()->isFloatingPointTy(),
"Result type must be an integer or floating-point type!", IF);
Assert(ResultTy->getElementType() == Op0ElemTy,
"Vector element type mismatch of the result and first operand "
"vector!", IF);
if (Op1ElemTy)
Assert(ResultTy->getElementType() == Op1ElemTy,
"Vector element type mismatch of the result and second operand "
"vector!", IF);
Assert(ResultTy->getNumElements() ==
NumRows->getZExtValue() * NumColumns->getZExtValue(),
"result of a matrix operation does not fit in the returned vector");
"Result of a matrix operation does not fit in the returned vector!");
if (Stride)
Assert(Stride->getZExtValue() >= NumRows->getZExtValue(),
"Stride must be greater or equal than the number of rows!", IF);
break;
}
};

View File

@ -3,9 +3,9 @@
declare <4 x float> @llvm.matrix.transpose.v4f32(<4 x float>, i32, i32)
define <4 x float> @transpose(<4 x float> %m, i32 %arg) {
; CHECK: assembly parsed, but does not verify as correct!
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: immarg operand has non-immediate parameter
; CHECK-NEXT: i32 %arg
; CHECK-NEXT: %result.3 = call <4 x float> @llvm.matrix.transpose.v4f32(<4 x float> %result.2, i32 %arg, i32 2)
@ -22,9 +22,9 @@ define <4 x float> @transpose(<4 x float> %m, i32 %arg) {
declare <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4f32(<4 x float>, <4 x float>, i32, i32, i32)
define <4 x float> @multiply(<4 x float> %m, i32 %arg) {
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: immarg operand has non-immediate parameter
; CHECK-NEXT: i32 %arg
; CHECK-NEXT: %result.3 = call <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4f32(<4 x float> %result.2, <4 x float> %m, i32 %arg, i32 2, i32 1)
@ -38,9 +38,9 @@ define <4 x float> @multiply(<4 x float> %m, i32 %arg) {
declare <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4f32(<4 x float>*, i64, i1, i32, i32)
declare <6 x float> @llvm.matrix.column.major.load.v6f32.p0v6f32(<6 x float>*, i64, i1, i32, i32)
define <4 x float> @column.major_load(<4 x float>* %m, <6 x float>* %n, i32 %arg) {
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: immarg operand has non-immediate parameter
; CHECK-NEXT: i32 %arg
; CHECK-NEXT: %result.3 = call <6 x float> @llvm.matrix.column.major.load.v6f32.p0v6f32(<6 x float>* %n, i64 2, i1 true, i32 3, i32 %arg)
@ -54,13 +54,110 @@ define <4 x float> @column.major_load(<4 x float>* %m, <6 x float>* %n, i32 %arg
declare void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float>, <4 x float>*, i64, i1, i32, i32)
declare void @llvm.matrix.column.major.store.v6f32.p0v6f32(<6 x float>, <6 x float>*, i64, i1, i32, i32)
define void @column.major_store(<4 x float>* %m, <6 x float>* %n, i64 %arg) {
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: result of a matrix operation does not fit in the returned vector
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector!
call void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float> zeroinitializer, <4 x float>* %m, i64 0, i1 false, i32 0, i32 0)
call void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float> zeroinitializer, <4 x float>* %m, i64 2, i1 false, i32 1, i32 2)
call void @llvm.matrix.column.major.store.v6f32.p0v6f32(<6 x float> zeroinitializer, <6 x float>* %n, i64 2, i1 false, i32 3, i32 3)
call void @llvm.matrix.column.major.store.v6f32.p0v6f32(<6 x float> zeroinitializer, <6 x float>* %n, i64 %arg, i1 false, i32 3, i32 3)
ret void
}
declare <4 x float> @llvm.matrix.transpose.v4f32.v4i32(<4 x i32>, i32, i32)
declare <4 x i32> @llvm.matrix.transpose.v4i32.v4f32(<4 x float>, i32, i32)
define <4 x float> @transpose_mixed_types(<4 x float> %fvec, <4 x i32> %ivec, i32 %arg) {
;
; CHECK-NEXT: Intrinsic has incorrect argument type!
; CHECK-NEXT: <4 x float> (<4 x i32>, i32, i32)* @llvm.matrix.transpose.v4f32.v4i32
; CHECK-NEXT: Intrinsic has incorrect argument type!
; CHECK-NEXT: <4 x i32> (<4 x float>, i32, i32)* @llvm.matrix.transpose.v4i32.v4f32
;
%result.0 = call <4 x float> @llvm.matrix.transpose.v4f32.v4i32(<4 x i32> %ivec, i32 0, i32 0)
%result.1 = call <4 x i32> @llvm.matrix.transpose.v4i32.v4f32(<4 x float> %result.0, i32 3, i32 2)
ret <4 x float> %result.0
}
declare <4 x i32> @llvm.matrix.multiply.v4i32.v4f32.v4f32(<4 x float>, <4 x float>, i32, i32, i32)
declare <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4f32(<4 x i32>, <4 x float>, i32, i32, i32)
declare <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4i32(<4 x float>, <4 x i32>, i32, i32, i32)
declare <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4i32(<4 x i32>, <4 x i32>, i32, i32, i32)
define <4 x float> @multiply_mixed_types(<4 x i32> %ivec, <4 x float> %fvec, i32 %arg) {
;
; CHECK-NEXT: Vector element type mismatch of the result and first operand vector!
; CHECK-NEXT: <4 x i32> (<4 x float>, <4 x float>, i32, i32, i32)* @llvm.matrix.multiply.v4i32.v4f32.v4f32
; CHECK-NEXT: Vector element type mismatch of the result and first operand vector!
; CHECK-NEXT: <4 x float> (<4 x i32>, <4 x float>, i32, i32, i32)* @llvm.matrix.multiply.v4f32.v4i32.v4f32
; CHECK-NEXT: Vector element type mismatch of the result and second operand vector!
; CHECK-NEXT: <4 x float> (<4 x float>, <4 x i32>, i32, i32, i32)* @llvm.matrix.multiply.v4f32.v4f32.v4i32
; CHECK-NEXT: Vector element type mismatch of the result and first operand vector!
; CHECK-NEXT: <4 x float> (<4 x i32>, <4 x i32>, i32, i32, i32)* @llvm.matrix.multiply.v4f32.v4i32.v4i32
;
%result.0 = call <4 x i32> @llvm.matrix.multiply.v4i32.v4f32.v4f32(<4 x float> %fvec, <4 x float> %fvec, i32 2, i32 2, i32 2)
%result.1 = call <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4f32(<4 x i32> %result.0, <4 x float> %fvec, i32 2, i32 2, i32 2)
%result.2 = call <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4i32(<4 x float> %fvec, <4 x i32> %ivec, i32 2, i32 2, i32 2)
%result.3 = call <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4i32(<4 x i32> %ivec, <4 x i32> %ivec, i32 2, i32 2, i32 2)
ret <4 x float> %result.3
}
declare <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4i32(<4 x i32>*, i64, i1, i32, i32)
declare <4 x i32> @llvm.matrix.column.major.load.v4i32.p0v4f32(<4 x float>*, i64, i1, i32, i32)
define <4 x float> @column.major_load_mixed_types(<4 x i32>* %m, <4 x float>* %n, i32 %arg) {
;
; CHECK-NEXT: Vector element type mismatch of the result and first operand vector!
; CHECK-NEXT: <4 x float> (<4 x i32>*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4f32.p0v4i32
; CHECK-NEXT: Vector element type mismatch of the result and first operand vector!
; CHECK-NEXT: <4 x i32> (<4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4i32.p0v4f32
;
%result.0 = call <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4i32(<4 x i32>* %m, i64 2, i1 false, i32 2, i32 2)
%result.1 = call <4 x i32> @llvm.matrix.column.major.load.v4i32.p0v4f32(<4 x float>* %n, i64 2, i1 false, i32 2, i32 2)
ret <4 x float> %result.0
}
declare void @llvm.matrix.column.major.store.v4i32.p0v4f32(<4 x i32>, <4 x float>*, i64, i1, i32, i32)
declare void @llvm.matrix.column.major.store.v4f32.p0v4i32(<4 x float>, <4 x i32>*, i64, i1, i32, i32)
define void @column.major_store_mixed_types(<4 x float>* %m, <4 x i32>* %n, i64 %arg) {
;
; CHECK-NEXT: Vector element type mismatch of the result and second operand vector!
; CHECK-NEXT: void (<4 x i32>, <4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4i32.p0v4f32
; CHECK-NEXT: Vector element type mismatch of the result and second operand vector!
; CHECK-NEXT: void (<4 x float>, <4 x i32>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4f32.p0v4i32
;
call void @llvm.matrix.column.major.store.v4i32.p0v4f32(<4 x i32> zeroinitializer, <4 x float>* %m, i64 2, i1 false, i32 2, i32 2)
call void @llvm.matrix.column.major.store.v4f32.p0v4i32(<4 x float> zeroinitializer, <4 x i32>* %n, i64 2, i1 false, i32 2, i32 2)
ret void
}
declare void @llvm.matrix.column.major.store.v4f32p0.p0v4f32(<4 x float*>, <4 x float>*, i64, i1, i32, i32)
define void @column.major_store_non_int_float_type(<4 x float>* %m, <4 x float>* %n, i64 %arg) {
;
; CHECK-NEXT: Result type must be an integer or floating-point type!
; CHECK-NEXT: void (<4 x float*>, <4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4p0f32.p0v4f32
;
call void @llvm.matrix.column.major.store.v4f32p0.p0v4f32(<4 x float*> zeroinitializer, <4 x float>* %n, i64 2, i1 false, i32 2, i32 2)
ret void
}
define <4 x float> @column.major_load_stride_too_small(<4 x float>* %m, i32 %arg) {
;
; CHECK-NEXT: Stride must be greater or equal than the number of rows!
; CHECK-NEXT: <4 x float> (<4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4f32.p0v4f32
;
%result.1 = call <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4f32(<4 x float>* %m, i64 1, i1 false, i32 2, i32 2)
ret <4 x float> %result.1
}
define void @column.major_store_stride_too_small(<4 x float>* %m, i64 %arg) {
;
; CHECK-NEXT: Stride must be greater or equal than the number of rows!
; CHECK-NEXT: void (<4 x float>, <4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4f32.p0v4f32
;
call void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float> zeroinitializer, <4 x float>* %m, i64 1, i1 false, i32 2, i32 2)
ret void
}