in X86/X86MachineInstructionRaiser.cpp [778:1556]
bool X86MachineInstructionRaiser::raiseBinaryOpRegToRegMachineInstr(
const MachineInstr &MI) {
auto MCID = MI.getDesc();
// Get the BasicBlock corresponding to MachineBasicBlock of MI.
// Raised instruction is added to this BasicBlock.
BasicBlock *RaisedBB = getRaisedBasicBlock(MI.getParent());
// Convenience variables for instructions with a dest and one or two
// operands
const unsigned DestOpIndex = 0, UseOp1Index = 1, UseOp2Index = 2;
std::vector<Value *> ExplicitSrcValues;
int MBBNo = MI.getParent()->getNumber();
bool Success = true;
unsigned opc = MI.getOpcode();
// Check if this instruction is a xor reg1, reg1 instruction, and does not need
// to look up the value of the operand values
bool IsXorSetZeroInstruction =
(opc == X86::XOR64rr || opc == X86::XOR32rr || opc == X86::XOR16rr ||
opc == X86::XOR8rr || opc == X86::XORPSrr || opc == X86::XORPDrr ||
opc == X86::PXORrr) &&
(MI.findTiedOperandIdx(1) == 0 &&
MI.getOperand(DestOpIndex).getReg() ==
MI.getOperand(UseOp2Index).getReg());
// If we are raising a xor instruction that's just zeroing-out a register,
// we don't need to look up the register operand values
if (!IsXorSetZeroInstruction) {
for (const MachineOperand &MO : MI.explicit_uses()) {
assert(MO.isReg() &&
"Unexpected non-register operand in binary op instruction");
auto UseOpIndex =
MI.findRegisterUseOperandIdx(MO.getReg(), false, nullptr);
Value *SrcValue = getRegOperandValue(MI, UseOpIndex);
ExplicitSrcValues.push_back(SrcValue);
}
// Verify the instruction has 1 or 2 use operands
assert(
(ExplicitSrcValues.size() == 1 || ((ExplicitSrcValues.size() == 2))) &&
"Unexpected number of operands in register binary op instruction");
// If the instruction has two use operands, ensure that their values are
// of the same type and non-pointer type.
if (ExplicitSrcValues.size() == 2) {
Value *Src1Value = ExplicitSrcValues.at(0);
Value *Src2Value = ExplicitSrcValues.at(1);
// The user operand values can be null if the instruction is 'xor op
// op'. See below.
if ((Src1Value != nullptr) && (Src2Value != nullptr)) {
// If this is a pointer type, convert it to int type
while (Src1Value->getType()->isPointerTy()) {
PtrToIntInst *ConvPtrToInst = new PtrToIntInst(
Src1Value, Src1Value->getType()->getPointerElementType());
RaisedBB->getInstList().push_back(ConvPtrToInst);
Src1Value = ConvPtrToInst;
}
// If this is a pointer type, convert it to int type
while (Src2Value->getType()->isPointerTy()) {
PtrToIntInst *ConvPtrToInst = new PtrToIntInst(
Src2Value, Src2Value->getType()->getPointerElementType());
RaisedBB->getInstList().push_back(ConvPtrToInst);
Src2Value = ConvPtrToInst;
}
assert(((Src1Value->getType()->isIntegerTy() &&
Src2Value->getType()->isIntegerTy()) ||
(Src1Value->getType()->isFloatingPointTy() &&
Src2Value->getType()->isFloatingPointTy()) ||
(Src1Value->getType()->isVectorTy() &&
Src2Value->getType()->isVectorTy())) &&
"Unhandled operand value types in reg-to-reg binary op "
"instruction");
if (Src1Value->getType() != Src2Value->getType()) {
// Cast the second operand to the type of second.
// NOTE : The choice of target cast type is rather arbitrary. May
// need a closer look.
Type *DestValueTy = Src1Value->getType();
Instruction *CInst = CastInst::Create(
CastInst::getCastOpcode(Src2Value, false, DestValueTy, false),
Src2Value, DestValueTy);
RaisedBB->getInstList().push_back(CInst);
Src2Value = CInst;
}
ExplicitSrcValues[0] = Src1Value;
ExplicitSrcValues[1] = Src2Value;
}
}
}
// Figure out the destination register, corresponding value and the
// binary operator.
unsigned int dstReg = X86::NoRegister;
Value *dstValue = nullptr;
// Construct the appropriate binary operation instruction
switch (opc) {
case X86::ADD8rr:
case X86::ADD32rr:
case X86::ADD64rr: {
Value *Src1Value = ExplicitSrcValues.at(0);
Value *Src2Value = ExplicitSrcValues.at(1);
// Verify the def operand is a register.
assert(MI.getOperand(DestOpIndex).isReg() &&
"Expecting destination of add instruction to be a register "
"operand");
assert((MCID.getNumDefs() == 1) &&
"Unexpected number of defines in an add instruction");
assert((Src1Value != nullptr) && (Src2Value != nullptr) &&
"Unhandled situation: register is used before initialization in "
"add");
dstReg = MI.getOperand(DestOpIndex).getReg();
// Create add instruction
Instruction *BinOpInst = BinaryOperator::CreateNSWAdd(Src1Value, Src2Value);
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(Src1Value, BinOpInst);
raisedValues->setInstMetadataRODataIndex(Src2Value, BinOpInst);
RaisedBB->getInstList().push_back(BinOpInst);
dstValue = BinOpInst;
// Set SF and ZF based on dstValue; technically OF, AF, CF and PF also
// needs to be set but ignoring for now.
raisedValues->testAndSetEflagSSAValue(EFLAGS::SF, MI, dstValue);
raisedValues->testAndSetEflagSSAValue(EFLAGS::ZF, MI, dstValue);
// Update the value of dstReg
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, dstValue);
} break;
case X86::IMUL16rr:
case X86::IMUL32rr:
case X86::IMUL64rr: {
Value *Src1Value = ExplicitSrcValues.at(0);
Value *Src2Value = ExplicitSrcValues.at(1);
// Verify the def operand is a register.
assert(MI.getOperand(DestOpIndex).isReg() &&
"Expecting destination of mul instruction to be a register "
"operand");
assert((MCID.getNumDefs() == 1) &&
"Unexpected number of defines in a mul instruction");
assert((Src1Value != nullptr) && (Src2Value != nullptr) &&
"Unhandled situation: register is used before initialization in "
"mul");
dstReg = MI.getOperand(DestOpIndex).getReg();
Instruction *BinOpInst = BinaryOperator::CreateNSWMul(Src1Value, Src2Value);
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(Src1Value, BinOpInst);
raisedValues->setInstMetadataRODataIndex(Src2Value, BinOpInst);
RaisedBB->getInstList().push_back(BinOpInst);
dstValue = BinOpInst;
// Setting EFLAG bits does not seem to matter, so not setting
// Set the dstReg value
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, dstValue);
} break;
case X86::IMUL16r:
case X86::IMUL32r:
case X86::IMUL64r:
case X86::MUL16r:
case X86::MUL32r:
case X86::MUL64r: {
bool IsSigned = instrNameStartsWith(MI, "IMUL");
assert(MCID.getNumDefs() == 0 && MCID.getNumImplicitDefs() == 3 &&
MCID.getNumImplicitUses() == 1 &&
"Unexpected operands in imul instruction");
// Find first source operand - this is the implicit operand AL/AX/EAX/RAX
const MCPhysReg Src1Reg = MCID.ImplicitUses[0];
assert(find64BitSuperReg(Src1Reg) == X86::RAX &&
"Unexpected implicit register in imul instruction");
// Find second operand - this is the explicit operand of the instruction
std::vector<MCPhysReg> SrcRegs;
for (const MachineOperand &MO : MI.explicit_uses()) {
assert(MO.isReg() &&
"Unexpected non-register operand in binary op instruction");
SrcRegs.push_back(MO.getReg());
}
// Ensure that there is only one explicit source operand
assert(SrcRegs.size() == 1 &&
"Unexpected number of source register operands in imul instruction");
// Check the sizes of source operands are the same
const MCPhysReg Src2Reg = SrcRegs[0];
unsigned int SrcOpSize = getPhysRegSizeInBits(Src1Reg);
assert(getPhysRegSizeInBits(Src1Reg) == getPhysRegSizeInBits(Src2Reg) &&
"Mismatched size of implicit source register and explicit source "
"register");
// Get the value of Src1Reg and Src2Reg
Value *Src1Value = getRegOrArgValue(Src1Reg, MBBNo);
Value *Src2Value = getRegOrArgValue(Src2Reg, MBBNo);
assert((Src1Value != nullptr) && (Src2Value != nullptr) &&
"Unexpected null source operand value in imul instruction");
assert(Src1Value->getType()->isIntegerTy() &&
Src2Value->getType()->isIntegerTy() &&
"Unexpected non-integer type source operands in imul instruction");
LLVMContext &Ctx(MF.getFunction().getContext());
// Widen the source values since the result of the multiplication
Type *WideTy = Type::getIntNTy(Ctx, SrcOpSize * 2);
CastInst *Src1ValueDT = CastInst::Create(
CastInst::getCastOpcode(Src1Value, IsSigned, WideTy, IsSigned),
Src1Value, WideTy);
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(Src1Value, Src1ValueDT);
RaisedBB->getInstList().push_back(Src1ValueDT);
CastInst *Src2ValueDT = CastInst::Create(
CastInst::getCastOpcode(Src2Value, IsSigned, WideTy, IsSigned),
Src2Value, WideTy);
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(Src2Value, Src2ValueDT);
RaisedBB->getInstList().push_back(Src2ValueDT);
// Multiply the values
Instruction *FullProductValue =
BinaryOperator::CreateNSWMul(Src1ValueDT, Src2ValueDT);
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(Src1ValueDT, FullProductValue);
raisedValues->setInstMetadataRODataIndex(Src2ValueDT, FullProductValue);
RaisedBB->getInstList().push_back(FullProductValue);
// Shift amount equal to size of source operand
Value *ShiftAmountVal =
ConstantInt::get(FullProductValue->getType(), SrcOpSize);
// Split the value into ImplicitDefs[0]:ImplicitDefs[1]
// Compute shr of FullProductValue
Instruction *ShrDT =
BinaryOperator::CreateLShr(FullProductValue, ShiftAmountVal);
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(FullProductValue, ShrDT);
RaisedBB->getInstList().push_back(ShrDT);
// Truncate ShrDT to SrcOpSize
Type *SrcValTy = Type::getIntNTy(Ctx, SrcOpSize);
CastInst *ProductUpperValue =
CastInst::Create(CastInst::Trunc, ShrDT, SrcValTy);
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(ShrDT, ProductUpperValue);
RaisedBB->getInstList().push_back(ProductUpperValue);
// Set the value of ImplicitDef[1] as ProductLowreHalfValue
raisedValues->setPhysRegSSAValue(MCID.ImplicitDefs[1], MBBNo,
ProductUpperValue);
// Truncate the multiplication result to get the lower half value
CastInst *ProductLowerHalfValue =
CastInst::Create(CastInst::Trunc, FullProductValue, SrcValTy);
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(FullProductValue,
ProductLowerHalfValue);
RaisedBB->getInstList().push_back(ProductLowerHalfValue);
// Set the value of ImplicitDef[0] as ProductLowerHalfValue
raisedValues->setPhysRegSSAValue(MCID.ImplicitDefs[0], MBBNo,
ProductLowerHalfValue);
if (IsSigned) {
// For IMUL instruction, we check if the full result is equal to the
// sign-extended lower half If they are equal, set OF and CF to 0, 1
// otherwise
auto LowerSExtended = CastInst::Create(
CastInst::SExt, ProductLowerHalfValue, WideTy, "", RaisedBB);
auto EqualToFullValue = new ICmpInst(CmpInst::Predicate::ICMP_NE,
LowerSExtended, FullProductValue);
RaisedBB->getInstList().push_back(EqualToFullValue);
raisedValues->setPhysRegSSAValue(X86RegisterUtils::EFLAGS::OF, MBBNo,
EqualToFullValue);
raisedValues->setPhysRegSSAValue(X86RegisterUtils::EFLAGS::CF, MBBNo,
EqualToFullValue);
} else {
// Set OF and CF flags to 0 if upper half of the result is 0; else to 1.
Value *ZeroValue = ConstantInt::get(SrcValTy, 0, IsSigned);
Instruction *ZFTest =
new ICmpInst(CmpInst::Predicate::ICMP_NE, ProductUpperValue,
ZeroValue, "Test_Not_Zero");
RaisedBB->getInstList().push_back(ZFTest);
raisedValues->setPhysRegSSAValue(X86RegisterUtils::EFLAGS::OF, MBBNo,
ZFTest);
raisedValues->setPhysRegSSAValue(X86RegisterUtils::EFLAGS::CF, MBBNo,
ZFTest);
}
} break;
case X86::AND8rr:
case X86::AND16rr:
case X86::AND32rr:
case X86::AND64rr:
case X86::OR8rr:
case X86::OR16rr:
case X86::OR32rr:
case X86::OR64rr:
case X86::XOR8rr:
case X86::XOR16rr:
case X86::XOR32rr:
case X86::XOR64rr: {
// Verify the def operand is a register.
const MachineOperand &DestOp = MI.getOperand(DestOpIndex);
assert(DestOp.isReg() && "Expecting destination of xor instruction to "
"be a register operand");
assert((MCID.getNumDefs() == 1) &&
MCID.hasImplicitDefOfPhysReg(X86::EFLAGS) &&
"Unexpected defines in a xor instruction");
dstReg = DestOp.getReg();
// Generate an or instruction to set the zero flag if the
// operands are the same. An instruction such as 'xor $ecx, ecx' is
// generated to set the register value to 0.
if (IsXorSetZeroInstruction) {
// No instruction to generate. Just set destReg value to 0.
Type *DestTy = getPhysRegOperandType(MI, 0);
Value *Val = ConstantInt::get(DestTy, 0, false /* isSigned */);
dstValue = Val;
// Set SF and ZF knowing that the value is 0
raisedValues->setEflagBoolean(EFLAGS::SF, MBBNo, false);
raisedValues->setEflagBoolean(EFLAGS::ZF, MBBNo, true);
// Set PF knowing that the value is 0, since 0 has
// an even number of bits set, namely, zero
raisedValues->setEflagBoolean(EFLAGS::PF, MBBNo, true);
} else {
Value *Src1Value = ExplicitSrcValues.at(0);
Value *Src2Value = ExplicitSrcValues.at(1);
assert((Src1Value != nullptr) && (Src2Value != nullptr) &&
"Unhandled situation: register used before initialization in "
"xor");
Instruction *BinOpInst = nullptr;
switch (opc) {
case X86::AND8rr:
case X86::AND16rr:
case X86::AND32rr:
case X86::AND64rr:
BinOpInst = BinaryOperator::CreateAnd(Src1Value, Src2Value);
break;
case X86::OR8rr:
case X86::OR16rr:
case X86::OR32rr:
case X86::OR64rr:
BinOpInst = BinaryOperator::CreateOr(Src1Value, Src2Value);
break;
case X86::XOR8rr:
case X86::XOR16rr:
case X86::XOR32rr:
case X86::XOR64rr:
BinOpInst = BinaryOperator::CreateXor(Src1Value, Src2Value);
break;
default:
assert(false && "Reached unexpected location");
}
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(Src1Value, BinOpInst);
raisedValues->setInstMetadataRODataIndex(Src2Value, BinOpInst);
RaisedBB->getInstList().push_back(BinOpInst);
dstValue = BinOpInst;
// Set SF, PF, and ZF based on dstValue.
raisedValues->testAndSetEflagSSAValue(EFLAGS::SF, MI, dstValue);
raisedValues->testAndSetEflagSSAValue(EFLAGS::ZF, MI, dstValue);
raisedValues->testAndSetEflagSSAValue(EFLAGS::PF, MI, dstValue);
}
// Clear OF and CF
raisedValues->setEflagBoolean(EFLAGS::OF, MBBNo, false);
raisedValues->setEflagBoolean(EFLAGS::CF, MBBNo, false);
// Update the value of dstReg
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, dstValue);
} break;
case X86::TEST8rr:
case X86::TEST16rr:
case X86::TEST32rr:
case X86::TEST64rr: {
Value *Src1Value = ExplicitSrcValues.at(0);
Value *Src2Value = ExplicitSrcValues.at(1);
assert((MCID.getNumDefs() == 0) &&
MCID.hasImplicitDefOfPhysReg(X86::EFLAGS) &&
"Unexpected defines in a test instruction");
assert((Src1Value != nullptr) && (Src2Value != nullptr) &&
"Unhandled situation: register is used before initialization in "
"test");
dstReg = X86::EFLAGS;
Instruction *BinOpInst = BinaryOperator::CreateAnd(Src1Value, Src2Value);
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(Src1Value, BinOpInst);
if (Src1Value != Src2Value)
raisedValues->setInstMetadataRODataIndex(Src2Value, BinOpInst);
RaisedBB->getInstList().push_back(BinOpInst);
dstValue = BinOpInst;
// Clear OF and CF
raisedValues->setEflagBoolean(EFLAGS::OF, MBBNo, false);
raisedValues->setEflagBoolean(EFLAGS::CF, MBBNo, false);
// Set SF, PF, and ZF based on dstValue.
raisedValues->testAndSetEflagSSAValue(EFLAGS::SF, MI, dstValue);
raisedValues->testAndSetEflagSSAValue(EFLAGS::ZF, MI, dstValue);
raisedValues->testAndSetEflagSSAValue(EFLAGS::PF, MI, dstValue);
} break;
case X86::NEG8r:
case X86::NEG16r:
case X86::NEG32r:
case X86::NEG64r: {
// Verify source and dest are tied and are registers
const MachineOperand &DestOp = MI.getOperand(DestOpIndex);
assert(DestOp.isTied() &&
(MI.findTiedOperandIdx(DestOpIndex) == UseOp1Index) &&
"Expect tied operand in neg instruction");
assert(DestOp.isReg() && "Expect reg operand in neg instruction");
assert((MCID.getNumDefs() == 1) &&
MCID.hasImplicitDefOfPhysReg(X86::EFLAGS) &&
"Unexpected defines in a neg instruction");
dstReg = DestOp.getReg();
Value *Src1Value = ExplicitSrcValues.at(0);
Instruction *BinOpInst = BinaryOperator::CreateNeg(Src1Value);
dstValue = BinOpInst;
// Set CF to 0 if source operand is 0
// Note: Add this instruction _before_ adding the result of neg
raisedValues->testAndSetEflagSSAValue(EFLAGS::CF, MI, dstValue);
// Now add the neg instruction
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(Src1Value, BinOpInst);
RaisedBB->getInstList().push_back(BinOpInst);
// Now set up the flags according to the result
// Set SF, PF, and ZF based on dstValue.
raisedValues->testAndSetEflagSSAValue(EFLAGS::ZF, MI, dstValue);
raisedValues->testAndSetEflagSSAValue(EFLAGS::SF, MI, dstValue);
raisedValues->testAndSetEflagSSAValue(EFLAGS::PF, MI, dstValue);
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, dstValue);
} break;
case X86::NOT8r:
case X86::NOT16r:
case X86::NOT32r:
case X86::NOT64r: {
// Verify source and dest are tied and are registers
const MachineOperand &DestOp = MI.getOperand(DestOpIndex);
assert(DestOp.isTied() &&
(MI.findTiedOperandIdx(DestOpIndex) == UseOp1Index) &&
"Expect tied operand in not instruction");
assert(DestOp.isReg() && "Expect reg operand in not instruction");
assert((MCID.getNumDefs() == 1) &&
"Unexpected defines in a not instruction");
dstReg = DestOp.getReg();
Value *Src1Value = ExplicitSrcValues.at(0);
Instruction *BinOpInst = BinaryOperator::CreateNot(Src1Value);
// No EFLAGS are effected
// Add the not instruction
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(Src1Value, BinOpInst);
RaisedBB->getInstList().push_back(BinOpInst);
dstValue = BinOpInst;
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, dstValue);
} break;
case X86::SAR8rCL:
case X86::SAR16rCL:
case X86::SAR32rCL:
case X86::SAR64rCL:
case X86::SHL8rCL:
case X86::SHL16rCL:
case X86::SHL32rCL:
case X86::SHL64rCL:
case X86::SHR8rCL:
case X86::SHR16rCL:
case X86::SHR32rCL:
case X86::SHR64rCL: {
// Verify source and dest are tied and are registers
const MachineOperand &DestOp = MI.getOperand(DestOpIndex);
assert(DestOp.isTied() &&
(MI.findTiedOperandIdx(DestOpIndex) == UseOp1Index) &&
"Expect tied operand in shl instruction");
assert(DestOp.isReg() && "Expect reg operand in shl instruction");
assert((MCID.getNumDefs() == 1) &&
"Unexpected defines in a shl instruction");
dstReg = DestOp.getReg();
Value *SrcOpValue = ExplicitSrcValues.at(0);
assert((MCID.getNumImplicitUses() == 1) &&
"Expect one implicit use in shl instruction");
assert((MCID.ImplicitUses[0] == X86::CL) &&
"Expect implicit CL regsiter operand in shl instruction");
Value *CountValue = getPhysRegValue(MI, X86::CL);
// Check for undefined use
if (CountValue == nullptr)
Success = false;
else {
// cast CountValue as needed
Type *SrcOpValueTy = SrcOpValue->getType();
CountValue =
getRaisedValues()->castValue(CountValue, SrcOpValueTy, RaisedBB);
// Count is masked to 5 bits (6 bits if 64-bit register)
bool Is64Bit = (SrcOpValue->getType()->getPrimitiveSizeInBits() == 64);
Value *CountMask = Is64Bit ? ConstantInt::get(SrcOpValueTy, 0x1f)
: ConstantInt::get(SrcOpValueTy, 0x3f);
// Generate mask
CountValue = BinaryOperator::CreateAnd(CountValue, CountMask,
"shift-cnt-msk", RaisedBB);
Instruction *BinOpInst;
if (instrNameStartsWith(MI, "SAR")) {
BinOpInst =
BinaryOperator::CreateAShr(SrcOpValue, CountValue);
} else if (instrNameStartsWith(MI, "SHL")) {
BinOpInst =
BinaryOperator::CreateShl(SrcOpValue, CountValue);
} else if (instrNameStartsWith(MI, "SHR")) {
BinOpInst =
BinaryOperator::CreateLShr(SrcOpValue, CountValue);
} else {
llvm_unreachable("unhandled shift instruction");
}
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(SrcOpValue, BinOpInst);
raisedValues->setInstMetadataRODataIndex(CountValue, BinOpInst);
// Add the shl instruction
RaisedBB->getInstList().push_back(BinOpInst);
dstValue = BinOpInst;
// Affected EFLAGS
raisedValues->testAndSetEflagSSAValue(EFLAGS::CF, MI, dstValue);
raisedValues->testAndSetEflagSSAValue(EFLAGS::ZF, MI, dstValue);
raisedValues->testAndSetEflagSSAValue(EFLAGS::SF, MI, dstValue);
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, dstValue);
}
} break;
case X86::POPCNT16rr:
case X86::POPCNT32rr:
case X86::POPCNT64rr: {
const MachineOperand &DestOp = MI.getOperand(DestOpIndex);
assert(DestOp.isReg() && "Expecting destination of popcnt instruction to "
"be a register operand");
assert((MCID.getNumDefs() == 1) &&
MCID.hasImplicitDefOfPhysReg(X86::EFLAGS) &&
"Unexpected defines in a popcnt instruction");
dstReg = DestOp.getReg();
Value *SrcValue = ExplicitSrcValues.at(0);
Module *M = MR->getModule();
Function *IntrinsicFunc =
Intrinsic::getDeclaration(M, Intrinsic::ctpop, SrcValue->getType());
Value *IntrinsicCallArgs[] = {SrcValue};
Instruction *BinOpInst =
CallInst::Create(IntrinsicFunc, ArrayRef<Value *>(IntrinsicCallArgs));
// Add the intrinsic call instruction
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(SrcValue, BinOpInst);
RaisedBB->getInstList().push_back(BinOpInst);
dstValue = BinOpInst;
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, dstValue);
// OF, SF, ZF, AF, CF, PF are all cleared. ZF is set if SRC = 0, otherwise
// ZF is cleared.
raisedValues->setEflagBoolean(EFLAGS::OF, MBBNo, false);
raisedValues->setEflagBoolean(EFLAGS::SF, MBBNo, false);
raisedValues->setEflagBoolean(EFLAGS::AF, MBBNo, false);
raisedValues->setEflagBoolean(EFLAGS::CF, MBBNo, false);
raisedValues->setEflagBoolean(EFLAGS::PF, MBBNo, false);
// Test if SrcValue is Zero
Value *ZeroValue =
ConstantInt::get(SrcValue->getType(), 0, false /* isSigned */);
Instruction *ZFTest = new ICmpInst(CmpInst::Predicate::ICMP_EQ, SrcValue,
ZeroValue, "ZeroFlag");
RaisedBB->getInstList().push_back(ZFTest);
// ZF = (SrcValue==0).
raisedValues->setPhysRegSSAValue(X86RegisterUtils::EFLAGS::ZF, MBBNo,
ZFTest);
} break;
case X86::SUBSSrr_Int:
case X86::SUBSDrr_Int:
case X86::ADDSSrr_Int:
case X86::ADDSDrr_Int:
case X86::MULSDrr_Int:
case X86::MULSSrr_Int:
case X86::DIVSDrr_Int:
case X86::DIVSSrr_Int: {
Value *Src1Value = ExplicitSrcValues.at(0);
Value *Src2Value = ExplicitSrcValues.at(1);
// Verify the def operand is a register.
assert(MI.getOperand(DestOpIndex).isReg() &&
"Expecting destination of fp op instruction to be a register "
"operand");
assert((MCID.getNumDefs() == 1) &&
"Unexpected number of defines in fp op instruction");
assert((Src1Value != nullptr) && (Src2Value != nullptr) &&
"Unhandled situation: register is used before initialization in "
"fp op");
dstReg = MI.getOperand(DestOpIndex).getReg();
Instruction *BinOpInst = nullptr;
switch (opc) {
case X86::ADDSSrr_Int:
case X86::ADDSDrr_Int:
BinOpInst = BinaryOperator::CreateFAdd(Src1Value, Src2Value);
break;
case X86::SUBSSrr_Int:
case X86::SUBSDrr_Int:
BinOpInst = BinaryOperator::CreateFSub(Src1Value, Src2Value);
break;
case X86::MULSDrr_Int:
case X86::MULSSrr_Int:
BinOpInst = BinaryOperator::CreateFMul(Src1Value, Src2Value);
break;
case X86::DIVSDrr_Int:
case X86::DIVSSrr_Int:
BinOpInst = BinaryOperator::CreateFDiv(Src1Value, Src2Value);
break;
default:
llvm_unreachable("Unhandled fp instruction");
}
// Copy any necessary rodata related metadata
raisedValues->setInstMetadataRODataIndex(Src1Value, BinOpInst);
// raisedValues->setInstMetadataRODataIndex(Src2Value, BinOpInst);
RaisedBB->getInstList().push_back(BinOpInst);
dstValue = BinOpInst;
// Update the value of dstReg
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, dstValue);
} break;
case X86::PANDrr:
case X86::PANDNrr:
case X86::ANDPDrr:
case X86::ANDPSrr:
case X86::ANDNPDrr:
case X86::ANDNPSrr:
case X86::PORrr:
case X86::ORPDrr:
case X86::ORPSrr:
case X86::PXORrr:
case X86::XORPDrr:
case X86::XORPSrr: {
// bitwise operations on fp values do not exist in LLVM.
// To emulate the behavior, we
// - bitcast values to int
// - perform the operation
// - bitcast back to original type
dstReg = MI.getOperand(DestOpIndex).getReg();
if (IsXorSetZeroInstruction) {
// No instruction to generate. Just set destReg value to 0.
Type *DestTy = getPhysRegOperandType(MI, 0);
if (DestTy->isFPOrFPVectorTy()) {
dstValue = ConstantFP::get(DestTy, 0);
} else {
dstValue = ConstantInt::get(DestTy, 0);
}
} else {
LLVMContext &Ctx(MF.getFunction().getContext());
Value *Src1Value = ExplicitSrcValues.at(0);
Value *Src2Value = ExplicitSrcValues.at(1);
// Verify the def operand is a register.
assert(MI.getOperand(DestOpIndex).isReg() &&
"Expecting destination of fp op instruction to be a register "
"operand");
assert((MCID.getNumDefs() == 1) &&
"Unexpected number of defines in fp op instruction");
assert((Src1Value != nullptr) && (Src2Value != nullptr) &&
"Unhandled situation: register is used before initialization in "
"fp op");
assert(Src1Value->getType()->getPrimitiveSizeInBits() ==
Src2Value->getType()->getPrimitiveSizeInBits() &&
"Expected operand types to have same size");
auto BitSize = std::max(Src1Value->getType()->getPrimitiveSizeInBits(),
Src2Value->getType()->getPrimitiveSizeInBits());
Instruction *BitCastToInt1 =
new BitCastInst(Src1Value, Type::getIntNTy(Ctx, BitSize),
"bitwise_operand", RaisedBB);
Instruction *BitCastToInt2 =
new BitCastInst(Src2Value, Type::getIntNTy(Ctx, BitSize),
"bitwise_operand", RaisedBB);
Instruction *Result;
switch (opc) {
case X86::PANDrr:
case X86::ANDPDrr:
case X86::ANDPSrr:
Result = BinaryOperator::CreateAnd(BitCastToInt1, BitCastToInt2,
"and_result", RaisedBB);
break;
case X86::PANDNrr:
case X86::ANDNPDrr:
case X86::ANDNPSrr: {
auto NotVal = BinaryOperator::CreateNot(BitCastToInt1, "", RaisedBB);
Result = BinaryOperator::CreateAnd(NotVal, BitCastToInt2,
"andn_result", RaisedBB);
} break;
case X86::PORrr:
case X86::ORPDrr:
case X86::ORPSrr:
Result = BinaryOperator::CreateOr(BitCastToInt1, BitCastToInt2,
"or_result", RaisedBB);
break;
case X86::PXORrr:
case X86::XORPDrr:
case X86::XORPSrr:
Result = BinaryOperator::CreateXor(BitCastToInt1, BitCastToInt2,
"xor_result", RaisedBB);
break;
default:
llvm_unreachable("unhandled bitwise instruction");
}
Instruction *CastBackResult = new BitCastInst(
Result, Src1Value->getType(), "bitcast_result", RaisedBB);
dstValue = CastBackResult;
}
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, dstValue);
} break;
case X86::MAXSDrr_Int:
case X86::MAXSSrr_Int:
case X86::MINSDrr_Int:
case X86::MINSSrr_Int: {
bool isMax = instrNameStartsWith(MI, "MAX");
std::string nameString = isMax ? "max" : "min";
Value *Src1Value = ExplicitSrcValues.at(0);
Value *Src2Value = ExplicitSrcValues.at(1);
auto CmpType = isMax ? CmpInst::FCMP_OGT : CmpInst::FCMP_OLT;
Instruction *CmpInst =
new FCmpInst(*RaisedBB, CmpType, Src1Value, Src2Value, "cmp");
Instruction *SelectInst =
SelectInst::Create(CmpInst, Src1Value, Src2Value, nameString, RaisedBB);
dstReg = MI.getOperand(DestOpIndex).getReg();
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, SelectInst);
} break;
case X86::SBB16rr:
case X86::SBB32rr:
case X86::SBB64rr:
case X86::SBB8rr: {
Value *Src1Value = ExplicitSrcValues.at(0);
Value *Src2Value = ExplicitSrcValues.at(1);
Value *CFValue = getRegOrArgValue(EFLAGS::CF, MBBNo);
assert(CFValue && "Expected CF to be set for sbb instruction");
auto CFExtended = CastInst::Create(Instruction::ZExt, CFValue,
Src2Value->getType(), "", RaisedBB);
auto Src2AndCFValue =
BinaryOperator::CreateAdd(Src2Value, CFExtended, "", RaisedBB);
auto Result =
BinaryOperator::CreateSub(Src1Value, Src2AndCFValue, "", RaisedBB);
dstReg = MI.getOperand(DestOpIndex).getReg();
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, Result);
raisedValues->testAndSetEflagSSAValue(EFLAGS::OF, MI, Result);
raisedValues->testAndSetEflagSSAValue(EFLAGS::CF, MI, Result);
} break;
case X86::SQRTSDr:
case X86::SQRTSDr_Int:
case X86::SQRTSSr:
case X86::SQRTSSr_Int: {
LLVMContext &Ctx(MF.getFunction().getContext());
Type *InstrTy = getRaisedValues()->getSSEInstructionType(MI, Ctx);
Value *SrcValue = getRaisedValues()->reinterpretSSERegValue(
ExplicitSrcValues.at(0), InstrTy, RaisedBB);
Module *M = MR->getModule();
auto IntrinsicFunc = Intrinsic::getDeclaration(M, Intrinsic::sqrt, InstrTy);
Value *IntrinsicCallArgs[] = {SrcValue};
auto Result = CallInst::Create(
IntrinsicFunc, ArrayRef<Value *>(IntrinsicCallArgs), "", RaisedBB);
raisedValues->setInstMetadataRODataIndex(SrcValue, Result);
dstReg = MI.getOperand(DestOpIndex).getReg();
raisedValues->setPhysRegSSAValue(dstReg, MBBNo, Result);
} break;
default:
MI.dump();
assert(false && "Unhandled binary instruction");
}
return Success;
}