Changes in directory llvm/lib/Target/X86:
X86TargetAsmInfo.cpp updated: 1.9 -> 1.10 X86TargetAsmInfo.h updated: 1.2 -> 1.3 --- Log message: Trivially lower 'bswap $0' into llvm.bswap. This fixes hexxagon with the JIT on darwin/x86, which has htonl implemented as inline asm. --- Diffs of the changes: (+75 -1) X86TargetAsmInfo.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++- X86TargetAsmInfo.h | 4 ++ 2 files changed, 75 insertions(+), 1 deletion(-) Index: llvm/lib/Target/X86/X86TargetAsmInfo.cpp diff -u llvm/lib/Target/X86/X86TargetAsmInfo.cpp:1.9 llvm/lib/Target/X86/X86TargetAsmInfo.cpp:1.10 --- llvm/lib/Target/X86/X86TargetAsmInfo.cpp:1.9 Tue Nov 28 16:28:08 2006 +++ llvm/lib/Target/X86/X86TargetAsmInfo.cpp Tue Nov 28 19:14:06 2006 @@ -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 @@ } } +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<InlineAsm>(CI->getCalledValue()); + //std::vector<InlineAsm::ConstraintInfo> Constraints = IA->ParseConstraints(); + + std::string AsmStr = IA->getAsmString(); + + // TODO: should remove alternatives from the asmstring: "foo {a|b}" -> "foo a" + std::vector<std::string> 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; +} Index: llvm/lib/Target/X86/X86TargetAsmInfo.h diff -u llvm/lib/Target/X86/X86TargetAsmInfo.h:1.2 llvm/lib/Target/X86/X86TargetAsmInfo.h:1.3 --- llvm/lib/Target/X86/X86TargetAsmInfo.h:1.2 Wed Oct 4 21:43:52 2006 +++ llvm/lib/Target/X86/X86TargetAsmInfo.h Tue Nov 28 19:14:06 2006 @@ -23,6 +23,10 @@ struct X86TargetAsmInfo : public TargetAsmInfo { X86TargetAsmInfo(const X86TargetMachine &TM); + + virtual bool ExpandInlineAsm(CallInst *CI) const; + private: + bool LowerToBSwap(CallInst *CI) const; }; } // namespace llvm _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits