// FIXME: This should just be implemented as a patch to // X86TargetAsmInfo.cpp, then everyone will benefit. bool RaiseAsmPass::runOnInstruction(Module &M, Instruction *I) { // We can just raise inline assembler using calls CallInst *ci = dyn_cast<CallInst>(I); if (!ci) return false; InlineAsm *ia = dyn_cast<InlineAsm>(ci->getCalledValue()); if (!ia) return false; // Try to use existing infrastructure if (!TLI) return false; if (TLI->ExpandInlineAsm(ci)) return true; if (triple.getArch() == llvm::Triple::x86_64 && triple.getOS() == llvm::Triple::Linux) { if (ia->getAsmString() == "" && ia->hasSideEffects()) { #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) IRBuilder<> Builder(I); Builder.CreateFence(llvm::SequentiallyConsistent); #endif I->eraseFromParent(); return true; } } return false; }
bool X86TargetAsmInfo<BaseTAI>::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. // bswap $0 if (AsmPieces.size() == 2 && (AsmPieces[0] == "bswap" || AsmPieces[0] == "bswapq" || AsmPieces[0] == "bswapl") && (AsmPieces[1] == "$0" || AsmPieces[1] == "${0:q}")) { // No need to check constraints, nothing other than the equivalent of // "=r,0" would be valid here. return LowerToBSwap(CI); } // rorw $$8, ${0:w} --> llvm.bswap.i16 if (CI->getType() == Type::Int16Ty && AsmPieces.size() == 3 && AsmPieces[0] == "rorw" && AsmPieces[1] == "$$8," && AsmPieces[2] == "${0:w}" && IA->getConstraintString() == "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}") { return LowerToBSwap(CI); } break; case 3: if (CI->getType() == Type::Int64Ty && Constraints.size() >= 2 && Constraints[0].Codes.size() == 1 && Constraints[0].Codes[0] == "A" && Constraints[1].Codes.size() == 1 && Constraints[1].Codes[0] == "0") { // bswap %eax / bswap %edx / xchgl %eax, %edx -> llvm.bswap.i64 std::vector<std::string> Words; SplitString(AsmPieces[0], Words, " \t"); if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%eax") { Words.clear(); SplitString(AsmPieces[1], Words, " \t"); if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%edx") { Words.clear(); SplitString(AsmPieces[2], Words, " \t,"); if (Words.size() == 3 && Words[0] == "xchgl" && Words[1] == "%eax" && Words[2] == "%edx") { return LowerToBSwap(CI); } } } } break; } return false; }