forked from OSchip/llvm-project
This is one of the first steps at moving to replace target-dependent
intrinsics with target-indepdent intrinsics. The first instruction(s) to be handled are the vector versions of count leading zeros (ctlz). The changes here are to clang so that it generates a target independent vector ctlz when it sees an ARM dependent vector ctlz. The changes in llvm are to match the target independent vector ctlz and in VMCore/AutoUpgrade.cpp to update any existing bc files containing ARM dependent vector ctlzs with target-independent ctlzs. There are also changes to an existing test case in llvm for ARM vector count instructions and a new test for the bitcode upgrade. <rdar://problem/11831778> There is deliberately no test for the change to clang, as so far as I know, no consensus has been reached regarding how to test neon instructions in clang; q.v. <rdar://problem/8762292> llvm-svn: 160200
This commit is contained in:
parent
f04a21917c
commit
43cb87839c
|
@ -4825,7 +4825,7 @@ defm VCLS : N2VInt_QHS<0b11, 0b11, 0b00, 0b01000, 0,
|
|||
// VCLZ : Vector Count Leading Zeros
|
||||
defm VCLZ : N2VInt_QHS<0b11, 0b11, 0b00, 0b01001, 0,
|
||||
IIC_VCNTiD, IIC_VCNTiQ, "vclz", "i",
|
||||
int_arm_neon_vclz>;
|
||||
ctlz>;
|
||||
// VCNT : Vector Count One Bits
|
||||
def VCNTd : N2VDInt<0b11, 0b11, 0b00, 0b00, 0b01010, 0,
|
||||
IIC_VCNTiD, "vcnt", "8",
|
||||
|
|
|
@ -52,6 +52,22 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
|
|||
|
||||
switch (Name[0]) {
|
||||
default: break;
|
||||
case 'a': {
|
||||
if (Name.startswith("arm.neon.vclz")) {
|
||||
Type* args[2] = {
|
||||
F->arg_begin()->getType(),
|
||||
Type::getInt1Ty(F->getContext())
|
||||
};
|
||||
// Can't use Intrinsic::getDeclaration here as it adds a ".i1" to
|
||||
// the end of the name. Change name from llvm.arm.neon.vclz.* to
|
||||
// llvm.ctlz.*
|
||||
FunctionType* fType = FunctionType::get(F->getReturnType(), args, false);
|
||||
NewFn = Function::Create(fType, F->getLinkage(),
|
||||
"llvm.ctlz." + Name.substr(14), F->getParent());
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
if (Name.startswith("ctlz.") && F->arg_size() == 1) {
|
||||
F->setName(Name + ".old");
|
||||
|
@ -295,6 +311,15 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
|
|||
CI->eraseFromParent();
|
||||
return;
|
||||
|
||||
case Intrinsic::arm_neon_vclz: {
|
||||
// Change name from llvm.arm.neon.vclz.* to llvm.ctlz.*
|
||||
CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, CI->getArgOperand(0),
|
||||
Builder.getFalse(),
|
||||
"llvm.ctlz." + Name.substr(14)));
|
||||
CI->eraseFromParent();
|
||||
return;
|
||||
}
|
||||
|
||||
case Intrinsic::x86_xop_vfrcz_ss:
|
||||
case Intrinsic::x86_xop_vfrcz_sd:
|
||||
CI->replaceAllUsesWith(Builder.CreateCall(NewFn, CI->getArgOperand(1),
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
|
||||
; NB: currently tests only vclz, should also test vcnt and vcls
|
||||
|
||||
define <4 x i16> @vclz16(<4 x i16>* %A) nounwind {
|
||||
;CHECK: @vclz16
|
||||
%tmp1 = load <4 x i16>* %A
|
||||
%tmp2 = call <4 x i16> @llvm.arm.neon.vclz.v4i16(<4 x i16> %tmp1)
|
||||
;CHECK: {{call.*@llvm.ctlz.v4i16\(<4 x i16>.*, i1 false}}
|
||||
ret <4 x i16> %tmp2
|
||||
}
|
||||
|
||||
declare <4 x i16> @llvm.arm.neon.vclz.v4i16(<4 x i16>) nounwind readnone
|
|
@ -1,4 +1,5 @@
|
|||
; RUN: llc < %s -march=arm -mattr=+neon | FileCheck %s
|
||||
; NB: this tests vcnt, vclz, and vcls
|
||||
|
||||
define <8 x i8> @vcnt8(<8 x i8>* %A) nounwind {
|
||||
;CHECK: vcnt8:
|
||||
|
@ -21,59 +22,59 @@ declare <16 x i8> @llvm.arm.neon.vcnt.v16i8(<16 x i8>) nounwind readnone
|
|||
|
||||
define <8 x i8> @vclz8(<8 x i8>* %A) nounwind {
|
||||
;CHECK: vclz8:
|
||||
;CHECK: vclz.i8
|
||||
;CHECK: vclz.i8 {{d[0-9]+}}, {{d[0-9]+}}
|
||||
%tmp1 = load <8 x i8>* %A
|
||||
%tmp2 = call <8 x i8> @llvm.arm.neon.vclz.v8i8(<8 x i8> %tmp1)
|
||||
%tmp2 = call <8 x i8> @llvm.ctlz.v8i8(<8 x i8> %tmp1, i1 0)
|
||||
ret <8 x i8> %tmp2
|
||||
}
|
||||
|
||||
define <4 x i16> @vclz16(<4 x i16>* %A) nounwind {
|
||||
;CHECK: vclz16:
|
||||
;CHECK: vclz.i16
|
||||
;CHECK: vclz.i16 {{d[0-9]+}}, {{d[0-9]+}}
|
||||
%tmp1 = load <4 x i16>* %A
|
||||
%tmp2 = call <4 x i16> @llvm.arm.neon.vclz.v4i16(<4 x i16> %tmp1)
|
||||
%tmp2 = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> %tmp1, i1 0)
|
||||
ret <4 x i16> %tmp2
|
||||
}
|
||||
|
||||
define <2 x i32> @vclz32(<2 x i32>* %A) nounwind {
|
||||
;CHECK: vclz32:
|
||||
;CHECK: vclz.i32
|
||||
;CHECK: vclz.i32 {{d[0-9]+}}, {{d[0-9]+}}
|
||||
%tmp1 = load <2 x i32>* %A
|
||||
%tmp2 = call <2 x i32> @llvm.arm.neon.vclz.v2i32(<2 x i32> %tmp1)
|
||||
%tmp2 = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %tmp1, i1 0)
|
||||
ret <2 x i32> %tmp2
|
||||
}
|
||||
|
||||
define <16 x i8> @vclzQ8(<16 x i8>* %A) nounwind {
|
||||
;CHECK: vclzQ8:
|
||||
;CHECK: vclz.i8
|
||||
;CHECK: vclz.i8 {{q[0-9]+}}, {{q[0-9]+}}
|
||||
%tmp1 = load <16 x i8>* %A
|
||||
%tmp2 = call <16 x i8> @llvm.arm.neon.vclz.v16i8(<16 x i8> %tmp1)
|
||||
%tmp2 = call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %tmp1, i1 0)
|
||||
ret <16 x i8> %tmp2
|
||||
}
|
||||
|
||||
define <8 x i16> @vclzQ16(<8 x i16>* %A) nounwind {
|
||||
;CHECK: vclzQ16:
|
||||
;CHECK: vclz.i16
|
||||
;CHECK: vclz.i16 {{q[0-9]+}}, {{q[0-9]+}}
|
||||
%tmp1 = load <8 x i16>* %A
|
||||
%tmp2 = call <8 x i16> @llvm.arm.neon.vclz.v8i16(<8 x i16> %tmp1)
|
||||
%tmp2 = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %tmp1, i1 0)
|
||||
ret <8 x i16> %tmp2
|
||||
}
|
||||
|
||||
define <4 x i32> @vclzQ32(<4 x i32>* %A) nounwind {
|
||||
;CHECK: vclzQ32:
|
||||
;CHECK: vclz.i32
|
||||
;CHECK: vclz.i32 {{q[0-9]+}}, {{q[0-9]+}}
|
||||
%tmp1 = load <4 x i32>* %A
|
||||
%tmp2 = call <4 x i32> @llvm.arm.neon.vclz.v4i32(<4 x i32> %tmp1)
|
||||
%tmp2 = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %tmp1, i1 0)
|
||||
ret <4 x i32> %tmp2
|
||||
}
|
||||
|
||||
declare <8 x i8> @llvm.arm.neon.vclz.v8i8(<8 x i8>) nounwind readnone
|
||||
declare <4 x i16> @llvm.arm.neon.vclz.v4i16(<4 x i16>) nounwind readnone
|
||||
declare <2 x i32> @llvm.arm.neon.vclz.v2i32(<2 x i32>) nounwind readnone
|
||||
declare <8 x i8> @llvm.ctlz.v8i8(<8 x i8>, i1) nounwind readnone
|
||||
declare <4 x i16> @llvm.ctlz.v4i16(<4 x i16>, i1) nounwind readnone
|
||||
declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1) nounwind readnone
|
||||
|
||||
declare <16 x i8> @llvm.arm.neon.vclz.v16i8(<16 x i8>) nounwind readnone
|
||||
declare <8 x i16> @llvm.arm.neon.vclz.v8i16(<8 x i16>) nounwind readnone
|
||||
declare <4 x i32> @llvm.arm.neon.vclz.v4i32(<4 x i32>) nounwind readnone
|
||||
declare <16 x i8> @llvm.ctlz.v16i8(<16 x i8>, i1) nounwind readnone
|
||||
declare <8 x i16> @llvm.ctlz.v8i16(<8 x i16>, i1) nounwind readnone
|
||||
declare <4 x i32> @llvm.ctlz.v4i32(<4 x i32>, i1) nounwind readnone
|
||||
|
||||
define <8 x i8> @vclss8(<8 x i8>* %A) nounwind {
|
||||
;CHECK: vclss8:
|
||||
|
|
Loading…
Reference in New Issue