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;
}