From: Chris Lattner Date: Wed, 29 Nov 2006 01:14:06 +0000 (+0000) Subject: Trivially lower 'bswap $0' into llvm.bswap. This fixes hexxagon with the X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=625bd052a3df8ef7bf016b1ad17a76283a56257a;p=oota-llvm.git Trivially lower 'bswap $0' into llvm.bswap. This fixes hexxagon with the JIT on darwin/x86, which has htonl implemented as inline asm. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31999 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/X86TargetAsmInfo.cpp b/lib/Target/X86/X86TargetAsmInfo.cpp index 0459f18c24a..32d918efec1 100644 --- a/lib/Target/X86/X86TargetAsmInfo.cpp +++ b/lib/Target/X86/X86TargetAsmInfo.cpp @@ -14,7 +14,10 @@ #include "X86TargetAsmInfo.h" #include "X86TargetMachine.h" #include "X86Subtarget.h" - +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/ADT/StringExtras.h" using namespace llvm; static const char* x86_asm_table[] = {"{si}", "S", @@ -154,3 +157,70 @@ X86TargetAsmInfo::X86TargetAsmInfo(const X86TargetMachine &TM) { } } +bool X86TargetAsmInfo::LowerToBSwap(CallInst *CI) const { + // FIXME: this should verify that we are targetting a 486 or better. If not, + // we will turn this bswap into something that will be lowered to logical ops + // instead of emitting the bswap asm. For now, we don't support 486 or lower + // so don't worry about this. + + // Verify this is a simple bswap. + if (CI->getNumOperands() != 2 || + CI->getType() != CI->getOperand(1)->getType() || + !CI->getType()->isInteger()) + return false; + + const Type *Ty = CI->getType()->getUnsignedVersion(); + const char *IntName; + switch (Ty->getTypeID()) { + default: return false; + case Type::UShortTyID: IntName = "llvm.bswap.i16"; break; + case Type::UIntTyID: IntName = "llvm.bswap.i32"; break; + case Type::ULongTyID: IntName = "llvm.bswap.i64"; break; + } + + // Okay, we can do this xform, do so now. + Module *M = CI->getParent()->getParent()->getParent(); + Function *Int = M->getOrInsertFunction(IntName, Ty, Ty, (Type*)0); + + Value *Op = CI->getOperand(1); + if (CI->getOperand(1)->getType() != Ty) + Op = new BitCastInst(Op, Ty, Op->getName(), CI); + + Op = new CallInst(Int, Op, CI->getName(), CI); + + if (Op->getType() != CI->getType()) + Op = new BitCastInst(Op, CI->getType(), Op->getName(), CI); + + CI->replaceAllUsesWith(Op); + CI->eraseFromParent(); + return true; +} + + +bool X86TargetAsmInfo::ExpandInlineAsm(CallInst *CI) const { + InlineAsm *IA = cast(CI->getCalledValue()); + //std::vector Constraints = IA->ParseConstraints(); + + std::string AsmStr = IA->getAsmString(); + + // TODO: should remove alternatives from the asmstring: "foo {a|b}" -> "foo a" + std::vector AsmPieces; + SplitString(AsmStr, AsmPieces, "\n"); // ; as separator? + + switch (AsmPieces.size()) { + default: return false; + case 1: + AsmStr = AsmPieces[0]; + AsmPieces.clear(); + SplitString(AsmStr, AsmPieces, " \t"); // Split with whitespace. + + if (AsmPieces.size() == 2 && + AsmPieces[0] == "bswap" && AsmPieces[1] == "$0") { + // No need to check constraints, nothing other than the equivalent of + // "=r,0" would be valid here. + return LowerToBSwap(CI); + } + break; + } + return false; +} diff --git a/lib/Target/X86/X86TargetAsmInfo.h b/lib/Target/X86/X86TargetAsmInfo.h index ac0505f7160..0f698590ae7 100644 --- a/lib/Target/X86/X86TargetAsmInfo.h +++ b/lib/Target/X86/X86TargetAsmInfo.h @@ -23,6 +23,10 @@ namespace llvm { struct X86TargetAsmInfo : public TargetAsmInfo { X86TargetAsmInfo(const X86TargetMachine &TM); + + virtual bool ExpandInlineAsm(CallInst *CI) const; + private: + bool LowerToBSwap(CallInst *CI) const; }; } // namespace llvm