Keep attributes, calling convention, etc, when remangling intrinsic

Summary: Fix issue reported where intrinsic calling convention is dropped after r295253.

Reviewers: sanjoy

Subscribers: materi, llvm-commits

Differential Revision: https://reviews.llvm.org/D30422

llvm-svn: 296563
This commit is contained in:
Daniel Berlin 2017-03-01 01:49:13 +00:00
parent 1bf65c8c0d
commit 3f91004ce7
2 changed files with 41 additions and 51 deletions

View File

@ -1911,20 +1911,14 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
return;
}
std::string Name = CI->getName();
if (!Name.empty())
CI->setName(Name + ".old");
CallInst *NewCall = nullptr;
switch (NewFn->getIntrinsicID()) {
default: {
// Handle generic mangling change, but nothing else
assert(
(CI->getCalledFunction()->getName() != NewFn->getName()) &&
"Unknown function for CallInst upgrade and isn't just a name change");
SmallVector<Value *, 4> Args(CI->arg_operands().begin(),
CI->arg_operands().end());
CI->replaceAllUsesWith(Builder.CreateCall(NewFn, Args));
CI->eraseFromParent();
CI->setCalledFunction(NewFn);
return;
}
@ -1944,47 +1938,39 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
case Intrinsic::arm_neon_vst4lane: {
SmallVector<Value *, 4> Args(CI->arg_operands().begin(),
CI->arg_operands().end());
CI->replaceAllUsesWith(Builder.CreateCall(NewFn, Args));
CI->eraseFromParent();
return;
NewCall = Builder.CreateCall(NewFn, Args);
break;
}
case Intrinsic::bitreverse:
CI->replaceAllUsesWith(Builder.CreateCall(NewFn, {CI->getArgOperand(0)}));
CI->eraseFromParent();
return;
NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
break;
case Intrinsic::ctlz:
case Intrinsic::cttz:
assert(CI->getNumArgOperands() == 1 &&
"Mismatch between function args and call args");
CI->replaceAllUsesWith(Builder.CreateCall(
NewFn, {CI->getArgOperand(0), Builder.getFalse()}, Name));
CI->eraseFromParent();
return;
NewCall =
Builder.CreateCall(NewFn, {CI->getArgOperand(0), Builder.getFalse()});
break;
case Intrinsic::objectsize:
CI->replaceAllUsesWith(Builder.CreateCall(
NewFn, {CI->getArgOperand(0), CI->getArgOperand(1)}, Name));
CI->eraseFromParent();
return;
NewCall =
Builder.CreateCall(NewFn, {CI->getArgOperand(0), CI->getArgOperand(1)});
break;
case Intrinsic::ctpop:
CI->replaceAllUsesWith(Builder.CreateCall(NewFn, {CI->getArgOperand(0)}));
CI->eraseFromParent();
return;
NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
break;
case Intrinsic::convert_from_fp16:
CI->replaceAllUsesWith(Builder.CreateCall(NewFn, {CI->getArgOperand(0)}));
CI->eraseFromParent();
return;
NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
break;
case Intrinsic::x86_xop_vfrcz_ss:
case Intrinsic::x86_xop_vfrcz_sd:
CI->replaceAllUsesWith(
Builder.CreateCall(NewFn, {CI->getArgOperand(1)}, Name));
CI->eraseFromParent();
return;
NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(1)});
break;
case Intrinsic::x86_xop_vpermil2pd:
case Intrinsic::x86_xop_vpermil2ps:
@ -1995,9 +1981,8 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
VectorType *FltIdxTy = cast<VectorType>(Args[2]->getType());
VectorType *IntIdxTy = VectorType::getInteger(FltIdxTy);
Args[2] = Builder.CreateBitCast(Args[2], IntIdxTy);
CI->replaceAllUsesWith(Builder.CreateCall(NewFn, Args, Name));
CI->eraseFromParent();
return;
NewCall = Builder.CreateCall(NewFn, Args);
break;
}
case Intrinsic::x86_sse41_ptestc:
@ -2019,10 +2004,8 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Value *BC0 = Builder.CreateBitCast(Arg0, NewVecTy, "cast");
Value *BC1 = Builder.CreateBitCast(Arg1, NewVecTy, "cast");
CallInst *NewCall = Builder.CreateCall(NewFn, {BC0, BC1}, Name);
CI->replaceAllUsesWith(NewCall);
CI->eraseFromParent();
return;
NewCall = Builder.CreateCall(NewFn, {BC0, BC1});
break;
}
case Intrinsic::x86_sse41_insertps:
@ -2038,17 +2021,13 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
// Replace the last argument with a trunc.
Args.back() = Builder.CreateTrunc(Args.back(), Type::getInt8Ty(C), "trunc");
CallInst *NewCall = Builder.CreateCall(NewFn, Args);
CI->replaceAllUsesWith(NewCall);
CI->eraseFromParent();
return;
NewCall = Builder.CreateCall(NewFn, Args);
break;
}
case Intrinsic::thread_pointer: {
CI->replaceAllUsesWith(Builder.CreateCall(NewFn, {}));
CI->eraseFromParent();
return;
NewCall = Builder.CreateCall(NewFn, {});
break;
}
case Intrinsic::invariant_start:
@ -2057,11 +2036,19 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
case Intrinsic::masked_store: {
SmallVector<Value *, 4> Args(CI->arg_operands().begin(),
CI->arg_operands().end());
CI->replaceAllUsesWith(Builder.CreateCall(NewFn, Args));
CI->eraseFromParent();
return;
NewCall = Builder.CreateCall(NewFn, Args);
break;
}
}
assert(NewCall && "Should have either set this variable or returned through "
"the default case");
std::string Name = CI->getName();
if (!Name.empty()) {
CI->setName(Name + ".old");
NewCall->setName(Name);
}
CI->replaceAllUsesWith(NewCall);
CI->eraseFromParent();
}
void llvm::UpgradeCallsToIntrinsic(Function *F) {

View File

@ -1,4 +1,5 @@
; RUN: opt -verify -S < %s
; RUN: opt -S < %s | FileCheck %s
; Tests the name mangling performed by the codepath following
; getMangledTypeStr(). Only tests that code with the various manglings
@ -67,7 +68,9 @@ entry:
define %i32* @test_broken_names(%i32* %v) gc "statepoint-example" {
entry:
%tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.deadbeef(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, %i32* %v)
%tok = call fastcc token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.deadbeef(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, %i32* %v)
; Make sure we do not destroy the calling convention when remangling
; CHECK: fastcc
%v-new = call %i32* @llvm.experimental.gc.relocate.beefdead(token %tok, i32 7, i32 7)
ret %i32* %v-new
}