/// have a destination register in mind.
inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB,
MachineBasicBlock::iterator &I,
- MachineOpCode Opcode,
- unsigned NumOperands,
+ int Opcode, unsigned NumOperands,
unsigned DestReg) {
assert(I >= MBB->begin() && I <= MBB->end() && "Bad iterator!");
MachineInstr *MI = new MachineInstr(Opcode, NumOperands+1, true, true);
/// instruction at as well as a basic block.
inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB,
MachineBasicBlock::iterator &I,
- MachineOpCode Opcode,
- unsigned NumOperands) {
+ int Opcode, unsigned NumOperands) {
assert(I >= MBB->begin() && I <= MBB->end() && "Bad iterator!");
MachineInstr *MI = new MachineInstr(Opcode, NumOperands, true, true);
I = MBB->insert(I, MI)+1;
RegMap.clear();
MBBMap.clear();
F = 0;
- return false; // We never modify the LLVM itself.
+ // We always build a machine code representation for the function
+ return true;
}
virtual const char *getPassName() const {
/// of the long value.
///
unsigned makeAnotherReg(const Type *Ty) {
+ assert(dynamic_cast<const X86RegisterInfo*>(TM.getRegisterInfo()) &&
+ "Current target doesn't have X86 reg info??");
+ const X86RegisterInfo *MRI =
+ static_cast<const X86RegisterInfo*>(TM.getRegisterInfo());
if (Ty == Type::LongTy || Ty == Type::ULongTy) {
- const TargetRegisterClass *RC =
- TM.getRegisterInfo()->getRegClassForType(Type::IntTy);
+ const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy);
// Create the lower part
F->getSSARegMap()->createVirtualRegister(RC);
// Create the upper part.
}
// Add the mapping of regnumber => reg class to MachineFunction
- const TargetRegisterClass *RC =
- TM.getRegisterInfo()->getRegClassForType(Ty);
+ const TargetRegisterClass *RC = MRI->getRegClassForType(Ty);
return F->getSSARegMap()->createVirtualRegister(RC);
}
if (Class == cLong) {
// Copy the value into the register pair.
- uint64_t Val;
- if (C->getType()->isSigned())
- Val = cast<ConstantSInt>(C)->getValue();
- else
- Val = cast<ConstantUInt>(C)->getValue();
-
+ uint64_t Val = cast<ConstantInt>(C)->getRawValue();
BMI(MBB, IP, X86::MOVir32, 1, R).addZImm(Val & 0xFFFFFFFF);
BMI(MBB, IP, X86::MOVir32, 1, R+1).addZImm(Val >> 32);
return;
if (C->getType() == Type::BoolTy) {
BMI(MBB, IP, X86::MOVir8, 1, R).addZImm(C == ConstantBool::True);
- } else if (C->getType()->isSigned()) {
- ConstantSInt *CSI = cast<ConstantSInt>(C);
- BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CSI->getValue());
} else {
- ConstantUInt *CUI = cast<ConstantUInt>(C);
- BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue());
+ ConstantInt *CI = cast<ConstantInt>(C);
+ BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CI->getRawValue());
}
} else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
double Value = CFP->getValue();
// The arguments are already supposed to be of the same type.
const Type *CompTy = Op0->getType();
bool isSigned = CompTy->isSigned();
- unsigned reg1 = getReg(Op0);
- unsigned reg2 = getReg(Op1);
-
unsigned Class = getClassB(CompTy);
+ unsigned Op0r = getReg(Op0);
+
+ // Special case handling of: cmp R, i
+ if (Class == cByte || Class == cShort || Class == cInt)
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
+ uint64_t Op1v = cast<ConstantInt>(CI)->getRawValue();
+
+ // Mask off any upper bits of the constant, if there are any...
+ Op1v &= (1ULL << (8 << Class)) - 1;
+
+ switch (Class) {
+ case cByte: BuildMI(BB, X86::CMPri8, 2).addReg(Op0r).addZImm(Op1v);break;
+ case cShort: BuildMI(BB, X86::CMPri16,2).addReg(Op0r).addZImm(Op1v);break;
+ case cInt: BuildMI(BB, X86::CMPri32,2).addReg(Op0r).addZImm(Op1v);break;
+ default:
+ assert(0 && "Invalid class!");
+ }
+ return isSigned;
+ }
+
+ unsigned Op1r = getReg(Op1);
switch (Class) {
default: assert(0 && "Unknown type class!");
// Emit: cmp <var1>, <var2> (do the comparison). We can
// compare 8-bit with 8-bit, 16-bit with 16-bit, 32-bit with
// 32-bit.
case cByte:
- BuildMI(BB, X86::CMPrr8, 2).addReg(reg1).addReg(reg2);
+ BuildMI(BB, X86::CMPrr8, 2).addReg(Op0r).addReg(Op1r);
break;
case cShort:
- BuildMI(BB, X86::CMPrr16, 2).addReg(reg1).addReg(reg2);
+ BuildMI(BB, X86::CMPrr16, 2).addReg(Op0r).addReg(Op1r);
break;
case cInt:
- BuildMI(BB, X86::CMPrr32, 2).addReg(reg1).addReg(reg2);
+ BuildMI(BB, X86::CMPrr32, 2).addReg(Op0r).addReg(Op1r);
break;
case cFP:
- BuildMI(BB, X86::FpUCOM, 2).addReg(reg1).addReg(reg2);
+ BuildMI(BB, X86::FpUCOM, 2).addReg(Op0r).addReg(Op1r);
BuildMI(BB, X86::FNSTSWr8, 0);
BuildMI(BB, X86::SAHF, 1);
isSigned = false; // Compare with unsigned operators
unsigned LoTmp = makeAnotherReg(Type::IntTy);
unsigned HiTmp = makeAnotherReg(Type::IntTy);
unsigned FinalTmp = makeAnotherReg(Type::IntTy);
- BuildMI(BB, X86::XORrr32, 2, LoTmp).addReg(reg1).addReg(reg2);
- BuildMI(BB, X86::XORrr32, 2, HiTmp).addReg(reg1+1).addReg(reg2+1);
+ BuildMI(BB, X86::XORrr32, 2, LoTmp).addReg(Op0r).addReg(Op1r);
+ BuildMI(BB, X86::XORrr32, 2, HiTmp).addReg(Op0r+1).addReg(Op1r+1);
BuildMI(BB, X86::ORrr32, 2, FinalTmp).addReg(LoTmp).addReg(HiTmp);
break; // Allow the sete or setne to be generated from flags set by OR
} else {
// classes! Until then, hardcode registers so that we can deal with their
// aliases (because we don't have conditional byte moves).
//
- BuildMI(BB, X86::CMPrr32, 2).addReg(reg1).addReg(reg2);
+ BuildMI(BB, X86::CMPrr32, 2).addReg(Op0r).addReg(Op1r);
BuildMI(BB, SetCCOpcodeTab[0][OpNum], 0, X86::AL);
- BuildMI(BB, X86::CMPrr32, 2).addReg(reg1+1).addReg(reg2+1);
+ BuildMI(BB, X86::CMPrr32, 2).addReg(Op0r+1).addReg(Op1r+1);
BuildMI(BB, SetCCOpcodeTab[isSigned][OpNum], 0, X86::BL);
BuildMI(BB, X86::CMOVErr16, 2, X86::BX).addReg(X86::BX).addReg(X86::AX);
// NOTE: visitSetCondInst knows that the value is dumped into the BL
addDirectMem(BuildMI(BB, X86::MOVrm32, 5), TmpReg2).addReg(TmpReg1);
return;
+ case LLVMIntrinsic::longjmp:
+ BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("abort", true);
+ return;
+
+ case LLVMIntrinsic::setjmp:
+ // Setjmp always returns zero...
+ BuildMI(BB, X86::MOVir32, 1, getReg(CI)).addZImm(0);
+ return;
default: assert(0 && "Unknown intrinsic for X86!");
}
}
Value *Op0, Value *Op1,
unsigned OperatorClass,unsigned TargetReg){
unsigned Class = getClassB(Op0->getType());
+ if (!isa<ConstantInt>(Op1) || Class == cLong) {
+ static const unsigned OpcodeTab[][4] = {
+ // Arithmetic operators
+ { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32, X86::FpADD }, // ADD
+ { X86::SUBrr8, X86::SUBrr16, X86::SUBrr32, X86::FpSUB }, // SUB
+
+ // Bitwise operators
+ { X86::ANDrr8, X86::ANDrr16, X86::ANDrr32, 0 }, // AND
+ { X86:: ORrr8, X86:: ORrr16, X86:: ORrr32, 0 }, // OR
+ { X86::XORrr8, X86::XORrr16, X86::XORrr32, 0 }, // XOR
+ };
+
+ bool isLong = false;
+ if (Class == cLong) {
+ isLong = true;
+ Class = cInt; // Bottom 32 bits are handled just like ints
+ }
+
+ unsigned Opcode = OpcodeTab[OperatorClass][Class];
+ assert(Opcode && "Floating point arguments to logical inst?");
+ unsigned Op0r = getReg(Op0, BB, IP);
+ unsigned Op1r = getReg(Op1, BB, IP);
+ BMI(BB, IP, Opcode, 2, TargetReg).addReg(Op0r).addReg(Op1r);
+
+ if (isLong) { // Handle the upper 32 bits of long values...
+ static const unsigned TopTab[] = {
+ X86::ADCrr32, X86::SBBrr32, X86::ANDrr32, X86::ORrr32, X86::XORrr32
+ };
+ BMI(BB, IP, TopTab[OperatorClass], 2,
+ TargetReg+1).addReg(Op0r+1).addReg(Op1r+1);
+ }
+ } else {
+ // Special case: op Reg, <const>
+ ConstantInt *Op1C = cast<ConstantInt>(Op1);
- static const unsigned OpcodeTab[][4] = {
- // Arithmetic operators
- { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32, X86::FpADD }, // ADD
- { X86::SUBrr8, X86::SUBrr16, X86::SUBrr32, X86::FpSUB }, // SUB
+ static const unsigned OpcodeTab[][3] = {
+ // Arithmetic operators
+ { X86::ADDri8, X86::ADDri16, X86::ADDri32 }, // ADD
+ { X86::SUBri8, X86::SUBri16, X86::SUBri32 }, // SUB
+
+ // Bitwise operators
+ { X86::ANDri8, X86::ANDri16, X86::ANDri32 }, // AND
+ { X86:: ORri8, X86:: ORri16, X86:: ORri32 }, // OR
+ { X86::XORri8, X86::XORri16, X86::XORri32 }, // XOR
+ };
- // Bitwise operators
- { X86::ANDrr8, X86::ANDrr16, X86::ANDrr32, 0 }, // AND
- { X86:: ORrr8, X86:: ORrr16, X86:: ORrr32, 0 }, // OR
- { X86::XORrr8, X86::XORrr16, X86::XORrr32, 0 }, // XOR
- };
+ assert(Class < 3 && "General code handles 64-bit integer types!");
+ unsigned Opcode = OpcodeTab[OperatorClass][Class];
+ unsigned Op0r = getReg(Op0, BB, IP);
+ uint64_t Op1v = cast<ConstantInt>(Op1C)->getRawValue();
- bool isLong = false;
- if (Class == cLong) {
- isLong = true;
- Class = cInt; // Bottom 32 bits are handled just like ints
- }
-
- unsigned Opcode = OpcodeTab[OperatorClass][Class];
- assert(Opcode && "Floating point arguments to logical inst?");
- unsigned Op0r = getReg(Op0, BB, IP);
- unsigned Op1r = getReg(Op1, BB, IP);
- BMI(BB, IP, Opcode, 2, TargetReg).addReg(Op0r).addReg(Op1r);
-
- if (isLong) { // Handle the upper 32 bits of long values...
- static const unsigned TopTab[] = {
- X86::ADCrr32, X86::SBBrr32, X86::ANDrr32, X86::ORrr32, X86::XORrr32
- };
- BMI(BB, IP, TopTab[OperatorClass], 2,
- TargetReg+1).addReg(Op0r+1).addReg(Op1r+1);
+ // Mask off any upper bits of the constant, if there are any...
+ Op1v &= (1ULL << (8 << Class)) - 1;
+ BMI(BB, IP, Opcode, 2, TargetReg).addReg(Op0r).addZImm(Op1v);
}
}
/// registers op0Reg and op1Reg, and put the result in DestReg. The type of the
/// result should be given as DestTy.
///
-/// FIXME: doMultiply should use one of the two address IMUL instructions!
-///
void ISel::doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI,
unsigned DestReg, const Type *DestTy,
unsigned op0Reg, unsigned op1Reg) {
case cFP: // Floating point multiply
BMI(BB, MBBI, X86::FpMUL, 2, DestReg).addReg(op0Reg).addReg(op1Reg);
return;
+ case cInt:
+ case cShort:
+ BMI(BB, MBBI, Class == cInt ? X86::IMULr32 : X86::IMULr16, 2, DestReg)
+ .addReg(op0Reg).addReg(op1Reg);
+ return;
+ case cByte:
+ // Must use the MUL instruction, which forces use of AL...
+ BMI(MBB, MBBI, X86::MOVrr8, 1, X86::AL).addReg(op0Reg);
+ BMI(MBB, MBBI, X86::MULr8, 1).addReg(op1Reg);
+ BMI(MBB, MBBI, X86::MOVrr8, 1, DestReg).addReg(X86::AL);
+ return;
default:
case cLong: assert(0 && "doMultiply cannot operate on LONG values!");
- case cByte:
- case cShort:
- case cInt: // Small integerals, handled below...
- break;
}
-
- static const unsigned Regs[] ={ X86::AL , X86::AX , X86::EAX };
- static const unsigned MulOpcode[]={ X86::MULr8 , X86::MULr16 , X86::MULr32 };
- static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 };
- unsigned Reg = Regs[Class];
-
- // Emit a MOV to put the first operand into the appropriately-sized
- // subreg of EAX.
- BMI(MBB, MBBI, MovOpcode[Class], 1, Reg).addReg(op0Reg);
-
- // Emit the appropriate multiply instruction.
- BMI(MBB, MBBI, MulOpcode[Class], 1).addReg(op1Reg);
-
- // Emit another MOV to put the result into the destination register.
- BMI(MBB, MBBI, MovOpcode[Class], 1, DestReg).addReg(Reg);
}
/// visitMul - Multiplies are not simple binary operators because they must deal
BuildMI(BB, X86::MOVrr32, 1, OverflowReg).addReg(X86::EDX); // AL*BL >> 32
MachineBasicBlock::iterator MBBI = BB->end();
- unsigned AHBLReg = makeAnotherReg(Type::UIntTy);
- doMultiply(BB, MBBI, AHBLReg, Type::UIntTy, Op0Reg+1, Op1Reg); // AH*BL
+ unsigned AHBLReg = makeAnotherReg(Type::UIntTy); // AH*BL
+ BMI(BB, MBBI, X86::IMULr32, 2, AHBLReg).addReg(Op0Reg+1).addReg(Op1Reg);
unsigned AHBLplusOverflowReg = makeAnotherReg(Type::UIntTy);
BuildMI(BB, X86::ADDrr32, 2, // AH*BL+(AL*BL >> 32)
AHBLplusOverflowReg).addReg(AHBLReg).addReg(OverflowReg);
MBBI = BB->end();
- unsigned ALBHReg = makeAnotherReg(Type::UIntTy);
- doMultiply(BB, MBBI, ALBHReg, Type::UIntTy, Op0Reg, Op1Reg+1); // AL*BH
+ unsigned ALBHReg = makeAnotherReg(Type::UIntTy); // AL*BH
+ BMI(BB, MBBI, X86::IMULr32, 2, ALBHReg).addReg(Op0Reg).addReg(Op1Reg+1);
BuildMI(BB, X86::ADDrr32, 2, // AL*BH + AH*BL + (AL*BL >> 32)
DestReg+1).addReg(AHBLplusOverflowReg).addReg(ALBHReg);
static const unsigned Regs[] ={ X86::AL , X86::AX , X86::EAX };
static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 };
- static const unsigned ExtOpcode[]={ X86::CBW , X86::CWD , X86::CDQ };
+ static const unsigned SarOpcode[]={ X86::SARir8, X86::SARir16, X86::SARir32 };
static const unsigned ClrOpcode[]={ X86::XORrr8, X86::XORrr16, X86::XORrr32 };
static const unsigned ExtRegs[] ={ X86::AH , X86::DX , X86::EDX };
if (isSigned) {
// Emit a sign extension instruction...
- BuildMI(BB, ExtOpcode[Class], 0);
+ unsigned ShiftResult = makeAnotherReg(I.getType());
+ BuildMI(BB, SarOpcode[Class], 2, ShiftResult).addReg(Op0Reg).addZImm(31);
+ BuildMI(BB, 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);
unsigned SrcAddrReg = getReg(I.getOperand(0));
unsigned DestReg = getReg(I);
- unsigned Class = getClass(I.getType());
+ unsigned Class = getClassB(I.getType());
switch (Class) {
case cFP: {
MachineBasicBlock::iterator MBBI = BB->end();
unsigned ValReg = getReg(I.getOperand(0));
unsigned AddressReg = getReg(I.getOperand(1));
- unsigned Class = getClass(I.getOperand(0)->getType());
+ unsigned Class = getClassB(I.getOperand(0)->getType());
switch (Class) {
case cLong:
if (isLittleEndian) {
/// visitCastInst - Here we have various kinds of copying with or without
/// sign extension going on.
void ISel::visitCastInst(CastInst &CI) {
+ Value *Op = CI.getOperand(0);
+ // If this is a cast from a 32-bit integer to a Long type, and the only uses
+ // of the case are GEP instructions, then the cast does not need to be
+ // generated explicitly, it will be folded into the GEP.
+ if (CI.getType() == Type::LongTy &&
+ (Op->getType() == Type::IntTy || Op->getType() == Type::UIntTy)) {
+ bool AllUsesAreGEPs = true;
+ for (Value::use_iterator I = CI.use_begin(), E = CI.use_end(); I != E; ++I)
+ if (!isa<GetElementPtrInst>(*I)) {
+ AllUsesAreGEPs = false;
+ break;
+ }
+
+ // No need to codegen this cast if all users are getelementptr instrs...
+ if (AllUsesAreGEPs) return;
+ }
+
unsigned DestReg = getReg(CI);
MachineBasicBlock::iterator MI = BB->end();
- emitCastOperation(BB, MI, CI.getOperand(0), CI.getType(), DestReg);
+ emitCastOperation(BB, MI, Op, CI.getType(), DestReg);
}
/// emitCastOperation - Common code shared between visitCastInst and
// Implement casts to bool by using compare on the operand followed by set if
// not zero on the result.
if (DestTy == Type::BoolTy) {
- if (SrcClass == cFP || SrcClass == cLong)
- abort(); // FIXME: implement cast (long & FP) to bool
-
- BMI(BB, IP, X86::CMPri8, 2).addReg(SrcReg).addZImm(0);
+ switch (SrcClass) {
+ case cByte:
+ BMI(BB, IP, X86::TESTrr8, 2).addReg(SrcReg).addReg(SrcReg);
+ break;
+ case cShort:
+ BMI(BB, IP, X86::TESTrr16, 2).addReg(SrcReg).addReg(SrcReg);
+ break;
+ case cInt:
+ BMI(BB, IP, X86::TESTrr32, 2).addReg(SrcReg).addReg(SrcReg);
+ break;
+ case cLong: {
+ unsigned TmpReg = makeAnotherReg(Type::IntTy);
+ BMI(BB, IP, X86::ORrr32, 2, TmpReg).addReg(SrcReg).addReg(SrcReg+1);
+ break;
+ }
+ case cFP:
+ assert(0 && "FIXME: implement cast FP to bool");
+ abort();
+ }
+
+ // If the zero flag is not set, then the value is true, set the byte to
+ // true.
BMI(BB, IP, X86::SETNEr, 1, DestReg);
return;
}
case cByte: StoreTy = Type::ShortTy; StoreClass = cShort; break;
case cShort: StoreTy = Type::IntTy; StoreClass = cInt; break;
case cInt: StoreTy = Type::LongTy; StoreClass = cLong; break;
- case cLong:
- assert(0 &&"FIXME not implemented: cast FP to unsigned long long");
- abort();
+ // The following treatment of cLong may not be perfectly right,
+ // but it survives chains of casts of the form
+ // double->ulong->double.
+ case cLong: StoreTy = Type::LongTy; StoreClass = cLong; break;
default: assert(0 && "Unknown store class!");
}
// time.
assert(idx->getType() == Type::LongTy && "Bad GEP array index!");
+ // Most GEP instructions use a [cast (int/uint) to LongTy] as their
+ // operand on X86. Handle this case directly now...
+ if (CastInst *CI = dyn_cast<CastInst>(idx))
+ if (CI->getOperand(0)->getType() == Type::IntTy ||
+ CI->getOperand(0)->getType() == Type::UIntTy)
+ idx = CI->getOperand(0);
+
// We want to add BaseReg to(idxReg * sizeof ElementType). First, we
// must find the size of the pointed-to type (Not coincidentally, the next
// type is the type of the elements in the array).
unsigned Op1Reg = getReg(I.getOperand(0));
MachineBasicBlock::iterator MBBI = BB->end();
doMultiply(BB, MBBI, Arg, Type::UIntTy, Op0Reg, Op1Reg);
-
-
}
std::vector<ValueRecord> Args;
}
-/// createSimpleX86InstructionSelector - This pass converts an LLVM function
+/// 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.
///
-Pass *createSimpleX86InstructionSelector(TargetMachine &TM) {
+Pass *createX86SimpleInstructionSelector(TargetMachine &TM) {
return new ISel(TM);
}