diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp --- a/llvm/lib/IR/Type.cpp +++ b/llvm/lib/IR/Type.cpp @@ -95,15 +95,8 @@ // else is not lossless. Conservatively assume we can't losslessly convert // between pointers with different address spaces. if (auto *PTy = dyn_cast(this)) { - if (auto *OtherPTy = dyn_cast(Ty)) { - // Don't bitcast "load <256 x i32>, <256 x i32>*" to - // "load x86_amx, x86_amx*", because we don't have a corresponding - // instruction to load x86_amx. Doing the transform causes trouble - // to lower "load x86_amx" instruction in backend. - if (OtherPTy->getElementType()->isX86_AMXTy()) - return false; + if (auto *OtherPTy = dyn_cast(Ty)) return PTy->getAddressSpace() == OtherPTy->getAddressSpace(); - } return false; } return false; // Other types have no identity values @@ -617,7 +610,8 @@ bool ArrayType::isValidElementType(Type *ElemTy) { return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy() && - !ElemTy->isTokenTy() && !isa(ElemTy); + !ElemTy->isTokenTy() && !ElemTy->isX86_AMXTy() && + !isa(ElemTy); } //===----------------------------------------------------------------------===// @@ -718,7 +712,8 @@ bool PointerType::isValidElementType(Type *ElemTy) { return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && - !ElemTy->isMetadataTy() && !ElemTy->isTokenTy(); + !ElemTy->isMetadataTy() && !ElemTy->isTokenTy() && + !ElemTy->isX86_AMXTy(); } bool PointerType::isLoadableOrStorableType(Type *ElemTy) { diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2444,6 +2444,8 @@ "Function takes metadata but isn't an intrinsic", &Arg, &F); Assert(!Arg.getType()->isTokenTy(), "Function takes token but isn't an intrinsic", &Arg, &F); + Assert(!Arg.getType()->isX86_AMXTy(), + "Function takes x86_amx but isn't an intrinsic", &Arg, &F); } // Check that swifterror argument is only used by loads and stores. @@ -2453,9 +2455,12 @@ ++i; } - if (!isLLVMdotName) + if (!isLLVMdotName) { Assert(!F.getReturnType()->isTokenTy(), "Functions returns a token but isn't an intrinsic", &F); + Assert(!F.getReturnType()->isX86_AMXTy(), + "Functions returns a x86_amx but isn't an intrinsic", &F); + } // Get the function metadata attachments. SmallVector, 4> MDs; @@ -3216,9 +3221,12 @@ } // Verify that indirect calls don't return tokens. - if (!Call.getCalledFunction()) + if (!Call.getCalledFunction()) { Assert(!FTy->getReturnType()->isTokenTy(), "Return type cannot be token for indirect call!"); + Assert(!FTy->getReturnType()->isX86_AMXTy(), + "Return type cannot be x86_amx for indirect call!"); + } if (Function *F = Call.getCalledFunction()) if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) @@ -4587,9 +4595,13 @@ // If the intrinsic takes MDNode arguments, verify that they are either global // or are local to *this* function. - for (Value *V : Call.args()) + for (Value *V : Call.args()) { if (auto *MD = dyn_cast(V)) visitMetadataAsValue(*MD, Call.getCaller()); + if (auto *Const = dyn_cast(V)) + Assert(!Const->getType()->isX86_AMXTy(), + "const x86_amx is not allowed in argument!"); + } switch (ID) { default: diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -2409,10 +2409,11 @@ Value *Addr = LI->getOperand(0); if (Addr == &CI || isa(Addr)) return nullptr; - // If there is any loss for the pointer bitcast, abandon. - auto *DestPtrTy = DestTy->getPointerTo(LI->getPointerAddressSpace()); - auto *SrcPtrTy = Addr->getType(); - if (!SrcPtrTy->canLosslesslyBitCastTo(DestPtrTy)) + // Don't tranform "load <256 x i32>, <256 x i32>*" to + // "load x86_amx, x86_amx*", because x86_amx* is invalid. + // TODO: Remove this check when bitcast between vector and x86_amx + // is replaced with a specific intrinsic. + if (DestTy->isX86_AMXTy()) return nullptr; if (LI->hasOneUse() && LI->isSimple()) continue; diff --git a/llvm/test/Verifier/x86_amx1.ll b/llvm/test/Verifier/x86_amx1.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/x86_amx1.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +@GV = dso_local global [10 x x86_amx] zeroinitializer, align 16 +; CHECK: invalid array element type diff --git a/llvm/test/Verifier/x86_amx2.ll b/llvm/test/Verifier/x86_amx2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/x86_amx2.ll @@ -0,0 +1,9 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define dso_local void @f() { +entry: + %a.addr = alloca <2 x x86_amx>, align 4 + ret void +} + +; CHECK: invalid vector element type diff --git a/llvm/test/Verifier/x86_amx3.ll b/llvm/test/Verifier/x86_amx3.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/x86_amx3.ll @@ -0,0 +1,8 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define void @f(x86_amx %A, x86_amx %B) { +entry: + alloca x86_amx +; CHECK: invalid type for alloca + ret void +} diff --git a/llvm/test/Verifier/x86_amx4.ll b/llvm/test/Verifier/x86_amx4.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/x86_amx4.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +@GV = external global x86_amx +; CHECK: invalid type for global variable diff --git a/llvm/test/Verifier/x86_amx5.ll b/llvm/test/Verifier/x86_amx5.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/x86_amx5.ll @@ -0,0 +1,7 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define void @f(x86_amx %A) { +entry: + ret void +} +; CHECK: Function takes x86_amx but isn't an intrinsic diff --git a/llvm/test/Verifier/x86_amx6.ll b/llvm/test/Verifier/x86_amx6.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/x86_amx6.ll @@ -0,0 +1,7 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define x86_amx @f() { +entry: + ret x86_amx undef +} +; CHECK: Functions returns a x86_amx but isn't an intrinsic diff --git a/llvm/test/Verifier/x86_amx7.ll b/llvm/test/Verifier/x86_amx7.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/x86_amx7.ll @@ -0,0 +1,8 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define void @f() { +entry: + call x86_amx () undef () + ret void +} +; CHECK: Return type cannot be x86_amx for indirect call! diff --git a/llvm/test/Verifier/x86_amx8.ll b/llvm/test/Verifier/x86_amx8.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/x86_amx8.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +@GV = dso_local global x86_amx* null +; CHECK: pointer to this type is invalid diff --git a/llvm/test/Verifier/x86_amx9.ll b/llvm/test/Verifier/x86_amx9.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/x86_amx9.ll @@ -0,0 +1,12 @@ +; RUN: not llc %s -o /dev/null 2>&1 | FileCheck %s + +@buf = dso_local global [1024 x i8] zeroinitializer, align 16 + +define dso_local void @test_tile_init(i16 signext %row, i16 signext %col) { +entry: + tail call void @llvm.x86.tilestored64.internal(i16 %row, i16 %col, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @buf, i64 0, i64 0), i64 64, x86_amx bitcast (<256 x i32> to x86_amx)) + ret void +} +; CHECK: const x86_amx is not allowed in argument! + +declare void @llvm.x86.tilestored64.internal(i16, i16, i8*, i64, x86_amx)