diff options
author | Evan Cheng <evan.cheng@apple.com> | 2007-12-17 22:33:23 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2007-12-17 22:33:23 +0000 |
commit | f9b83fcf95e8a280d7b117af8858596fe5b10d94 (patch) | |
tree | 0545ada63de4a6fd2f4d2a60a1f5c4206f8abed0 | |
parent | 504c369213efb263136bb048e79af3516511c040 (diff) | |
download | external_llvm-f9b83fcf95e8a280d7b117af8858596fe5b10d94.zip external_llvm-f9b83fcf95e8a280d7b117af8858596fe5b10d94.tar.gz external_llvm-f9b83fcf95e8a280d7b117af8858596fe5b10d94.tar.bz2 |
Bring back int_x86_sse2_movl_dq intrinsic for backward compatibility. Make sure
it's auto-upgraded to a shufflevector instruction.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45131 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/AutoUpgrade.h | 6 | ||||
-rw-r--r-- | include/llvm/IntrinsicsX86.td | 2 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitcodeReader.cpp | 3 | ||||
-rw-r--r-- | lib/VMCore/AutoUpgrade.cpp | 91 | ||||
-rw-r--r-- | test/Bitcode/sse2_movl_dq.ll | 2 | ||||
-rw-r--r-- | test/Bitcode/sse2_movl_dq.ll.bc | bin | 0 -> 480 bytes |
6 files changed, 78 insertions, 26 deletions
diff --git a/include/llvm/AutoUpgrade.h b/include/llvm/AutoUpgrade.h index e3a32b9..d0d8e95 100644 --- a/include/llvm/AutoUpgrade.h +++ b/include/llvm/AutoUpgrade.h @@ -20,8 +20,10 @@ namespace llvm { class BasicBlock; /// This is a more granular function that simply checks an intrinsic function - /// for upgrading, and if it requires upgrading provides the new function. - Function* UpgradeIntrinsicFunction(Function *F); + /// for upgrading, and returns true if it requires upgrading. It may return + /// null in NewFn if the all calls to the original intrinsic function + /// should be transformed to non-function-call instructions. + bool UpgradeIntrinsicFunction(Function *F, Function *&NewFn); /// This is the complement to the above, replacing a specific call to an /// intrinsic function with a call to the specified new function. diff --git a/include/llvm/IntrinsicsX86.td b/include/llvm/IntrinsicsX86.td index 4a553af..12e7633 100644 --- a/include/llvm/IntrinsicsX86.td +++ b/include/llvm/IntrinsicsX86.td @@ -460,6 +460,8 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_packuswb_128 : GCCBuiltin<"__builtin_ia32_packuswb128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_movl_dq : GCCBuiltin<"__builtin_ia32_movqv4si">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; def int_x86_sse2_movmsk_pd : GCCBuiltin<"__builtin_ia32_movmskpd">, Intrinsic<[llvm_i32_ty, llvm_v2f64_ty], [IntrNoMem]>; def int_x86_sse2_pmovmskb_128 : GCCBuiltin<"__builtin_ia32_pmovmskb128">, diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 4e761e4..19b7aa5 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -873,7 +873,8 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) { // Look for intrinsic functions which need to be upgraded at some point for (Module::iterator FI = TheModule->begin(), FE = TheModule->end(); FI != FE; ++FI) { - if (Function* NewFn = UpgradeIntrinsicFunction(FI)) + Function* NewFn; + if (UpgradeIntrinsicFunction(FI, NewFn)) UpgradedIntrinsics.push_back(std::make_pair(FI, NewFn)); } diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp index 005b1f8..e2f6137 100644 --- a/lib/VMCore/AutoUpgrade.cpp +++ b/lib/VMCore/AutoUpgrade.cpp @@ -21,7 +21,7 @@ using namespace llvm; -static Function* UpgradeIntrinsicFunction1(Function *F) { +static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { assert(F && "Illegal to upgrade a non-existent Function."); // Get the Function's name. @@ -33,7 +33,7 @@ static Function* UpgradeIntrinsicFunction1(Function *F) { // Quickly eliminate it, if it's not a candidate. if (Name.length() <= 8 || Name[0] != 'l' || Name[1] != 'l' || Name[2] != 'v' || Name[3] != 'm' || Name[4] != '.') - return 0; + return false; Module *M = F->getParent(); switch (Name[5]) { @@ -49,7 +49,8 @@ static Function* UpgradeIntrinsicFunction1(Function *F) { if (delim != std::string::npos) { // Construct the new name as 'llvm.bswap' + '.i*' F->setName(Name.substr(0,10)+Name.substr(delim)); - return F; + NewFn = F; + return true; } } break; @@ -71,10 +72,11 @@ static Function* UpgradeIntrinsicFunction1(Function *F) { // Now construct the new intrinsic with the correct name and type. We // leave the old function around in order to query its type, whatever it // may be, and correctly convert up to the new type. - return cast<Function>(M->getOrInsertFunction(Name, - FTy->getParamType(0), - FTy->getParamType(0), - (Type *)0)); + NewFn = cast<Function>(M->getOrInsertFunction(Name, + FTy->getParamType(0), + FTy->getParamType(0), + (Type *)0)); + return true; } break; @@ -88,7 +90,8 @@ static Function* UpgradeIntrinsicFunction1(Function *F) { if (delim != std::string::npos) { // Construct a new name as 'llvm.part.select' + '.i*' F->setName(Name.substr(0,16)+Name.substr(delim)); - return F; + NewFn = F; + return true; } break; } @@ -105,7 +108,8 @@ static Function* UpgradeIntrinsicFunction1(Function *F) { Name.find('.',delim+1) != std::string::npos) { // Construct a new name as 'llvm.part.select' + '.i*.i*' F->setName(Name.substr(0,13)+Name.substr(delim)); - return F; + NewFn = F; + return true; } break; } @@ -137,12 +141,18 @@ static Function* UpgradeIntrinsicFunction1(Function *F) { // Now construct the new intrinsic with the correct name and type. We // leave the old function around in order to query its type, whatever it // may be, and correctly convert up to the new type. - return cast<Function>(M->getOrInsertFunction(Name, - FTy->getReturnType(), - FTy->getParamType(0), - VT, - (Type *)0)); + NewFn = cast<Function>(M->getOrInsertFunction(Name, + FTy->getReturnType(), + FTy->getParamType(0), + VT, + (Type *)0)); + return true; + } else if (Name.compare(5,16,"x86.sse2.movl.dq",16) == 0) { + // Calls to this intrinsic are transformed into ShuffleVector's. + NewFn = 0; + return true; } + break; } @@ -150,15 +160,16 @@ static Function* UpgradeIntrinsicFunction1(Function *F) { // to both detect an intrinsic which needs upgrading, and to provide the // upgraded form of the intrinsic. We should perhaps have two separate // functions for this. - return 0; + return false; } -Function* llvm::UpgradeIntrinsicFunction(Function *F) { - Function *Upgraded = UpgradeIntrinsicFunction1(F); +bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) { + NewFn = 0; + bool Upgraded = UpgradeIntrinsicFunction1(F, NewFn); // Upgrade intrinsic attributes. This does not change the function. - if (Upgraded) - F = Upgraded; + if (NewFn) + F = NewFn; if (unsigned id = F->getIntrinsicID(true)) F->setParamAttrs(Intrinsic::getParamAttrs((Intrinsic::ID)id)); return Upgraded; @@ -168,11 +179,44 @@ Function* llvm::UpgradeIntrinsicFunction(Function *F) { // upgraded intrinsic. All argument and return casting must be provided in // order to seamlessly integrate with existing context. void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { - assert(NewFn && "Cannot upgrade an intrinsic call without a new function."); - Function *F = CI->getCalledFunction(); assert(F && "CallInst has no function associated with it."); - + + if (!NewFn) { + switch(F->getIntrinsicID()) { + default: assert(0 && "Unknown function for CallInst upgrade."); + case Intrinsic::x86_sse2_movl_dq: { + std::vector<Constant*> Idxs; + Constant *Zero = ConstantInt::get(Type::Int32Ty, 0); + Idxs.push_back(Zero); + Idxs.push_back(Zero); + Idxs.push_back(Zero); + Idxs.push_back(Zero); + Value *ZeroV = ConstantVector::get(Idxs); + + Idxs.clear(); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 4)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 5)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 2)); + Idxs.push_back(ConstantInt::get(Type::Int32Ty, 3)); + Value *Mask = ConstantVector::get(Idxs); + ShuffleVectorInst *SI = new ShuffleVectorInst(ZeroV, CI->getOperand(1), + Mask, "upgraded", CI); + + // Handle any uses of the old CallInst. + if (!CI->use_empty()) + // Replace all uses of the old call with the new cast which has the + // correct type. + CI->replaceAllUsesWith(SI); + + // Clean up the old call now that it has been completely upgraded. + CI->eraseFromParent(); + break; + } + } + return; + } + switch(NewFn->getIntrinsicID()) { default: assert(0 && "Unknown function for CallInst upgrade."); case Intrinsic::x86_mmx_psll_d: @@ -257,7 +301,8 @@ void llvm::UpgradeCallsToIntrinsic(Function* F) { assert(F && "Illegal attempt to upgrade a non-existent intrinsic."); // Upgrade the function and check if it is a totaly new function. - if (Function* NewFn = UpgradeIntrinsicFunction(F)) { + Function* NewFn; + if (UpgradeIntrinsicFunction(F, NewFn)) { if (NewFn != F) { // Replace all uses to the old function with the new one if necessary. for (Value::use_iterator UI = F->use_begin(), UE = F->use_end(); diff --git a/test/Bitcode/sse2_movl_dq.ll b/test/Bitcode/sse2_movl_dq.ll new file mode 100644 index 0000000..093d8213 --- /dev/null +++ b/test/Bitcode/sse2_movl_dq.ll @@ -0,0 +1,2 @@ +; RUN: llvm-dis < %s.bc | not grep {i32 @llvm\\.movl.dq} +; RUN: llvm-dis < %s.bc | grep shufflevector diff --git a/test/Bitcode/sse2_movl_dq.ll.bc b/test/Bitcode/sse2_movl_dq.ll.bc Binary files differnew file mode 100644 index 0000000..74d1826 --- /dev/null +++ b/test/Bitcode/sse2_movl_dq.ll.bc |