Example #1
0
// 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;
}
Example #2
0
/// 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;
}
Example #3
0
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;
}