X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FX86%2FInstSelectSimple.cpp;h=2cc4e8367dfbdb5114695d258fcc86a7f6ea3a64;hb=19df3876e6dce016ec4c5ab28320a246ab285001;hp=a7c3c648c8b1a57217fc9051688e68e081e649f5;hpb=034acf0a3de01d80bc341e491fbc1dfa2779a577;p=oota-llvm.git diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp index a7c3c648c8b..2cc4e8367df 100644 --- a/lib/Target/X86/InstSelectSimple.cpp +++ b/lib/Target/X86/InstSelectSimple.cpp @@ -85,7 +85,8 @@ namespace { 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 { @@ -121,9 +122,11 @@ namespace { void visitBranchInst(BranchInst &BI); struct ValueRecord { + Value *Val; unsigned Reg; const Type *Ty; - ValueRecord(unsigned R, const Type *T) : Reg(R), Ty(T) {} + ValueRecord(unsigned R, const Type *T) : Val(0), Reg(R), Ty(T) {} + ValueRecord(Value *V) : Val(V), Reg(0), Ty(V->getType()) {} }; void doCall(const ValueRecord &Ret, MachineInstr *CallMI, const std::vector &Args); @@ -218,9 +221,12 @@ namespace { /// of the long value. /// unsigned makeAnotherReg(const Type *Ty) { + assert(dynamic_cast(TM.getRegisterInfo()) && + "Current target doesn't have X86 reg info??"); + const X86RegisterInfo *MRI = + static_cast(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. @@ -228,8 +234,7 @@ namespace { } // 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); } @@ -343,12 +348,7 @@ void ISel::copyConstantToRegister(MachineBasicBlock *MBB, if (Class == cLong) { // Copy the value into the register pair. - uint64_t Val; - if (C->getType()->isSigned()) - Val = cast(C)->getValue(); - else - Val = cast(C)->getValue(); - + uint64_t Val = cast(C)->getRawValue(); BMI(MBB, IP, X86::MOVir32, 1, R).addZImm(Val & 0xFFFFFFFF); BMI(MBB, IP, X86::MOVir32, 1, R+1).addZImm(Val >> 32); return; @@ -362,12 +362,9 @@ void ISel::copyConstantToRegister(MachineBasicBlock *MBB, if (C->getType() == Type::BoolTy) { BMI(MBB, IP, X86::MOVir8, 1, R).addZImm(C == ConstantBool::True); - } else if (C->getType()->isSigned()) { - ConstantSInt *CSI = cast(C); - BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CSI->getValue()); } else { - ConstantUInt *CUI = cast(C); - BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CUI->getValue()); + ConstantInt *CI = cast(C); + BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CI->getRawValue()); } } else if (ConstantFP *CFP = dyn_cast(C)) { double Value = CFP->getValue(); @@ -585,11 +582,8 @@ bool ISel::EmitComparisonGetSignedness(unsigned OpNum, Value *Op0, Value *Op1) { // Special case handling of: cmp R, i if (Class == cByte || Class == cShort || Class == cInt) if (ConstantInt *CI = dyn_cast(Op1)) { - uint64_t Op1v; - if (ConstantSInt *CSI = dyn_cast(CI)) - Op1v = CSI->getValue(); - else - Op1v = cast(CI)->getValue(); + uint64_t Op1v = cast(CI)->getRawValue(); + // Mask off any upper bits of the constant, if there are any... Op1v &= (1ULL << (8 << Class)) - 1; @@ -652,6 +646,8 @@ bool ISel::EmitComparisonGetSignedness(unsigned OpNum, Value *Op0, Value *Op1) { BuildMI(BB, SetCCOpcodeTab[0][OpNum], 0, X86::AL); BuildMI(BB, X86::CMPrr32, 2).addReg(Op0r+1).addReg(Op1r+1); BuildMI(BB, SetCCOpcodeTab[isSigned][OpNum], 0, X86::BL); + BuildMI(BB, X86::IMPLICIT_DEF, 0, X86::BH); + BuildMI(BB, X86::IMPLICIT_DEF, 0, X86::AH); BuildMI(BB, X86::CMOVErr16, 2, X86::BX).addReg(X86::BX).addReg(X86::AX); // NOTE: visitSetCondInst knows that the value is dumped into the BL // register at this point for long values... @@ -687,24 +683,28 @@ void ISel::visitSetCondInst(SetCondInst &I) { /// operand, in the specified target register. void ISel::promote32(unsigned targetReg, const ValueRecord &VR) { bool isUnsigned = VR.Ty->isUnsigned(); + + // Make sure we have the register number for this value... + unsigned Reg = VR.Val ? getReg(VR.Val) : VR.Reg; + switch (getClassB(VR.Ty)) { case cByte: // Extend value into target register (8->32) if (isUnsigned) - BuildMI(BB, X86::MOVZXr32r8, 1, targetReg).addReg(VR.Reg); + BuildMI(BB, X86::MOVZXr32r8, 1, targetReg).addReg(Reg); else - BuildMI(BB, X86::MOVSXr32r8, 1, targetReg).addReg(VR.Reg); + BuildMI(BB, X86::MOVSXr32r8, 1, targetReg).addReg(Reg); break; case cShort: // Extend value into target register (16->32) if (isUnsigned) - BuildMI(BB, X86::MOVZXr32r16, 1, targetReg).addReg(VR.Reg); + BuildMI(BB, X86::MOVZXr32r16, 1, targetReg).addReg(Reg); else - BuildMI(BB, X86::MOVSXr32r16, 1, targetReg).addReg(VR.Reg); + BuildMI(BB, X86::MOVSXr32r16, 1, targetReg).addReg(Reg); break; case cInt: // Move value into target register (32->32) - BuildMI(BB, X86::MOVrr32, 1, targetReg).addReg(VR.Reg); + BuildMI(BB, X86::MOVrr32, 1, targetReg).addReg(Reg); break; default: assert(0 && "Unpromotable operand class in promote32"); @@ -856,7 +856,7 @@ void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI, // Arguments go on the stack in reverse order, as specified by the ABI. unsigned ArgOffset = 0; for (unsigned i = 0, e = Args.size(); i != e; ++i) { - unsigned ArgReg = Args[i].Reg; + unsigned ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg; switch (getClassB(Args[i].Ty)) { case cByte: case cShort: { @@ -953,8 +953,7 @@ void ISel::visitCallInst(CallInst &CI) { std::vector Args; for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i) - Args.push_back(ValueRecord(getReg(CI.getOperand(i)), - CI.getOperand(i)->getType())); + Args.push_back(ValueRecord(CI.getOperand(i))); unsigned DestReg = CI.getType() != Type::VoidTy ? getReg(CI) : 0; doCall(ValueRecord(DestReg, CI.getType()), TheCall, Args); @@ -978,6 +977,14 @@ void ISel::visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &CI) { 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!"); } } @@ -1053,11 +1060,7 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *BB, assert(Class < 3 && "General code handles 64-bit integer types!"); unsigned Opcode = OpcodeTab[OperatorClass][Class]; unsigned Op0r = getReg(Op0, BB, IP); - uint64_t Op1v; - if (ConstantSInt *CSI = dyn_cast(Op1C)) - Op1v = CSI->getValue(); - else - Op1v = cast(Op1C)->getValue(); + uint64_t Op1v = cast(Op1C)->getRawValue(); // Mask off any upper bits of the constant, if there are any... Op1v &= (1ULL << (8 << Class)) - 1; @@ -1139,21 +1142,21 @@ void ISel::visitMul(BinaryOperator &I) { /// instructions work differently for signed and unsigned operands. /// void ISel::visitDivRem(BinaryOperator &I) { - unsigned Class = getClass(I.getType()); - unsigned Op0Reg = getReg(I.getOperand(0)); - unsigned Op1Reg = getReg(I.getOperand(1)); - unsigned ResultReg = getReg(I); + unsigned Class = getClass(I.getType()); + unsigned Op0Reg, Op1Reg, ResultReg = getReg(I); switch (Class) { case cFP: // Floating point divide - if (I.getOpcode() == Instruction::Div) + 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); - else { // Floating point remainder... + } else { // Floating point remainder... MachineInstr *TheCall = BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("fmod", true); std::vector Args; - Args.push_back(ValueRecord(Op0Reg, Type::DoubleTy)); - Args.push_back(ValueRecord(Op1Reg, Type::DoubleTy)); + Args.push_back(ValueRecord(I.getOperand(0))); + Args.push_back(ValueRecord(I.getOperand(1))); doCall(ValueRecord(ResultReg, Type::DoubleTy), TheCall, Args); } return; @@ -1167,8 +1170,8 @@ void ISel::visitDivRem(BinaryOperator &I) { BuildMI(X86::CALLpcrel32, 1).addExternalSymbol(FnName[NameIdx], true); std::vector Args; - Args.push_back(ValueRecord(Op0Reg, Type::LongTy)); - Args.push_back(ValueRecord(Op1Reg, Type::LongTy)); + Args.push_back(ValueRecord(I.getOperand(0))); + Args.push_back(ValueRecord(I.getOperand(1))); doCall(ValueRecord(ResultReg, Type::LongTy), TheCall, Args); return; } @@ -1179,7 +1182,7 @@ void ISel::visitDivRem(BinaryOperator &I) { 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 }; @@ -1193,17 +1196,21 @@ void ISel::visitDivRem(BinaryOperator &I) { 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); 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); } // Emit the appropriate divide or remainder instruction... + Op1Reg = getReg(I.getOperand(1)); BuildMI(BB, DivOpcode[isSigned][Class], 1).addReg(Op1Reg); // Figure out which register we want to pick the result out of... @@ -1425,7 +1432,7 @@ void ISel::visitLoadInst(LoadInst &I) { 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(); @@ -1525,7 +1532,7 @@ void ISel::visitStoreInst(StoreInst &I) { 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) { @@ -1806,9 +1813,10 @@ void ISel::emitCastOperation(MachineBasicBlock *BB, 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!"); } @@ -2071,8 +2079,6 @@ void ISel::visitMallocInst(MallocInst &I) { unsigned Op1Reg = getReg(I.getOperand(0)); MachineBasicBlock::iterator MBBI = BB->end(); doMultiply(BB, MBBI, Arg, Type::UIntTy, Op0Reg, Op1Reg); - - } std::vector Args; @@ -2088,18 +2094,17 @@ void ISel::visitMallocInst(MallocInst &I) { /// void ISel::visitFreeInst(FreeInst &I) { std::vector Args; - Args.push_back(ValueRecord(getReg(I.getOperand(0)), - I.getOperand(0)->getType())); + Args.push_back(ValueRecord(I.getOperand(0))); MachineInstr *TheCall = BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("free", true); doCall(ValueRecord(0, Type::VoidTy), TheCall, 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) { +FunctionPass *createX86SimpleInstructionSelector(TargetMachine &TM) { return new ISel(TM); }