#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/InstVisitor.h"
+namespace llvm {
+
/// BMI - A special BuildMI variant that takes an iterator to insert the
/// instruction at as well as a basic block. This is the version for when you
/// have a destination register in mind.
void doCall(const ValueRecord &Ret, MachineInstr *CallMI,
const std::vector<ValueRecord> &Args);
void visitCallInst(CallInst &I);
- void visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &I);
+ void visitIntrinsicCall(Intrinsic::ID ID, CallInst &I);
// Arithmetic operators
void visitSimpleBinary(BinaryOperator &B, unsigned OpcodeClass);
///
void promote32(unsigned targetReg, const ValueRecord &VR);
- /// EmitByteSwap - Byteswap SrcReg into DestReg.
- ///
- void EmitByteSwap(unsigned DestReg, unsigned SrcReg, unsigned Class);
-
/// emitGEPOperation - Common code shared between visitGetElementPtrInst and
/// constant expression GEP support.
///
Value *Op0, Value *Op1,
unsigned OperatorClass, unsigned TargetReg);
+ void emitDivRemOperation(MachineBasicBlock *BB,
+ MachineBasicBlock::iterator &IP,
+ unsigned Op0Reg, unsigned Op1Reg, bool isDiv,
+ const Type *Ty, unsigned TargetReg);
+
/// emitSetCCOperation - Common code shared between visitSetCondInst and
/// constant expression support.
void emitSetCCOperation(MachineBasicBlock *BB,
Class, R);
return;
+ case Instruction::Mul: {
+ unsigned Op0Reg = getReg(CE->getOperand(0), MBB, IP);
+ unsigned Op1Reg = getReg(CE->getOperand(1), MBB, IP);
+ doMultiply(MBB, IP, R, CE->getType(), Op0Reg, Op1Reg);
+ return;
+ }
+ case Instruction::Div:
+ case Instruction::Rem: {
+ unsigned Op0Reg = getReg(CE->getOperand(0), MBB, IP);
+ unsigned Op1Reg = getReg(CE->getOperand(1), MBB, IP);
+ emitDivRemOperation(MBB, IP, Op0Reg, Op1Reg,
+ CE->getOpcode() == Instruction::Div,
+ CE->getType(), R);
+ return;
+ }
+
case Instruction::SetNE:
case Instruction::SetEQ:
case Instruction::SetLT:
MachineInstr *TheCall;
if (Function *F = CI.getCalledFunction()) {
// Is it an intrinsic function call?
- if (LLVMIntrinsic::ID ID = (LLVMIntrinsic::ID)F->getIntrinsicID()) {
+ if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) {
visitIntrinsicCall(ID, CI); // Special intrinsics are not handled here
return;
}
}
-void ISel::visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &CI) {
+void ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) {
unsigned TmpReg1, TmpReg2;
switch (ID) {
- case LLVMIntrinsic::va_start:
+ case Intrinsic::va_start:
// Get the address of the first vararg value...
TmpReg1 = getReg(CI);
addFrameReference(BuildMI(BB, X86::LEAr32, 5, TmpReg1), VarArgsFrameIndex);
return;
- case LLVMIntrinsic::va_copy:
+ case Intrinsic::va_copy:
TmpReg1 = getReg(CI);
TmpReg2 = getReg(CI.getOperand(1));
BuildMI(BB, X86::MOVrr32, 1, TmpReg1).addReg(TmpReg2);
return;
- case LLVMIntrinsic::va_end: return; // Noop on X86
+ case Intrinsic::va_end: return; // Noop on X86
- case LLVMIntrinsic::longjmp:
- case LLVMIntrinsic::siglongjmp:
+ case Intrinsic::longjmp:
+ case Intrinsic::siglongjmp:
BuildMI(BB, X86::CALLpcrel32, 1).addExternalSymbol("abort", true);
return;
- case LLVMIntrinsic::setjmp:
- case LLVMIntrinsic::sigsetjmp:
+ case Intrinsic::setjmp:
+ case Intrinsic::sigsetjmp:
// Setjmp always returns zero...
BuildMI(BB, X86::MOVir32, 1, getReg(CI)).addZImm(0);
return;
/// instructions work differently for signed and unsigned operands.
///
void ISel::visitDivRem(BinaryOperator &I) {
- unsigned Class = getClass(I.getType());
- unsigned Op0Reg, Op1Reg, ResultReg = getReg(I);
+ unsigned Op0Reg = getReg(I.getOperand(0));
+ unsigned Op1Reg = getReg(I.getOperand(1));
+ unsigned ResultReg = getReg(I);
+ MachineBasicBlock::iterator IP = BB->end();
+ emitDivRemOperation(BB, IP, Op0Reg, Op1Reg, I.getOpcode() == Instruction::Div,
+ I.getType(), ResultReg);
+}
+
+void ISel::emitDivRemOperation(MachineBasicBlock *BB,
+ MachineBasicBlock::iterator &IP,
+ unsigned Op0Reg, unsigned Op1Reg, bool isDiv,
+ const Type *Ty, unsigned ResultReg) {
+ unsigned Class = getClass(Ty);
switch (Class) {
case cFP: // Floating point divide
- if (I.getOpcode() == Instruction::Div) {
- Op0Reg = getReg(I.getOperand(0));
- Op1Reg = getReg(I.getOperand(1));
- BuildMI(BB, X86::FpDIV, 2, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
+ if (isDiv) {
+ BMI(BB, IP, X86::FpDIV, 2, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
} else { // Floating point remainder...
MachineInstr *TheCall =
BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("fmod", true);
std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(I.getOperand(0)));
- Args.push_back(ValueRecord(I.getOperand(1)));
+ Args.push_back(ValueRecord(Op0Reg, Type::DoubleTy));
+ Args.push_back(ValueRecord(Op1Reg, Type::DoubleTy));
doCall(ValueRecord(ResultReg, Type::DoubleTy), TheCall, Args);
}
return;
static const char *FnName[] =
{ "__moddi3", "__divdi3", "__umoddi3", "__udivdi3" };
- unsigned NameIdx = I.getType()->isUnsigned()*2;
- NameIdx += I.getOpcode() == Instruction::Div;
+ unsigned NameIdx = Ty->isUnsigned()*2 + isDiv;
MachineInstr *TheCall =
BuildMI(X86::CALLpcrel32, 1).addExternalSymbol(FnName[NameIdx], true);
std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(I.getOperand(0)));
- Args.push_back(ValueRecord(I.getOperand(1)));
+ Args.push_back(ValueRecord(Op0Reg, Type::LongTy));
+ Args.push_back(ValueRecord(Op1Reg, Type::LongTy));
doCall(ValueRecord(ResultReg, Type::LongTy), TheCall, Args);
return;
}
{ X86::IDIVr8, X86::IDIVr16, X86::IDIVr32, 0 }, // Signed division
};
- bool isSigned = I.getType()->isSigned();
+ bool isSigned = Ty->isSigned();
unsigned Reg = Regs[Class];
unsigned ExtReg = ExtRegs[Class];
// Put the first operand into one of the A registers...
- Op0Reg = getReg(I.getOperand(0));
- BuildMI(BB, MovOpcode[Class], 1, Reg).addReg(Op0Reg);
+ BMI(BB, IP, MovOpcode[Class], 1, Reg).addReg(Op0Reg);
if (isSigned) {
// Emit a sign extension instruction...
- unsigned ShiftResult = makeAnotherReg(I.getType());
- BuildMI(BB, SarOpcode[Class], 2, ShiftResult).addReg(Op0Reg).addZImm(31);
- BuildMI(BB, MovOpcode[Class], 1, ExtReg).addReg(ShiftResult);
+ unsigned ShiftResult = makeAnotherReg(Ty);
+ BMI(BB, IP, SarOpcode[Class], 2, ShiftResult).addReg(Op0Reg).addZImm(31);
+ BMI(BB, IP, MovOpcode[Class], 1, ExtReg).addReg(ShiftResult);
} else {
// If unsigned, emit a zeroing instruction... (reg = xor reg, reg)
- BuildMI(BB, ClrOpcode[Class], 2, ExtReg).addReg(ExtReg).addReg(ExtReg);
+ BMI(BB, IP, ClrOpcode[Class], 2, ExtReg).addReg(ExtReg).addReg(ExtReg);
}
// Emit the appropriate divide or remainder instruction...
- Op1Reg = getReg(I.getOperand(1));
- BuildMI(BB, DivOpcode[isSigned][Class], 1).addReg(Op1Reg);
+ BMI(BB, IP, DivOpcode[isSigned][Class], 1).addReg(Op1Reg);
// Figure out which register we want to pick the result out of...
- unsigned DestReg = (I.getOpcode() == Instruction::Div) ? Reg : ExtReg;
+ unsigned DestReg = isDiv ? Reg : ExtReg;
// Put the result into the destination register...
- BuildMI(BB, MovOpcode[Class], 1, ResultReg).addReg(DestReg);
+ BMI(BB, IP, MovOpcode[Class], 1, ResultReg).addReg(DestReg);
}
}
-/// EmitByteSwap - Byteswap SrcReg into DestReg.
-///
-void ISel::EmitByteSwap(unsigned DestReg, unsigned SrcReg, unsigned Class) {
- // Emit the byte swap instruction...
- switch (Class) {
- case cByte:
- // No byteswap necessary for 8 bit value...
- BuildMI(BB, X86::MOVrr8, 1, DestReg).addReg(SrcReg);
- break;
- case cInt:
- // Use the 32 bit bswap instruction to do a 32 bit swap...
- BuildMI(BB, X86::BSWAPr32, 1, DestReg).addReg(SrcReg);
- break;
-
- case cShort:
- // For 16 bit we have to use an xchg instruction, because there is no
- // 16-bit bswap. XCHG is necessarily not in SSA form, so we force things
- // into AX to do the xchg.
- //
- BuildMI(BB, X86::MOVrr16, 1, X86::AX).addReg(SrcReg);
- BuildMI(BB, X86::XCHGrr8, 2).addReg(X86::AL, MOTy::UseAndDef)
- .addReg(X86::AH, MOTy::UseAndDef);
- BuildMI(BB, X86::MOVrr16, 1, DestReg).addReg(X86::AX);
- break;
- default: assert(0 && "Cannot byteswap this class!");
- }
-}
-
-
/// visitLoadInst - Implement LLVM load instructions in terms of the x86 'mov'
/// instruction. The load and store instructions are the only place where we
/// need to worry about the memory layout of the target machine.
doCall(ValueRecord(0, Type::VoidTy), TheCall, Args);
}
-
/// createX86SimpleInstructionSelector - This pass converts an LLVM function
/// into a machine code representation is a very simple peep-hole fashion. The
/// generated code sucks but the implementation is nice and simple.
FunctionPass *createX86SimpleInstructionSelector(TargetMachine &TM) {
return new ISel(TM);
}
+
+} // End llvm namespace