/// OptimizeInlineAsmInst - If there are any memory operands, use /// OptimizeMemoryInst to sink their address computing into the block when /// possible / profitable. bool CodeGenPrepare::OptimizeInlineAsmInst(Instruction *I, CallSite CS, DenseMap<Value*,Value*> &SunkAddrs) { bool MadeChange = false; InlineAsm *IA = cast<InlineAsm>(CS.getCalledValue()); // Do a prepass over the constraints, canonicalizing them, and building up the // ConstraintOperands list. std::vector<InlineAsm::ConstraintInfo> ConstraintInfos = IA->ParseConstraints(); /// ConstraintOperands - Information about all of the constraints. std::vector<TargetLowering::AsmOperandInfo> ConstraintOperands; unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) { ConstraintOperands. push_back(TargetLowering::AsmOperandInfo(ConstraintInfos[i])); TargetLowering::AsmOperandInfo &OpInfo = ConstraintOperands.back(); // Compute the value type for each operand. switch (OpInfo.Type) { case InlineAsm::isOutput: if (OpInfo.isIndirect) OpInfo.CallOperandVal = CS.getArgument(ArgNo++); break; case InlineAsm::isInput: OpInfo.CallOperandVal = CS.getArgument(ArgNo++); break; case InlineAsm::isClobber: // Nothing to do. break; } // Compute the constraint code and ConstraintType to use. TLI->ComputeConstraintToUse(OpInfo, SDValue(), OpInfo.ConstraintType == TargetLowering::C_Memory); if (OpInfo.ConstraintType == TargetLowering::C_Memory && OpInfo.isIndirect) { Value *OpVal = OpInfo.CallOperandVal; MadeChange |= OptimizeMemoryInst(I, OpVal, OpVal->getType(), SunkAddrs); } } return MadeChange; }
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; }