summaryrefslogtreecommitdiff
path: root/llvm/lib/IR/AutoUpgrade.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR/AutoUpgrade.cpp')
-rw-r--r--llvm/lib/IR/AutoUpgrade.cpp134
1 files changed, 126 insertions, 8 deletions
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index d73d1e9c20b3..b8ad2b294b87 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -702,6 +702,31 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
NewFn = Intrinsic::getDeclaration(F->getParent(), IID, Tys);
return true;
}
+
+ if (Name == "arm.mve.vctp64" &&
+ cast<FixedVectorType>(F->getReturnType())->getNumElements() == 4) {
+ // A vctp64 returning a v4i1 is converted to return a v2i1. Rename the
+ // function and deal with it below in UpgradeIntrinsicCall.
+ rename(F);
+ return true;
+ }
+ // These too are changed to accept a v2i1 insteead of the old v4i1.
+ if (Name == "arm.mve.mull.int.predicated.v2i64.v4i32.v4i1" ||
+ Name == "arm.mve.vqdmull.predicated.v2i64.v4i32.v4i1" ||
+ Name == "arm.mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1" ||
+ Name == "arm.mve.vldr.gather.base.wb.predicated.v2i64.v2i64.v4i1" ||
+ Name == "arm.mve.vldr.gather.offset.predicated.v2i64.p0i64.v2i64.v4i1" ||
+ Name == "arm.mve.vstr.scatter.base.predicated.v2i64.v2i64.v4i1" ||
+ Name == "arm.mve.vstr.scatter.base.wb.predicated.v2i64.v2i64.v4i1" ||
+ Name == "arm.mve.vstr.scatter.offset.predicated.p0i64.v2i64.v2i64.v4i1" ||
+ Name == "arm.cde.vcx1q.predicated.v2i64.v4i1" ||
+ Name == "arm.cde.vcx1qa.predicated.v2i64.v4i1" ||
+ Name == "arm.cde.vcx2q.predicated.v2i64.v4i1" ||
+ Name == "arm.cde.vcx2qa.predicated.v2i64.v4i1" ||
+ Name == "arm.cde.vcx3q.predicated.v2i64.v4i1" ||
+ Name == "arm.cde.vcx3qa.predicated.v2i64.v4i1")
+ return true;
+
break;
}
@@ -1803,6 +1828,96 @@ void llvm::UpgradeInlineAsmString(std::string *AsmStr) {
}
}
+static Value *UpgradeARMIntrinsicCall(StringRef Name, CallInst *CI, Function *F,
+ IRBuilder<> &Builder) {
+ if (Name == "mve.vctp64.old") {
+ // Replace the old v4i1 vctp64 with a v2i1 vctp and predicate-casts to the
+ // correct type.
+ Value *VCTP = Builder.CreateCall(
+ Intrinsic::getDeclaration(F->getParent(), Intrinsic::arm_mve_vctp64),
+ CI->getArgOperand(0), CI->getName());
+ Value *C1 = Builder.CreateCall(
+ Intrinsic::getDeclaration(
+ F->getParent(), Intrinsic::arm_mve_pred_v2i,
+ {VectorType::get(Builder.getInt1Ty(), 2, false)}),
+ VCTP);
+ return Builder.CreateCall(
+ Intrinsic::getDeclaration(
+ F->getParent(), Intrinsic::arm_mve_pred_i2v,
+ {VectorType::get(Builder.getInt1Ty(), 4, false)}),
+ C1);
+ } else if (Name == "mve.mull.int.predicated.v2i64.v4i32.v4i1" ||
+ Name == "mve.vqdmull.predicated.v2i64.v4i32.v4i1" ||
+ Name == "mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1" ||
+ Name == "mve.vldr.gather.base.wb.predicated.v2i64.v2i64.v4i1" ||
+ Name == "mve.vldr.gather.offset.predicated.v2i64.p0i64.v2i64.v4i1" ||
+ Name == "mve.vstr.scatter.base.predicated.v2i64.v2i64.v4i1" ||
+ Name == "mve.vstr.scatter.base.wb.predicated.v2i64.v2i64.v4i1" ||
+ Name == "mve.vstr.scatter.offset.predicated.p0i64.v2i64.v2i64.v4i1" ||
+ Name == "cde.vcx1q.predicated.v2i64.v4i1" ||
+ Name == "cde.vcx1qa.predicated.v2i64.v4i1" ||
+ Name == "cde.vcx2q.predicated.v2i64.v4i1" ||
+ Name == "cde.vcx2qa.predicated.v2i64.v4i1" ||
+ Name == "cde.vcx3q.predicated.v2i64.v4i1" ||
+ Name == "cde.vcx3qa.predicated.v2i64.v4i1") {
+ std::vector<Type *> Tys;
+ unsigned ID = CI->getIntrinsicID();
+ Type *V2I1Ty = FixedVectorType::get(Builder.getInt1Ty(), 2);
+ switch (ID) {
+ case Intrinsic::arm_mve_mull_int_predicated:
+ case Intrinsic::arm_mve_vqdmull_predicated:
+ case Intrinsic::arm_mve_vldr_gather_base_predicated:
+ Tys = {CI->getType(), CI->getOperand(0)->getType(), V2I1Ty};
+ break;
+ case Intrinsic::arm_mve_vldr_gather_base_wb_predicated:
+ case Intrinsic::arm_mve_vstr_scatter_base_predicated:
+ case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated:
+ Tys = {CI->getOperand(0)->getType(), CI->getOperand(0)->getType(),
+ V2I1Ty};
+ break;
+ case Intrinsic::arm_mve_vldr_gather_offset_predicated:
+ Tys = {CI->getType(), CI->getOperand(0)->getType(),
+ CI->getOperand(1)->getType(), V2I1Ty};
+ break;
+ case Intrinsic::arm_mve_vstr_scatter_offset_predicated:
+ Tys = {CI->getOperand(0)->getType(), CI->getOperand(1)->getType(),
+ CI->getOperand(2)->getType(), V2I1Ty};
+ break;
+ case Intrinsic::arm_cde_vcx1q_predicated:
+ case Intrinsic::arm_cde_vcx1qa_predicated:
+ case Intrinsic::arm_cde_vcx2q_predicated:
+ case Intrinsic::arm_cde_vcx2qa_predicated:
+ case Intrinsic::arm_cde_vcx3q_predicated:
+ case Intrinsic::arm_cde_vcx3qa_predicated:
+ Tys = {CI->getOperand(1)->getType(), V2I1Ty};
+ break;
+ default:
+ llvm_unreachable("Unhandled Intrinsic!");
+ }
+
+ std::vector<Value *> Ops;
+ for (Value *Op : CI->args()) {
+ Type *Ty = Op->getType();
+ if (Ty->getScalarSizeInBits() == 1) {
+ Value *C1 = Builder.CreateCall(
+ Intrinsic::getDeclaration(
+ F->getParent(), Intrinsic::arm_mve_pred_v2i,
+ {VectorType::get(Builder.getInt1Ty(), 4, false)}),
+ Op);
+ Op = Builder.CreateCall(
+ Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::arm_mve_pred_i2v, {V2I1Ty}),
+ C1);
+ }
+ Ops.push_back(Op);
+ }
+
+ Function *Fn = Intrinsic::getDeclaration(F->getParent(), ID, Tys);
+ return Builder.CreateCall(Fn, Ops, CI->getName());
+ }
+ llvm_unreachable("Unknown function for ARM CallInst upgrade.");
+}
+
/// Upgrade a call to an old intrinsic. All argument and return casting must be
/// provided to seamlessly integrate with existing context.
void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
@@ -1826,6 +1941,9 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
bool IsNVVM = Name.startswith("nvvm.");
if (IsNVVM)
Name = Name.substr(5);
+ bool IsARM = Name.startswith("arm.");
+ if (IsARM)
+ Name = Name.substr(4);
if (IsX86 && Name.startswith("sse4a.movnt.")) {
Module *M = F->getParent();
@@ -2289,14 +2407,12 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
if (CI->arg_size() >= 3)
Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
CI->getArgOperand(1));
- } else if (IsX86 && (Name.startswith("avx512.mask.loadu."))) {
- Rep = UpgradeMaskedLoad(Builder, CI->getArgOperand(0),
- CI->getArgOperand(1), CI->getArgOperand(2),
- /*Aligned*/false);
- } else if (IsX86 && (Name.startswith("avx512.mask.load."))) {
- Rep = UpgradeMaskedLoad(Builder, CI->getArgOperand(0),
- CI->getArgOperand(1),CI->getArgOperand(2),
- /*Aligned*/true);
+ } else if (IsX86 && Name.startswith("avx512.mask.load")) {
+ // "avx512.mask.loadu." or "avx512.mask.load."
+ bool Aligned = Name[16] != 'u'; // "avx512.mask.loadu".
+ Rep =
+ UpgradeMaskedLoad(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2), Aligned);
} else if (IsX86 && Name.startswith("avx512.mask.expand.load.")) {
auto *ResultTy = cast<FixedVectorType>(CI->getType());
Type *PtrTy = ResultTy->getElementType();
@@ -3649,6 +3765,8 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
F->getParent(), Intrinsic::convert_from_fp16,
{Builder.getFloatTy()}),
CI->getArgOperand(0), "h2f");
+ } else if (IsARM) {
+ Rep = UpgradeARMIntrinsicCall(Name, CI, F, Builder);
} else {
llvm_unreachable("Unknown function for CallInst upgrade.");
}