bool X86MachineInstructionRaiser::raiseMoveRegToRegMachineInstr()

in X86/X86MachineInstructionRaiser.cpp [322:668]


bool X86MachineInstructionRaiser::raiseMoveRegToRegMachineInstr(
    const MachineInstr &MI) {
  unsigned int Opcode = MI.getOpcode();
  int MBBNo = MI.getParent()->getNumber();
  LLVMContext &Ctx(MF.getFunction().getContext());

  // Get the BasicBlock corresponding to MachineBasicBlock of MI.
  // Raised instruction is added to this BasicBlock.
  BasicBlock *RaisedBB = getRaisedBasicBlock(MI.getParent());

  bool Success = false;
  unsigned DstIndex = 0, Src1Index = 1, Src2Index = 2;
  assert(
      (MI.getNumExplicitOperands() == 2 || MI.getNumExplicitOperands() == 4) &&
      MI.getOperand(DstIndex).isReg() &&
      (MI.getOperand(Src1Index).isReg() || MI.getOperand(Src2Index).isReg()) &&
      "Expecting exactly two or four operands for move reg-to-reg "
      "instructions");

  unsigned int DstPReg = MI.getOperand(DstIndex).getReg();

  // Get source operand value
  Value *SrcValue = nullptr;
  if (MI.getNumExplicitOperands() == 2)
    SrcValue = getRegOperandValue(MI, Src1Index);
  else if (MI.getNumExplicitOperands() == 4)
    SrcValue = getRegOperandValue(MI, Src2Index);
  else
    assert(false &&
           "Unexpected operand numbers for move reg-to-reg instruction");

  switch (Opcode) {
  case X86::MOVSX16rr8:
  case X86::MOVSX32rr8:
  case X86::MOVSX32rr16:
  case X86::MOVSX64rr8:
  case X86::MOVSX64rr16:
  case X86::MOVSX64rr32:
  case X86::MOVZX16rr8:
  case X86::MOVZX32rr8:
  case X86::MOVZX32rr16:
  case X86::MOVZX64rr8:
  case X86::MOVZX64rr16: {
    Type *Ty = nullptr;
    Instruction::CastOps Cast;
    // Check for sanity of source value
    assert(SrcValue &&
           "Encountered instruction with undefined source register");

    switch (Opcode) {
    case X86::MOVSX16rr8: {
      assert(is16BitPhysReg(DstPReg) &&
             "Not found expected 16-bit destination register - movsx "
             "instruction");
      Ty = Type::getInt16Ty(Ctx);
      Cast = Instruction::SExt;
    } break;
    case X86::MOVSX32rr8:
    case X86::MOVSX32rr16: {
      assert(is32BitPhysReg(DstPReg) &&
             "Not found expected 32-bit destination register - movsx "
             "instruction");
      Ty = Type::getInt32Ty(Ctx);
      Cast = Instruction::SExt;
    } break;
    case X86::MOVSX64rr8:
    case X86::MOVSX64rr16:
    case X86::MOVSX64rr32: {
      assert(is64BitPhysReg(DstPReg) &&
             "Not found expected 64-bit destination register - movsx "
             "instruction");
      Ty = Type::getInt64Ty(Ctx);
      Cast = Instruction::SExt;
    } break;
    case X86::MOVZX16rr8: {
      assert(is16BitPhysReg(DstPReg) &&
             "Not found expected 16-bit destination register - movsx "
             "instruction");
      Ty = Type::getInt16Ty(Ctx);
      Cast = Instruction::ZExt;
    } break;
    case X86::MOVZX32rr8:
    case X86::MOVZX32rr16: {
      assert(is32BitPhysReg(DstPReg) &&
             "Not found expected 32-bit destination register - movzx "
             "instruction");
      Ty = Type::getInt32Ty(Ctx);
      Cast = Instruction::ZExt;
    } break;
    case X86::MOVZX64rr8:
    case X86::MOVZX64rr16: {
      assert(is64BitPhysReg(DstPReg) &&
             "Not found expected 64-bit destination register - movzx "
             "instruction");
      Ty = Type::getInt64Ty(Ctx);
      Cast = Instruction::ZExt;
    } break;
    default:
      assert(false &&
             "Should not reach here! - mov with extension instruction");
    }
    assert(Ty != nullptr &&
           "Failed to set type - mov with extension instruction");
    // Now create the cast instruction corresponding to the instruction.
    CastInst *CInst = CastInst::Create(Cast, SrcValue, Ty);
    RaisedBB->getInstList().push_back(CInst);

    // Update the value mapping of DstPReg
    raisedValues->setPhysRegSSAValue(DstPReg, MBBNo, CInst);
    Success = true;
  } break;
  case X86::MOV64rr:
  case X86::MOV32rr:
  case X86::MOV16rr:
  case X86::MOV8rr: {
    unsigned int DstPRegSize = getPhysRegOperandSize(MI, DstIndex);
    unsigned int SrcPRegSize = getPhysRegOperandSize(MI, Src1Index);

    // Verify sanity of the instruction.
    assert(DstPRegSize != 0 && DstPRegSize == SrcPRegSize &&
           "Unexpected sizes of source and destination registers size differ "
           "in mov instruction");
    assert(SrcValue &&
           "Encountered mov instruction with undefined source register");
    assert(SrcValue->getType()->isSized() &&
           "Unsized source value in move instruction");
    MachineOperand MO = MI.getOperand(Src1Index);
    assert(MO.isReg() && "Unexpected non-register operand");
    // Check for undefined use
    Success = (SrcValue != nullptr);
    if (Success)
      // Update the value mapping of DstPReg
      raisedValues->setPhysRegSSAValue(DstPReg, MBBNo, SrcValue);
  } break;
  case X86::CMOV16rr:
  case X86::CMOV32rr:
  case X86::CMOV64rr: {
    unsigned int DstPRegSize = getPhysRegOperandSize(MI, DstIndex);
    unsigned int SrcPRegSize = getPhysRegOperandSize(MI, Src2Index);

    // Verify sanity of the instruction.
    assert(DstPRegSize != 0 && DstPRegSize == SrcPRegSize &&
           "Unexpected sizes of source and destination registers size differ "
           "in cmovcc instruction");
    assert(SrcValue &&
           "Encountered cmovcc instruction with undefined source register");
    assert(SrcValue->getType()->isSized() &&
           "Unsized source value in cmovcc instruction");
    SrcValue = getRegOperandValue(MI, Src2Index);
    // Check for undefined use
    Success = (SrcValue != nullptr);
    if (Success) {
      // Get destination operand value
      Value *DstValue = getRegOrArgValue(DstPReg, MBBNo);
      Value *TrueValue = ConstantInt::getTrue(Ctx);
      Value *FalseValue = ConstantInt::getFalse(Ctx);
      CmpInst::Predicate Pred = CmpInst::Predicate::BAD_ICMP_PREDICATE;
      Value *CMOVCond = nullptr;

      switch (X86::getCondFromCMov(MI)) {
      case X86::COND_NE: {
        // Check if ZF == 0
        Value *ZFValue = getRegOrArgValue(EFLAGS::ZF, MBBNo);
        assert(ZFValue != nullptr &&
               "Failed to get EFLAGS value while raising CMOVNE!");
        Pred = CmpInst::Predicate::ICMP_EQ;
        // Construct a compare instruction
        CMOVCond = new ICmpInst(Pred, ZFValue, FalseValue, "Cond_CMOVNE");
      } break;
      case X86::COND_E: {
        // Check if ZF == 1
        Value *ZFValue = getRegOrArgValue(EFLAGS::ZF, MBBNo);
        assert(ZFValue != nullptr &&
               "Failed to get EFLAGS value while raising CMOVE!");
        Pred = CmpInst::Predicate::ICMP_EQ;
        // Construct a compare instruction
        CMOVCond = new ICmpInst(Pred, ZFValue, TrueValue, "Cond_CMOVE");
      } break;
      case X86::COND_A: {
        // Check CF == 0 and ZF == 0
        Value *CFValue = getRegOrArgValue(EFLAGS::CF, MBBNo);
        Value *ZFValue = getRegOrArgValue(EFLAGS::ZF, MBBNo);
        assert((CFValue != nullptr) && (ZFValue != nullptr) &&
               "Failed to get EFLAGS value while raising CMOVA!");
        Pred = CmpInst::Predicate::ICMP_EQ;
        // CF or ZF
        BinaryOperator *CFZFOrCond =
            BinaryOperator::CreateOr(CFValue, ZFValue, "CFZFOR_CMOVA");
        RaisedBB->getInstList().push_back(CFZFOrCond);
        // Test CF == 0 and ZF == 0
        CMOVCond = new ICmpInst(Pred, CFZFOrCond, FalseValue, "Cond_CMOVA");
      } break;
      case X86::COND_L: {
        // Check SF != OF
        Value *SFValue = getRegOrArgValue(EFLAGS::SF, MBBNo);
        Value *OFValue = getRegOrArgValue(EFLAGS::OF, MBBNo);
        assert((SFValue != nullptr) && (OFValue != nullptr) &&
               "Failed to get EFLAGS value while raising CMOVL!");
        Pred = CmpInst::Predicate::ICMP_NE;
        // Test SF != OF
        CMOVCond = new ICmpInst(Pred, SFValue, OFValue, "Cond_CMOVL");
      } break;
      case X86::COND_G: {
        // Check ZF == 0 and SF == OF
        Value *ZFValue = getRegOrArgValue(EFLAGS::ZF, MBBNo);
        Value *SFValue = getRegOrArgValue(EFLAGS::SF, MBBNo);
        Value *OFValue = getRegOrArgValue(EFLAGS::OF, MBBNo);
        assert((ZFValue != nullptr) && (SFValue != nullptr) &&
               (OFValue != nullptr) &&
               "Failed to get EFLAGS value while raising CMOVG!");
        Pred = CmpInst::Predicate::ICMP_EQ;
        // Compare ZF and 0
        CmpInst *ZFCond =
            new ICmpInst(Pred, ZFValue, FalseValue, "ZFCmp_CMOVG");
        RaisedBB->getInstList().push_back(ZFCond);
        // Test SF == OF
        CmpInst *SFOFCond =
            new ICmpInst(Pred, SFValue, OFValue, "SFOFCmp_CMOVG");
        RaisedBB->getInstList().push_back(SFOFCond);
        CMOVCond = BinaryOperator::CreateAnd(ZFCond, SFOFCond, "Cond_CMOVG");
      } break;
      case X86::COND_LE: {
        // Check ZF == 1 or SF != OF
        Value *ZFValue = getRegOrArgValue(EFLAGS::ZF, MBBNo);
        Value *SFValue = getRegOrArgValue(EFLAGS::SF, MBBNo);
        Value *OFValue = getRegOrArgValue(EFLAGS::OF, MBBNo);
        assert((ZFValue != nullptr) && (SFValue != nullptr) &&
               (OFValue != nullptr) &&
               "Failed to get EFLAGS value while raising CMOVLE!");

        // Check ZF == 1
        CmpInst *ZFCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, ZFValue,
                                       TrueValue, "ZFCmp_CMOVLE");
        RaisedBB->getInstList().push_back(ZFCond);

        // Test SF != OF
        CmpInst *SFOFCond = new ICmpInst(CmpInst::Predicate::ICMP_NE, SFValue,
                                         OFValue, "SFOFCmp_CMOVLE");
        RaisedBB->getInstList().push_back(SFOFCond);

        CMOVCond = BinaryOperator::CreateOr(ZFCond, SFOFCond, "Cond_CMOVLE");
      } break;
      case X86::COND_NS: {
        // Test SF == 0
        Value *SFValue = getRegOrArgValue(EFLAGS::SF, MBBNo);
        assert(SFValue != nullptr &&
               "Failed to get EFLAGS value while raising CMOVNS");
        // Construct a compare instruction
        CMOVCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, SFValue,
                                FalseValue, "Cond_CMOVNS");
      } break;
      case X86::COND_AE: {
        // Test CF == 0
        Value *CFValue = getRegOrArgValue(EFLAGS::CF, MBBNo);
        assert(CFValue != nullptr &&
               "Failed to get EFLAGS value while raising CMOVAE");
        // Construct a compare instruction
        CMOVCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, CFValue,
                                FalseValue, "Cond_CMOVAE");
      } break;
      case X86::COND_B: {
        // Check if CF == 1
        Value *CFValue = getRegOrArgValue(EFLAGS::CF, MBBNo);
        assert(CFValue != nullptr &&
               "Failed to get EFLAGS value while raising CMOVB!");
        Pred = CmpInst::Predicate::ICMP_EQ;
        // Construct a compare instruction
        CMOVCond = new ICmpInst(Pred, CFValue, TrueValue, "Cond_CMOVB");
      } break;
      case X86::COND_NO: {
        // Test OF == 0
        Value *OFValue = getRegOrArgValue(EFLAGS::OF, MBBNo);
        assert(OFValue != nullptr &&
               "Failed to get EFLAGS value while raising CMOVNO");
        // Construct a compare instruction
        CMOVCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, OFValue,
                                FalseValue, "Cond_CMOVNO");
      } break;
      case X86::COND_O: {
        // Check if OF == 1
        Value *OFValue = getRegOrArgValue(EFLAGS::OF, MBBNo);
        assert(OFValue != nullptr &&
               "Failed to get EFLAGS value while raising CMOVO!");
        Pred = CmpInst::Predicate::ICMP_EQ;
        // Construct a compare instruction
        CMOVCond = new ICmpInst(Pred, OFValue, TrueValue, "Cond_CMOVO");
      } break;
      case X86::COND_S: {
        // Check if SF == 1
        Value *SFValue = getRegOrArgValue(EFLAGS::SF, MBBNo);
        assert(SFValue != nullptr &&
               "Failed to get EFLAGS value while raising CMOVS!");
        Pred = CmpInst::Predicate::ICMP_EQ;
        // Construct a compare instruction
        CMOVCond = new ICmpInst(Pred, SFValue, TrueValue, "Cond_CMOVS");
      } break;
      case X86::COND_GE: {
        // Check SF == OF
        Value *SFValue = getRegOrArgValue(EFLAGS::SF, MBBNo);
        Value *OFValue = getRegOrArgValue(EFLAGS::OF, MBBNo);
        assert((SFValue != nullptr) && (OFValue != nullptr) &&
               "Failed to get EFLAGS value while raising CMOVGE!");
        // Test SF == OF
        CMOVCond = new ICmpInst(CmpInst::Predicate::ICMP_EQ, SFValue, OFValue,
                                "Cond_CMOVGE");
      } break;
      case X86::COND_BE: {
        // Check CF == 1 OR ZF == 1
        Value *CFValue = getRegOrArgValue(EFLAGS::CF, MBBNo);
        Value *ZFValue = getRegOrArgValue(EFLAGS::ZF, MBBNo);
        assert(CFValue != nullptr && ZFValue != nullptr &&
               "Failed to get EFLAGS value while raising CMOVBE");
        auto CFCmp = new ICmpInst(CmpInst::Predicate::ICMP_EQ, CFValue,
                                  TrueValue, "Cond_CMOVBE_CF");
        auto ZFCmp = new ICmpInst(CmpInst::Predicate::ICMP_EQ, ZFValue,
                                  TrueValue, "Cond_CMOVBE_ZF");
        RaisedBB->getInstList().push_back(CFCmp);
        RaisedBB->getInstList().push_back(ZFCmp);
        CMOVCond = BinaryOperator::CreateOr(CFCmp, ZFCmp, "Cond_CMOVBE");
      } break;
      case X86::COND_INVALID:
        assert(false && "CMOV instruction with invalid condition found");
        break;
      default:
        assert(false && "CMOV instruction with unhandled condition found");
        break;
      }
      RaisedBB->getInstList().push_back(dyn_cast<Instruction>(CMOVCond));

      // Ensure that the types of SrcValue and DstValue match.
      DstValue =
          getRaisedValues()->castValue(DstValue, SrcValue->getType(), RaisedBB);

      // Generate SelectInst for CMOV instruction
      SelectInst *SI =
          SelectInst::Create(CMOVCond, SrcValue, DstValue, "CMOV", RaisedBB);

      // Update the value mapping of DstPReg
      raisedValues->setPhysRegSSAValue(DstPReg, MBBNo, SI);
    }
  } break;
  default:
    assert(false && "Unhandled move reg-to-reg instruction");
    break;
  }
  return Success;
}