//===----------------------------------------------------------------------===//
#include "X86.h"
-#include "X86InstrInfo.h"
#include "X86InstrBuilder.h"
+#include "X86InstrInfo.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Constants.h"
+#include "llvm/IntrinsicLowering.h"
#include "llvm/Pass.h"
-#include "llvm/Intrinsics.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/SSARegMap.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MRegisterInfo.h"
+#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/InstVisitor.h"
+#include "llvm/Support/CFG.h"
+using namespace llvm;
+
+//#define SMART_FP 1
/// 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.
inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator &I,
+ MachineBasicBlock::iterator I,
int Opcode, unsigned NumOperands,
unsigned DestReg) {
- assert(I >= MBB->begin() && I <= MBB->end() && "Bad iterator!");
MachineInstr *MI = new MachineInstr(Opcode, NumOperands+1, true, true);
- I = MBB->insert(I, MI)+1;
+ MBB->insert(I, MI);
return MachineInstrBuilder(MI).addReg(DestReg, MOTy::Def);
}
/// BMI - A special BuildMI variant that takes an iterator to insert the
/// instruction at as well as a basic block.
inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator &I,
+ MachineBasicBlock::iterator I,
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;
+ MBB->insert(I, MI);
return MachineInstrBuilder(MI);
}
MachineFunction *F; // The function we are compiling into
MachineBasicBlock *BB; // The current MBB we are compiling
int VarArgsFrameIndex; // FrameIndex for start of varargs area
+ int ReturnAddressIndex; // FrameIndex for the return address
std::map<Value*, unsigned> RegMap; // Mapping between Val's and SSA Regs
/// the entire function.
///
bool runOnFunction(Function &Fn) {
+ // First pass over the function, lower any unknown intrinsic functions
+ // with the IntrinsicLowering class.
+ LowerUnknownIntrinsicFunctionCalls(Fn);
+
F = &MachineFunction::construct(&Fn, TM);
// Create all of the machine basic blocks for the function...
BB = &F->front();
+ // Set up a frame object for the return address. This is used by the
+ // llvm.returnaddress & llvm.frameaddress intrinisics.
+ ReturnAddressIndex = F->getFrameInfo()->CreateFixedObject(4, -4);
+
// Copy incoming arguments off of the stack...
LoadArgumentsToVirtualRegs(Fn);
BB = MBBMap[&LLVM_BB];
}
+ /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
+ /// function, lowering any calls to unknown intrinsic functions into the
+ /// equivalent LLVM code.
+ void LowerUnknownIntrinsicFunctionCalls(Function &F);
+
/// LoadArgumentsToVirtualRegs - Load all of the arguments to this function
/// from the stack into virtual registers.
///
ValueRecord(Value *V) : Val(V), Reg(0), Ty(V->getType()) {}
};
void doCall(const ValueRecord &Ret, MachineInstr *CallMI,
- const std::vector<ValueRecord> &Args);
+ 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 visitSub(BinaryOperator &B) { visitSimpleBinary(B, 1); }
void doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI,
unsigned DestReg, const Type *DestTy,
- unsigned Op0Reg, unsigned Op1Reg);
+ unsigned Op0Reg, unsigned Op1Reg);
void doMultiplyConst(MachineBasicBlock *MBB,
MachineBasicBlock::iterator &MBBI,
unsigned DestReg, const Type *DestTy,
///
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,
MachineBasicBlock::iterator &IP,
Value *Op0, Value *Op1, unsigned Opcode,
unsigned TargetReg);
-
+
+ /// emitShiftOperation - Common code shared between visitShiftInst and
+ /// constant expression support.
+ void emitShiftOperation(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator &IP,
+ Value *Op, Value *ShiftAmount, bool isLeftShift,
+ const Type *ResultTy, unsigned DestReg);
+
/// copyConstantToRegister - Output the instructions required to put the
/// specified constant into the specified register.
const X86RegisterInfo *MRI =
static_cast<const X86RegisterInfo*>(TM.getRegisterInfo());
if (Ty == Type::LongTy || Ty == Type::ULongTy) {
- const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy);
- // Create the lower part
- F->getSSARegMap()->createVirtualRegister(RC);
- // Create the upper part.
- return F->getSSARegMap()->createVirtualRegister(RC)-1;
+ const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy);
+ // Create the lower part
+ F->getSSARegMap()->createVirtualRegister(RC);
+ // Create the upper part.
+ return F->getSSARegMap()->createVirtualRegister(RC)-1;
}
// Add the mapping of regnumber => reg class to MachineFunction
RegMap.erase(V); // Assign a new name to this constant if ref'd again
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
// Move the address of the global into the register
- BMI(MBB, IPt, X86::MOVir32, 1, Reg).addGlobalAddress(GV);
+ BMI(MBB, IPt, X86::MOVri32, 1, Reg).addGlobalAddress(GV);
RegMap.erase(V); // Assign a new name to this address if ref'd again
}
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:
CE->getOpcode(), R);
return;
+ case Instruction::Shl:
+ case Instruction::Shr:
+ emitShiftOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1),
+ CE->getOpcode() == Instruction::Shl, CE->getType(), R);
+ return;
+
default:
std::cerr << "Offending expr: " << C << "\n";
assert(0 && "Constant expression not yet handled!\n");
if (Class == cLong) {
// Copy the value into the register pair.
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);
+ BMI(MBB, IP, X86::MOVri32, 1, R).addZImm(Val & 0xFFFFFFFF);
+ BMI(MBB, IP, X86::MOVri32, 1, R+1).addZImm(Val >> 32);
return;
}
assert(Class <= cInt && "Type not handled yet!");
static const unsigned IntegralOpcodeTab[] = {
- X86::MOVir8, X86::MOVir16, X86::MOVir32
+ X86::MOVri8, X86::MOVri16, X86::MOVri32
};
if (C->getType() == Type::BoolTy) {
- BMI(MBB, IP, X86::MOVir8, 1, R).addZImm(C == ConstantBool::True);
+ BMI(MBB, IP, X86::MOVri8, 1, R).addZImm(C == ConstantBool::True);
} else {
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();
- if (Value == +0.0)
+ if (CFP->isExactlyValue(+0.0))
BMI(MBB, IP, X86::FLD0, 0, R);
- else if (Value == +1.0)
+ else if (CFP->isExactlyValue(+1.0))
BMI(MBB, IP, X86::FLD1, 0, R);
else {
// Otherwise we need to spill the constant to memory...
} else if (isa<ConstantPointerNull>(C)) {
// Copy zero (null pointer) to the register.
- BMI(MBB, IP, X86::MOVir32, 1, R).addZImm(0);
+ BMI(MBB, IP, X86::MOVri32, 1, R).addZImm(0);
} else if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)) {
unsigned SrcReg = getReg(CPR->getValue(), MBB, IP);
BMI(MBB, IP, X86::MOVrr32, 1, R).addReg(SrcReg);
switch (getClassB(I->getType())) {
case cByte:
FI = MFI->CreateFixedObject(1, ArgOffset);
- addFrameReference(BuildMI(BB, X86::MOVmr8, 4, Reg), FI);
+ addFrameReference(BuildMI(BB, X86::MOVrm8, 4, Reg), FI);
break;
case cShort:
FI = MFI->CreateFixedObject(2, ArgOffset);
- addFrameReference(BuildMI(BB, X86::MOVmr16, 4, Reg), FI);
+ addFrameReference(BuildMI(BB, X86::MOVrm16, 4, Reg), FI);
break;
case cInt:
FI = MFI->CreateFixedObject(4, ArgOffset);
- addFrameReference(BuildMI(BB, X86::MOVmr32, 4, Reg), FI);
+ addFrameReference(BuildMI(BB, X86::MOVrm32, 4, Reg), FI);
break;
case cLong:
FI = MFI->CreateFixedObject(8, ArgOffset);
- addFrameReference(BuildMI(BB, X86::MOVmr32, 4, Reg), FI);
- addFrameReference(BuildMI(BB, X86::MOVmr32, 4, Reg+1), FI, 4);
+ addFrameReference(BuildMI(BB, X86::MOVrm32, 4, Reg), FI);
+ addFrameReference(BuildMI(BB, X86::MOVrm32, 4, Reg+1), FI, 4);
ArgOffset += 4; // longs require 4 additional bytes
break;
case cFP:
unsigned Opcode;
if (I->getType() == Type::FloatTy) {
- Opcode = X86::FLDr32;
- FI = MFI->CreateFixedObject(4, ArgOffset);
+ Opcode = X86::FLDr32;
+ FI = MFI->CreateFixedObject(4, ArgOffset);
} else {
- Opcode = X86::FLDr64;
- FI = MFI->CreateFixedObject(8, ArgOffset);
- ArgOffset += 4; // doubles require 4 additional bytes
+ Opcode = X86::FLDr64;
+ FI = MFI->CreateFixedObject(8, ArgOffset);
+ ArgOffset += 4; // doubles require 4 additional bytes
}
addFrameReference(BuildMI(BB, Opcode, 4, Reg), FI);
break;
MachineBasicBlock *MBB = MBBMap[I];
// Loop over all of the PHI nodes in the LLVM basic block...
- unsigned NumPHIs = 0;
+ MachineInstr* instr = MBB->begin();
for (BasicBlock::const_iterator I = BB->begin();
PHINode *PN = const_cast<PHINode*>(dyn_cast<PHINode>(I)); ++I) {
// Create a new machine instr PHI node, and insert it.
unsigned PHIReg = getReg(*PN);
MachineInstr *PhiMI = BuildMI(X86::PHI, PN->getNumOperands(), PHIReg);
- MBB->insert(MBB->begin()+NumPHIs++, PhiMI);
+ MBB->insert(instr, PhiMI);
MachineInstr *LongPhiMI = 0;
if (PN->getType() == Type::LongTy || PN->getType() == Type::ULongTy) {
- LongPhiMI = BuildMI(X86::PHI, PN->getNumOperands(), PHIReg+1);
- MBB->insert(MBB->begin()+NumPHIs++, LongPhiMI);
+ LongPhiMI = BuildMI(X86::PHI, PN->getNumOperands(), PHIReg+1);
+ MBB->insert(instr, LongPhiMI);
}
// PHIValues - Map of blocks to incoming virtual registers. We use this
MachineBasicBlock::iterator PI = PredMBB->begin();
// Skip over any PHI nodes though!
- while (PI != PredMBB->end() && (*PI)->getOpcode() == X86::PHI)
+ while (PI != PredMBB->end() && PI->getOpcode() == X86::PHI)
++PI;
ValReg = getReg(Val, PredMBB, PI);
PHIValues.insert(EntryIt, std::make_pair(PredMBB, ValReg));
}
- PhiMI->addRegOperand(ValReg);
+ PhiMI->addRegOperand(ValReg);
PhiMI->addMachineBasicBlockOperand(PredMBB);
- if (LongPhiMI) {
- LongPhiMI->addRegOperand(ValReg+1);
- LongPhiMI->addMachineBasicBlockOperand(PredMBB);
- }
+ if (LongPhiMI) {
+ LongPhiMI->addRegOperand(ValReg+1);
+ LongPhiMI->addMachineBasicBlockOperand(PredMBB);
+ }
}
}
}
return OpNum;
}
+ // Special case handling of comparison against +/- 0.0
+ if (ConstantFP *CFP = dyn_cast<ConstantFP>(Op1))
+ if (CFP->isExactlyValue(+0.0) || CFP->isExactlyValue(-0.0)) {
+ BMI(MBB, IP, X86::FTST, 1).addReg(Op0r);
+ BMI(MBB, IP, X86::FNSTSWr8, 0);
+ BMI(MBB, IP, X86::SAHF, 1);
+ return OpNum;
+ }
+
unsigned Op1r = getReg(Op1, MBB, IP);
switch (Class) {
default: assert(0 && "Unknown type class!");
///
void ISel::visitReturnInst(ReturnInst &I) {
if (I.getNumOperands() == 0) {
+#ifndef SMART_FP
+ BuildMI(BB, X86::FP_REG_KILL, 0);
+#endif
BuildMI(BB, X86::RET, 0); // Just emit a 'ret' instruction
return;
}
BuildMI(BB, X86::MOVrr32, 1, X86::EAX).addReg(RetReg);
BuildMI(BB, X86::MOVrr32, 1, X86::EDX).addReg(RetReg+1);
// Declare that EAX & EDX are live on exit
- BuildMI(BB, X86::IMPLICIT_USE, 3).addReg(X86::EAX).addReg(X86::EDX).addReg(X86::ESP);
+ BuildMI(BB, X86::IMPLICIT_USE, 3).addReg(X86::EAX).addReg(X86::EDX)
+ .addReg(X86::ESP);
break;
default:
visitInstruction(I);
}
// Emit a 'ret' instruction
+#ifndef SMART_FP
+ BuildMI(BB, X86::FP_REG_KILL, 0);
+#endif
BuildMI(BB, X86::RET, 0);
}
return I != BB->getParent()->end() ? &*I : 0;
}
+/// RequiresFPRegKill - The floating point stackifier pass cannot insert
+/// compensation code on critical edges. As such, it requires that we kill all
+/// FP registers on the exit from any blocks that either ARE critical edges, or
+/// branch to a block that has incoming critical edges.
+///
+/// Note that this kill instruction will eventually be eliminated when
+/// restrictions in the stackifier are relaxed.
+///
+static bool RequiresFPRegKill(const BasicBlock *BB) {
+#ifdef SMART_FP
+ for (succ_const_iterator SI = succ_begin(BB), E = succ_end(BB); SI!=E; ++SI) {
+ const BasicBlock *Succ = *SI;
+ pred_const_iterator PI = pred_begin(Succ), PE = pred_end(Succ);
+ ++PI; // Block have at least one predecessory
+ if (PI != PE) { // If it has exactly one, this isn't crit edge
+ // If this block has more than one predecessor, check all of the
+ // predecessors to see if they have multiple successors. If so, then the
+ // block we are analyzing needs an FPRegKill.
+ for (PI = pred_begin(Succ); PI != PE; ++PI) {
+ const BasicBlock *Pred = *PI;
+ succ_const_iterator SI2 = succ_begin(Pred);
+ ++SI2; // There must be at least one successor of this block.
+ if (SI2 != succ_end(Pred))
+ return true; // Yes, we must insert the kill on this edge.
+ }
+ }
+ }
+ // If we got this far, there is no need to insert the kill instruction.
+ return false;
+#else
+ return true;
+#endif
+}
+
/// visitBranchInst - Handle conditional and unconditional branches here. Note
/// that since code layout is frozen at this point, that if we are trying to
/// jump to a block that is the immediate successor of the current block, we can
BasicBlock *NextBB = getBlockAfter(BI.getParent()); // BB after current one
if (!BI.isConditional()) { // Unconditional branch?
+ if (RequiresFPRegKill(BI.getParent()))
+ BuildMI(BB, X86::FP_REG_KILL, 0);
if (BI.getSuccessor(0) != NextBB)
BuildMI(BB, X86::JMP, 1).addPCDisp(BI.getSuccessor(0));
return;
// computed some other way...
unsigned condReg = getReg(BI.getCondition());
BuildMI(BB, X86::CMPri8, 2).addReg(condReg).addZImm(0);
+ if (RequiresFPRegKill(BI.getParent()))
+ BuildMI(BB, X86::FP_REG_KILL, 0);
if (BI.getSuccessor(1) == NextBB) {
if (BI.getSuccessor(0) != NextBB)
BuildMI(BB, X86::JNE, 1).addPCDisp(BI.getSuccessor(0));
unsigned OpNum = getSetCCNumber(SCI->getOpcode());
MachineBasicBlock::iterator MII = BB->end();
- OpNum = EmitComparison(OpNum, SCI->getOperand(0), SCI->getOperand(1), BB, MII);
+ OpNum = EmitComparison(OpNum, SCI->getOperand(0), SCI->getOperand(1), BB,MII);
const Type *CompTy = SCI->getOperand(0)->getType();
bool isSigned = CompTy->isSigned() && getClassB(CompTy) != cFP;
X86::JS, X86::JNS },
};
+ if (RequiresFPRegKill(BI.getParent()))
+ BuildMI(BB, X86::FP_REG_KILL, 0);
if (BI.getSuccessor(0) != NextBB) {
BuildMI(BB, OpcodeTab[isSigned][OpNum], 1).addPCDisp(BI.getSuccessor(0));
if (BI.getSuccessor(1) != NextBB)
/// it inserts the specified CallMI instruction into the stream.
///
void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
- const std::vector<ValueRecord> &Args) {
+ const std::vector<ValueRecord> &Args) {
// Count how many bytes are to be pushed on the stack...
unsigned NumBytes = 0;
for (unsigned i = 0, e = Args.size(); i != e; ++i)
switch (getClassB(Args[i].Ty)) {
case cByte: case cShort: case cInt:
- NumBytes += 4; break;
+ NumBytes += 4; break;
case cLong:
- NumBytes += 8; break;
+ NumBytes += 8; break;
case cFP:
- NumBytes += Args[i].Ty == Type::FloatTy ? 4 : 8;
- break;
+ NumBytes += Args[i].Ty == Type::FloatTy ? 4 : 8;
+ break;
default: assert(0 && "Unknown class!");
}
switch (getClassB(Args[i].Ty)) {
case cByte:
case cShort: {
- // Promote arg to 32 bits wide into a temporary register...
- unsigned R = makeAnotherReg(Type::UIntTy);
- promote32(R, Args[i]);
- addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
- X86::ESP, ArgOffset).addReg(R);
- break;
+ // Promote arg to 32 bits wide into a temporary register...
+ unsigned R = makeAnotherReg(Type::UIntTy);
+ promote32(R, Args[i]);
+ addRegOffset(BuildMI(BB, X86::MOVmr32, 5),
+ X86::ESP, ArgOffset).addReg(R);
+ break;
}
case cInt:
- addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
- X86::ESP, ArgOffset).addReg(ArgReg);
- break;
+ addRegOffset(BuildMI(BB, X86::MOVmr32, 5),
+ X86::ESP, ArgOffset).addReg(ArgReg);
+ break;
case cLong:
- addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
- X86::ESP, ArgOffset).addReg(ArgReg);
- addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
- X86::ESP, ArgOffset+4).addReg(ArgReg+1);
- ArgOffset += 4; // 8 byte entry, not 4.
- break;
-
+ addRegOffset(BuildMI(BB, X86::MOVmr32, 5),
+ X86::ESP, ArgOffset).addReg(ArgReg);
+ addRegOffset(BuildMI(BB, X86::MOVmr32, 5),
+ X86::ESP, ArgOffset+4).addReg(ArgReg+1);
+ ArgOffset += 4; // 8 byte entry, not 4.
+ break;
+
case cFP:
- if (Args[i].Ty == Type::FloatTy) {
- addRegOffset(BuildMI(BB, X86::FSTr32, 5),
- X86::ESP, ArgOffset).addReg(ArgReg);
- } else {
- assert(Args[i].Ty == Type::DoubleTy && "Unknown FP type!");
- addRegOffset(BuildMI(BB, X86::FSTr64, 5),
- X86::ESP, ArgOffset).addReg(ArgReg);
- ArgOffset += 4; // 8 byte entry, not 4.
- }
- break;
+ if (Args[i].Ty == Type::FloatTy) {
+ addRegOffset(BuildMI(BB, X86::FSTr32, 5),
+ X86::ESP, ArgOffset).addReg(ArgReg);
+ } else {
+ assert(Args[i].Ty == Type::DoubleTy && "Unknown FP type!");
+ addRegOffset(BuildMI(BB, X86::FSTr64, 5),
+ X86::ESP, ArgOffset).addReg(ArgReg);
+ ArgOffset += 4; // 8 byte entry, not 4.
+ }
+ break;
default: assert(0 && "Unknown class!");
}
// Integral results are in %eax, or the appropriate portion
// thereof.
static const unsigned regRegMove[] = {
- X86::MOVrr8, X86::MOVrr16, X86::MOVrr32
+ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32
};
static const unsigned AReg[] = { X86::AL, X86::AX, X86::EAX };
BuildMI(BB, regRegMove[DestClass], 1, Ret.Reg).addReg(AReg[DestClass]);
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;
}
unsigned DestReg = CI.getType() != Type::VoidTy ? getReg(CI) : 0;
doCall(ValueRecord(DestReg, CI.getType()), TheCall, Args);
-}
+}
+
+
+/// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
+/// function, lowering any calls to unknown intrinsic functions into the
+/// equivalent LLVM code.
+void ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
+ for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+ for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; )
+ if (CallInst *CI = dyn_cast<CallInst>(I++))
+ if (Function *F = CI->getCalledFunction())
+ switch (F->getIntrinsicID()) {
+ case Intrinsic::not_intrinsic:
+ case Intrinsic::va_start:
+ case Intrinsic::va_copy:
+ case Intrinsic::va_end:
+ case Intrinsic::returnaddress:
+ case Intrinsic::frameaddress:
+ case Intrinsic::memcpy:
+ case Intrinsic::memset:
+ // We directly implement these intrinsics
+ break;
+ default:
+ // All other intrinsic calls we must lower.
+ Instruction *Before = CI->getPrev();
+ TM.getIntrinsicLowering().LowerIntrinsicCall(CI);
+ if (Before) { // Move iterator to instruction after call
+ I = Before; ++I;
+ } else {
+ I = BB->begin();
+ }
+ }
+}
-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 Intrinsic::returnaddress:
+ case Intrinsic::frameaddress:
+ TmpReg1 = getReg(CI);
+ if (cast<Constant>(CI.getOperand(1))->isNullValue()) {
+ if (ID == Intrinsic::returnaddress) {
+ // Just load the return address
+ addFrameReference(BuildMI(BB, X86::MOVrm32, 4, TmpReg1),
+ ReturnAddressIndex);
+ } else {
+ addFrameReference(BuildMI(BB, X86::LEAr32, 4, TmpReg1),
+ ReturnAddressIndex, -4);
+ }
+ } else {
+ // Values other than zero are not implemented yet.
+ BuildMI(BB, X86::MOVri32, 1, TmpReg1).addZImm(0);
+ }
+ return;
- case LLVMIntrinsic::longjmp:
- case LLVMIntrinsic::siglongjmp:
- BuildMI(BB, X86::CALLpcrel32, 1).addExternalSymbol("abort", true);
+ case Intrinsic::memcpy: {
+ assert(CI.getNumOperands() == 5 && "Illegal llvm.memcpy call!");
+ unsigned Align = 1;
+ if (ConstantInt *AlignC = dyn_cast<ConstantInt>(CI.getOperand(4))) {
+ Align = AlignC->getRawValue();
+ if (Align == 0) Align = 1;
+ }
+
+ // Turn the byte code into # iterations
+ unsigned ByteReg;
+ unsigned CountReg;
+ unsigned Opcode;
+ switch (Align & 3) {
+ case 2: // WORD aligned
+ if (ConstantInt *I = dyn_cast<ConstantInt>(CI.getOperand(3))) {
+ CountReg = getReg(ConstantUInt::get(Type::UIntTy, I->getRawValue()/2));
+ } else {
+ CountReg = makeAnotherReg(Type::IntTy);
+ BuildMI(BB, X86::SHRri32, 2, CountReg).addReg(ByteReg).addZImm(1);
+ }
+ Opcode = X86::REP_MOVSW;
+ break;
+ case 0: // DWORD aligned
+ if (ConstantInt *I = dyn_cast<ConstantInt>(CI.getOperand(3))) {
+ CountReg = getReg(ConstantUInt::get(Type::UIntTy, I->getRawValue()/4));
+ } else {
+ CountReg = makeAnotherReg(Type::IntTy);
+ BuildMI(BB, X86::SHRri32, 2, CountReg).addReg(ByteReg).addZImm(2);
+ }
+ Opcode = X86::REP_MOVSD;
+ break;
+ case 1: // BYTE aligned
+ case 3: // BYTE aligned
+ CountReg = getReg(CI.getOperand(3));
+ Opcode = X86::REP_MOVSB;
+ break;
+ }
+
+ // No matter what the alignment is, we put the source in ESI, the
+ // destination in EDI, and the count in ECX.
+ TmpReg1 = getReg(CI.getOperand(1));
+ TmpReg2 = getReg(CI.getOperand(2));
+ BuildMI(BB, X86::MOVrr32, 1, X86::ECX).addReg(CountReg);
+ BuildMI(BB, X86::MOVrr32, 1, X86::EDI).addReg(TmpReg1);
+ BuildMI(BB, X86::MOVrr32, 1, X86::ESI).addReg(TmpReg2);
+ BuildMI(BB, Opcode, 0);
return;
+ }
+ case Intrinsic::memset: {
+ assert(CI.getNumOperands() == 5 && "Illegal llvm.memset call!");
+ unsigned Align = 1;
+ if (ConstantInt *AlignC = dyn_cast<ConstantInt>(CI.getOperand(4))) {
+ Align = AlignC->getRawValue();
+ if (Align == 0) Align = 1;
+ }
- case LLVMIntrinsic::setjmp:
- case LLVMIntrinsic::sigsetjmp:
- // Setjmp always returns zero...
- BuildMI(BB, X86::MOVir32, 1, getReg(CI)).addZImm(0);
+ // Turn the byte code into # iterations
+ unsigned ByteReg;
+ unsigned CountReg;
+ unsigned Opcode;
+ if (ConstantInt *ValC = dyn_cast<ConstantInt>(CI.getOperand(2))) {
+ unsigned Val = ValC->getRawValue() & 255;
+
+ // If the value is a constant, then we can potentially use larger copies.
+ switch (Align & 3) {
+ case 2: // WORD aligned
+ if (ConstantInt *I = dyn_cast<ConstantInt>(CI.getOperand(3))) {
+ CountReg =getReg(ConstantUInt::get(Type::UIntTy, I->getRawValue()/2));
+ } else {
+ CountReg = makeAnotherReg(Type::IntTy);
+ BuildMI(BB, X86::SHRri32, 2, CountReg).addReg(ByteReg).addZImm(1);
+ }
+ BuildMI(BB, X86::MOVri16, 1, X86::AX).addZImm((Val << 8) | Val);
+ Opcode = X86::REP_STOSW;
+ break;
+ case 0: // DWORD aligned
+ if (ConstantInt *I = dyn_cast<ConstantInt>(CI.getOperand(3))) {
+ CountReg =getReg(ConstantUInt::get(Type::UIntTy, I->getRawValue()/4));
+ } else {
+ CountReg = makeAnotherReg(Type::IntTy);
+ BuildMI(BB, X86::SHRri32, 2, CountReg).addReg(ByteReg).addZImm(2);
+ }
+ Val = (Val << 8) | Val;
+ BuildMI(BB, X86::MOVri32, 1, X86::EAX).addZImm((Val << 16) | Val);
+ Opcode = X86::REP_STOSD;
+ break;
+ case 1: // BYTE aligned
+ case 3: // BYTE aligned
+ CountReg = getReg(CI.getOperand(3));
+ BuildMI(BB, X86::MOVri8, 1, X86::AL).addZImm(Val);
+ Opcode = X86::REP_STOSB;
+ break;
+ }
+ } else {
+ // If it's not a constant value we are storing, just fall back. We could
+ // try to be clever to form 16 bit and 32 bit values, but we don't yet.
+ unsigned ValReg = getReg(CI.getOperand(2));
+ BuildMI(BB, X86::MOVrr8, 1, X86::AL).addReg(ValReg);
+ CountReg = getReg(CI.getOperand(3));
+ Opcode = X86::REP_STOSB;
+ }
+
+ // No matter what the alignment is, we put the source in ESI, the
+ // destination in EDI, and the count in ECX.
+ TmpReg1 = getReg(CI.getOperand(1));
+ //TmpReg2 = getReg(CI.getOperand(2));
+ BuildMI(BB, X86::MOVrr32, 1, X86::ECX).addReg(CountReg);
+ BuildMI(BB, X86::MOVrr32, 1, X86::EDI).addReg(TmpReg1);
+ BuildMI(BB, Opcode, 0);
return;
- default: assert(0 && "Unknown intrinsic for X86!");
+ }
+
+ default: assert(0 && "Error: unknown intrinsics should have been lowered!");
}
}
// sub 0, X -> neg X
if (OperatorClass == 1 && Class != cLong)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0))
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0)) {
if (CI->isNullValue()) {
unsigned op1Reg = getReg(Op1, MBB, IP);
switch (Class) {
return;
}
}
+ } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(Op0))
+ if (CFP->isExactlyValue(-0.0)) {
+ // -0.0 - X === -X
+ unsigned op1Reg = getReg(Op1, MBB, IP);
+ BMI(MBB, IP, X86::FCHS, 1, DestReg).addReg(op1Reg);
+ return;
+ }
if (!isa<ConstantInt>(Op1) || Class == cLong) {
static const unsigned OpcodeTab[][4] = {
switch (Class) {
default: assert(0 && "Unknown class for this function!");
case cByte:
- BMI(MBB, IP, X86::SHLir32, 2, DestReg).addReg(op0Reg).addZImm(Shift-1);
+ BMI(MBB, IP, X86::SHLri32, 2, DestReg).addReg(op0Reg).addZImm(Shift-1);
return;
case cShort:
- BMI(MBB, IP, X86::SHLir32, 2, DestReg).addReg(op0Reg).addZImm(Shift-1);
+ BMI(MBB, IP, X86::SHLri32, 2, DestReg).addReg(op0Reg).addZImm(Shift-1);
return;
case cInt:
- BMI(MBB, IP, X86::SHLir32, 2, DestReg).addReg(op0Reg).addZImm(Shift-1);
+ BMI(MBB, IP, X86::SHLri32, 2, DestReg).addReg(op0Reg).addZImm(Shift-1);
return;
}
}
if (Class == cShort) {
- BMI(MBB, IP, X86::IMULri16, 2, DestReg).addReg(op0Reg).addZImm(ConstRHS);
+ BMI(MBB, IP, X86::IMULrri16, 2, DestReg).addReg(op0Reg).addZImm(ConstRHS);
return;
} else if (Class == cInt) {
- BMI(MBB, IP, X86::IMULri32, 2, DestReg).addReg(op0Reg).addZImm(ConstRHS);
+ BMI(MBB, IP, X86::IMULrri32, 2, DestReg).addReg(op0Reg).addZImm(ConstRHS);
return;
}
// Most general case, emit a normal multiply...
- static const unsigned MOVirTab[] = {
- X86::MOVir8, X86::MOVir16, X86::MOVir32
+ static const unsigned MOVriTab[] = {
+ X86::MOVri8, X86::MOVri16, X86::MOVri32
};
unsigned TmpReg = makeAnotherReg(DestTy);
- BMI(MBB, IP, MOVirTab[Class], 1, TmpReg).addZImm(ConstRHS);
+ BMI(MBB, IP, MOVriTab[Class], 1, TmpReg).addZImm(ConstRHS);
// Emit a MUL to multiply the register holding the index by
// elementSize, putting the result in OffsetReg.
unsigned AHBLplusOverflowReg = makeAnotherReg(Type::UIntTy);
BuildMI(BB, X86::ADDrr32, 2, // AH*BL+(AL*BL >> 32)
- AHBLplusOverflowReg).addReg(AHBLReg).addReg(OverflowReg);
+ AHBLplusOverflowReg).addReg(AHBLReg).addReg(OverflowReg);
MBBI = BB->end();
unsigned ALBHReg = makeAnotherReg(Type::UIntTy); // AL*BH
BMI(BB, MBBI, X86::IMULrr32, 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);
+ DestReg+1).addReg(AHBLplusOverflowReg).addReg(ALBHReg);
}
}
/// 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);
+ 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;
}
static const unsigned Regs[] ={ X86::AL , X86::AX , X86::EAX };
static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 };
- static const unsigned SarOpcode[]={ X86::SARir8, X86::SARir16, X86::SARir32 };
- static const unsigned ClrOpcode[]={ X86::XORrr8, X86::XORrr16, X86::XORrr32 };
+ static const unsigned SarOpcode[]={ X86::SARri8, X86::SARri16, X86::SARri32 };
+ static const unsigned ClrOpcode[]={ X86::MOVri8, X86::MOVri16, X86::MOVri32 };
static const unsigned ExtRegs[] ={ X86::AH , X86::DX , X86::EDX };
static const unsigned DivOpcode[][4] = {
{ 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);
+ // If unsigned, emit a zeroing instruction... (reg = 0)
+ BMI(BB, IP, ClrOpcode[Class], 2, ExtReg).addZImm(0);
}
// 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);
}
/// because the shift amount has to be in CL, not just any old register.
///
void ISel::visitShiftInst(ShiftInst &I) {
- unsigned SrcReg = getReg(I.getOperand(0));
- unsigned DestReg = getReg(I);
- bool isLeftShift = I.getOpcode() == Instruction::Shl;
- bool isSigned = I.getType()->isSigned();
- unsigned Class = getClass(I.getType());
+ MachineBasicBlock::iterator IP = BB->end ();
+ emitShiftOperation (BB, IP, I.getOperand (0), I.getOperand (1),
+ I.getOpcode () == Instruction::Shl, I.getType (),
+ getReg (I));
+}
+
+/// emitShiftOperation - Common code shared between visitShiftInst and
+/// constant expression support.
+void ISel::emitShiftOperation(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator &IP,
+ Value *Op, Value *ShiftAmount, bool isLeftShift,
+ const Type *ResultTy, unsigned DestReg) {
+ unsigned SrcReg = getReg (Op, MBB, IP);
+ bool isSigned = ResultTy->isSigned ();
+ unsigned Class = getClass (ResultTy);
static const unsigned ConstantOperand[][4] = {
- { X86::SHRir8, X86::SHRir16, X86::SHRir32, X86::SHRDir32 }, // SHR
- { X86::SARir8, X86::SARir16, X86::SARir32, X86::SHRDir32 }, // SAR
- { X86::SHLir8, X86::SHLir16, X86::SHLir32, X86::SHLDir32 }, // SHL
- { X86::SHLir8, X86::SHLir16, X86::SHLir32, X86::SHLDir32 }, // SAL = SHL
+ { X86::SHRri8, X86::SHRri16, X86::SHRri32, X86::SHRDri32 }, // SHR
+ { X86::SARri8, X86::SARri16, X86::SARri32, X86::SHRDri32 }, // SAR
+ { X86::SHLri8, X86::SHLri16, X86::SHLri32, X86::SHLDri32 }, // SHL
+ { X86::SHLri8, X86::SHLri16, X86::SHLri32, X86::SHLDri32 }, // SAL = SHL
};
static const unsigned NonConstantOperand[][4] = {
// If we have a constant shift, we can generate much more efficient code
// than otherwise...
//
- if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(I.getOperand(1))) {
+ if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(ShiftAmount)) {
unsigned Amount = CUI->getValue();
if (Amount < 32) {
- const unsigned *Opc = ConstantOperand[isLeftShift*2+isSigned];
- if (isLeftShift) {
- BuildMI(BB, Opc[3], 3,
- DestReg+1).addReg(SrcReg+1).addReg(SrcReg).addZImm(Amount);
- BuildMI(BB, Opc[2], 2, DestReg).addReg(SrcReg).addZImm(Amount);
- } else {
- BuildMI(BB, Opc[3], 3,
- DestReg).addReg(SrcReg ).addReg(SrcReg+1).addZImm(Amount);
- BuildMI(BB, Opc[2], 2, DestReg+1).addReg(SrcReg+1).addZImm(Amount);
- }
+ const unsigned *Opc = ConstantOperand[isLeftShift*2+isSigned];
+ if (isLeftShift) {
+ BMI(MBB, IP, Opc[3], 3,
+ DestReg+1).addReg(SrcReg+1).addReg(SrcReg).addZImm(Amount);
+ BMI(MBB, IP, Opc[2], 2, DestReg).addReg(SrcReg).addZImm(Amount);
+ } else {
+ BMI(MBB, IP, Opc[3], 3,
+ DestReg).addReg(SrcReg ).addReg(SrcReg+1).addZImm(Amount);
+ BMI(MBB, IP, Opc[2], 2, DestReg+1).addReg(SrcReg+1).addZImm(Amount);
+ }
} else { // Shifting more than 32 bits
- Amount -= 32;
- if (isLeftShift) {
- BuildMI(BB, X86::SHLir32, 2,DestReg+1).addReg(SrcReg).addZImm(Amount);
- BuildMI(BB, X86::MOVir32, 1,DestReg ).addZImm(0);
- } else {
- unsigned Opcode = isSigned ? X86::SARir32 : X86::SHRir32;
- BuildMI(BB, Opcode, 2, DestReg).addReg(SrcReg+1).addZImm(Amount);
- BuildMI(BB, X86::MOVir32, 1, DestReg+1).addZImm(0);
- }
+ Amount -= 32;
+ if (isLeftShift) {
+ BMI(MBB, IP, X86::SHLri32, 2,
+ DestReg + 1).addReg(SrcReg).addZImm(Amount);
+ BMI(MBB, IP, X86::MOVri32, 1,
+ DestReg).addZImm(0);
+ } else {
+ unsigned Opcode = isSigned ? X86::SARri32 : X86::SHRri32;
+ BMI(MBB, IP, Opcode, 2, DestReg).addReg(SrcReg+1).addZImm(Amount);
+ BMI(MBB, IP, X86::MOVri32, 1, DestReg+1).addZImm(0);
+ }
}
} else {
unsigned TmpReg = makeAnotherReg(Type::IntTy);
// If this is a SHR of a Long, then we need to do funny sign extension
// stuff. TmpReg gets the value to use as the high-part if we are
// shifting more than 32 bits.
- BuildMI(BB, X86::SARir32, 2, TmpReg).addReg(SrcReg).addZImm(31);
+ BMI(MBB, IP, X86::SARri32, 2, TmpReg).addReg(SrcReg).addZImm(31);
} else {
// Other shifts use a fixed zero value if the shift is more than 32
// bits.
- BuildMI(BB, X86::MOVir32, 1, TmpReg).addZImm(0);
+ BMI(MBB, IP, X86::MOVri32, 1, TmpReg).addZImm(0);
}
// Initialize CL with the shift amount...
- unsigned ShiftAmount = getReg(I.getOperand(1));
- BuildMI(BB, X86::MOVrr8, 1, X86::CL).addReg(ShiftAmount);
+ unsigned ShiftAmountReg = getReg(ShiftAmount, MBB, IP);
+ BMI(MBB, IP, X86::MOVrr8, 1, X86::CL).addReg(ShiftAmountReg);
unsigned TmpReg2 = makeAnotherReg(Type::IntTy);
unsigned TmpReg3 = makeAnotherReg(Type::IntTy);
if (isLeftShift) {
// TmpReg2 = shld inHi, inLo
- BuildMI(BB, X86::SHLDrr32, 2, TmpReg2).addReg(SrcReg+1).addReg(SrcReg);
+ BMI(MBB, IP, X86::SHLDrr32, 2, TmpReg2).addReg(SrcReg+1).addReg(SrcReg);
// TmpReg3 = shl inLo, CL
- BuildMI(BB, X86::SHLrr32, 1, TmpReg3).addReg(SrcReg);
+ BMI(MBB, IP, X86::SHLrr32, 1, TmpReg3).addReg(SrcReg);
// Set the flags to indicate whether the shift was by more than 32 bits.
- BuildMI(BB, X86::TESTri8, 2).addReg(X86::CL).addZImm(32);
+ BMI(MBB, IP, X86::TESTri8, 2).addReg(X86::CL).addZImm(32);
// DestHi = (>32) ? TmpReg3 : TmpReg2;
- BuildMI(BB, X86::CMOVNErr32, 2,
+ BMI(MBB, IP, X86::CMOVNErr32, 2,
DestReg+1).addReg(TmpReg2).addReg(TmpReg3);
// DestLo = (>32) ? TmpReg : TmpReg3;
- BuildMI(BB, X86::CMOVNErr32, 2, DestReg).addReg(TmpReg3).addReg(TmpReg);
+ BMI(MBB, IP, X86::CMOVNErr32, 2,
+ DestReg).addReg(TmpReg3).addReg(TmpReg);
} else {
// TmpReg2 = shrd inLo, inHi
- BuildMI(BB, X86::SHRDrr32, 2, TmpReg2).addReg(SrcReg).addReg(SrcReg+1);
+ BMI(MBB, IP, X86::SHRDrr32, 2, TmpReg2).addReg(SrcReg).addReg(SrcReg+1);
// TmpReg3 = s[ah]r inHi, CL
- BuildMI(BB, isSigned ? X86::SARrr32 : X86::SHRrr32, 1, TmpReg3)
+ BMI(MBB, IP, isSigned ? X86::SARrr32 : X86::SHRrr32, 1, TmpReg3)
.addReg(SrcReg+1);
// Set the flags to indicate whether the shift was by more than 32 bits.
- BuildMI(BB, X86::TESTri8, 2).addReg(X86::CL).addZImm(32);
+ BMI(MBB, IP, X86::TESTri8, 2).addReg(X86::CL).addZImm(32);
// DestLo = (>32) ? TmpReg3 : TmpReg2;
- BuildMI(BB, X86::CMOVNErr32, 2,
+ BMI(MBB, IP, X86::CMOVNErr32, 2,
DestReg).addReg(TmpReg2).addReg(TmpReg3);
// DestHi = (>32) ? TmpReg : TmpReg3;
- BuildMI(BB, X86::CMOVNErr32, 2,
+ BMI(MBB, IP, X86::CMOVNErr32, 2,
DestReg+1).addReg(TmpReg3).addReg(TmpReg);
}
}
return;
}
- if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(I.getOperand(1))) {
+ if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(ShiftAmount)) {
// The shift amount is constant, guaranteed to be a ubyte. Get its value.
assert(CUI->getType() == Type::UByteTy && "Shift amount not a ubyte?");
const unsigned *Opc = ConstantOperand[isLeftShift*2+isSigned];
- BuildMI(BB, Opc[Class], 2, DestReg).addReg(SrcReg).addZImm(CUI->getValue());
+ BMI(MBB, IP, Opc[Class], 2,
+ DestReg).addReg(SrcReg).addZImm(CUI->getValue());
} else { // The shift amount is non-constant.
- BuildMI(BB, X86::MOVrr8, 1, X86::CL).addReg(getReg(I.getOperand(1)));
+ unsigned ShiftAmountReg = getReg (ShiftAmount, MBB, IP);
+ BMI(MBB, IP, X86::MOVrr8, 1, X86::CL).addReg(ShiftAmountReg);
const unsigned *Opc = NonConstantOperand[isLeftShift*2+isSigned];
- BuildMI(BB, Opc[Class], 1, DestReg).addReg(SrcReg);
- }
-}
-
-
-/// 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!");
+ BMI(MBB, IP, Opc[Class], 1, DestReg).addReg(SrcReg);
}
}
unsigned Class = getClassB(I.getType());
if (Class == cLong) {
- addDirectMem(BuildMI(BB, X86::MOVmr32, 4, DestReg), SrcAddrReg);
- addRegOffset(BuildMI(BB, X86::MOVmr32, 4, DestReg+1), SrcAddrReg, 4);
+ addDirectMem(BuildMI(BB, X86::MOVrm32, 4, DestReg), SrcAddrReg);
+ addRegOffset(BuildMI(BB, X86::MOVrm32, 4, DestReg+1), SrcAddrReg, 4);
return;
}
static const unsigned Opcodes[] = {
- X86::MOVmr8, X86::MOVmr16, X86::MOVmr32, X86::FLDr32
+ X86::MOVrm8, X86::MOVrm16, X86::MOVrm32, X86::FLDr32
};
unsigned Opcode = Opcodes[Class];
if (I.getType() == Type::DoubleTy) Opcode = X86::FLDr64;
unsigned Class = getClassB(ValTy);
if (Class == cLong) {
- addDirectMem(BuildMI(BB, X86::MOVrm32, 1+4), AddressReg).addReg(ValReg);
- addRegOffset(BuildMI(BB, X86::MOVrm32, 1+4), AddressReg,4).addReg(ValReg+1);
+ addDirectMem(BuildMI(BB, X86::MOVmr32, 1+4), AddressReg).addReg(ValReg);
+ addRegOffset(BuildMI(BB, X86::MOVmr32, 1+4), AddressReg,4).addReg(ValReg+1);
return;
}
static const unsigned Opcodes[] = {
- X86::MOVrm8, X86::MOVrm16, X86::MOVrm32, X86::FSTr32
+ X86::MOVmr8, X86::MOVmr16, X86::MOVmr32, X86::FSTr32
};
unsigned Opcode = Opcodes[Class];
if (ValTy == Type::DoubleTy) Opcode = X86::FSTr64;
BMI(BB, IP, RegRegMove[SrcClass], 1, DestReg).addReg(SrcReg);
} else if (SrcClass == cFP) {
if (SrcTy == Type::FloatTy) { // double -> float
- assert(DestTy == Type::DoubleTy && "Unknown cFP member!");
- BMI(BB, IP, X86::FpMOV, 1, DestReg).addReg(SrcReg);
+ assert(DestTy == Type::DoubleTy && "Unknown cFP member!");
+ BMI(BB, IP, X86::FpMOV, 1, DestReg).addReg(SrcReg);
} else { // float -> double
- assert(SrcTy == Type::DoubleTy && DestTy == Type::FloatTy &&
- "Unknown cFP member!");
- // Truncate from double to float by storing to memory as short, then
- // reading it back.
- unsigned FltAlign = TM.getTargetData().getFloatAlignment();
+ assert(SrcTy == Type::DoubleTy && DestTy == Type::FloatTy &&
+ "Unknown cFP member!");
+ // Truncate from double to float by storing to memory as short, then
+ // reading it back.
+ unsigned FltAlign = TM.getTargetData().getFloatAlignment();
int FrameIdx = F->getFrameInfo()->CreateStackObject(4, FltAlign);
- addFrameReference(BMI(BB, IP, X86::FSTr32, 5), FrameIdx).addReg(SrcReg);
- addFrameReference(BMI(BB, IP, X86::FLDr32, 5, DestReg), FrameIdx);
+ addFrameReference(BMI(BB, IP, X86::FSTr32, 5), FrameIdx).addReg(SrcReg);
+ addFrameReference(BMI(BB, IP, X86::FLDr32, 5, DestReg), FrameIdx);
}
} else if (SrcClass == cLong) {
BMI(BB, IP, X86::MOVrr32, 1, DestReg).addReg(SrcReg);
if (isLong) { // Handle upper 32 bits as appropriate...
if (isUnsigned) // Zero out top bits...
- BMI(BB, IP, X86::MOVir32, 1, DestReg+1).addZImm(0);
+ BMI(BB, IP, X86::MOVri32, 1, DestReg+1).addZImm(0);
else // Sign extend bottom half...
- BMI(BB, IP, X86::SARir32, 2, DestReg+1).addReg(DestReg).addZImm(31);
+ BMI(BB, IP, X86::SARri32, 2, DestReg+1).addReg(DestReg).addZImm(31);
}
return;
}
// Make a 64 bit temporary... and zero out the top of it...
unsigned TmpReg = makeAnotherReg(Type::LongTy);
BMI(BB, IP, X86::MOVrr32, 1, TmpReg).addReg(SrcReg);
- BMI(BB, IP, X86::MOVir32, 1, TmpReg+1).addZImm(0);
+ BMI(BB, IP, X86::MOVri32, 1, TmpReg+1).addZImm(0);
SrcTy = Type::LongTy;
SrcClass = cLong;
SrcReg = TmpReg;
F->getFrameInfo()->CreateStackObject(SrcTy, TM.getTargetData());
if (SrcClass == cLong) {
- addFrameReference(BMI(BB, IP, X86::MOVrm32, 5), FrameIdx).addReg(SrcReg);
- addFrameReference(BMI(BB, IP, X86::MOVrm32, 5),
- FrameIdx, 4).addReg(SrcReg+1);
+ addFrameReference(BMI(BB, IP, X86::MOVmr32, 5), FrameIdx).addReg(SrcReg);
+ addFrameReference(BMI(BB, IP, X86::MOVmr32, 5),
+ FrameIdx, 4).addReg(SrcReg+1);
} else {
- static const unsigned Op1[] = { X86::MOVrm8, X86::MOVrm16, X86::MOVrm32 };
+ static const unsigned Op1[] = { X86::MOVmr8, X86::MOVmr16, X86::MOVmr32 };
addFrameReference(BMI(BB, IP, Op1[SrcClass], 5), FrameIdx).addReg(SrcReg);
}
// Load the old value of the high byte of the control word...
unsigned HighPartOfCW = makeAnotherReg(Type::UByteTy);
- addFrameReference(BMI(BB, IP, X86::MOVmr8, 4, HighPartOfCW), CWFrameIdx, 1);
+ addFrameReference(BMI(BB, IP, X86::MOVrm8, 4, HighPartOfCW), CWFrameIdx, 1);
// Set the high part to be round to zero...
- addFrameReference(BMI(BB, IP, X86::MOVim8, 5), CWFrameIdx, 1).addZImm(12);
+ addFrameReference(BMI(BB, IP, X86::MOVmi8, 5), CWFrameIdx, 1).addZImm(12);
// Reload the modified control word now...
addFrameReference(BMI(BB, IP, X86::FLDCWm16, 4), CWFrameIdx);
// Restore the memory image of control word to original value
- addFrameReference(BMI(BB, IP, X86::MOVrm8, 5),
- CWFrameIdx, 1).addReg(HighPartOfCW);
+ addFrameReference(BMI(BB, IP, X86::MOVmr8, 5),
+ CWFrameIdx, 1).addReg(HighPartOfCW);
// We don't have the facilities for directly storing byte sized data to
// memory. Promote it to 16 bits. We also must promote unsigned values to
addFrameReference(BMI(BB, IP, Op1[StoreClass], 5), FrameIdx).addReg(SrcReg);
if (DestClass == cLong) {
- addFrameReference(BMI(BB, IP, X86::MOVmr32, 4, DestReg), FrameIdx);
- addFrameReference(BMI(BB, IP, X86::MOVmr32, 4, DestReg+1), FrameIdx, 4);
+ addFrameReference(BMI(BB, IP, X86::MOVrm32, 4, DestReg), FrameIdx);
+ addFrameReference(BMI(BB, IP, X86::MOVrm32, 4, DestReg+1), FrameIdx, 4);
} else {
- static const unsigned Op2[] = { X86::MOVmr8, X86::MOVmr16, X86::MOVmr32 };
+ static const unsigned Op2[] = { X86::MOVrm8, X86::MOVrm16, X86::MOVrm32 };
addFrameReference(BMI(BB, IP, Op2[DestClass], 4, DestReg), FrameIdx);
}
case Type::PointerTyID:
case Type::UIntTyID:
case Type::IntTyID:
- addDirectMem(BuildMI(BB, X86::MOVmr32, 4, DestReg), VAList);
+ addDirectMem(BuildMI(BB, X86::MOVrm32, 4, DestReg), VAList);
break;
case Type::ULongTyID:
case Type::LongTyID:
- addDirectMem(BuildMI(BB, X86::MOVmr32, 4, DestReg), VAList);
- addRegOffset(BuildMI(BB, X86::MOVmr32, 4, DestReg+1), VAList, 4);
+ addDirectMem(BuildMI(BB, X86::MOVrm32, 4, DestReg), VAList);
+ addRegOffset(BuildMI(BB, X86::MOVrm32, 4, DestReg+1), VAList, 4);
break;
case Type::DoubleTyID:
addDirectMem(BuildMI(BB, X86::FLDr64, 4, DestReg), VAList);
// which names the field. This index must have ubyte type.
const ConstantUInt *CUI = cast<ConstantUInt>(idx);
assert(CUI->getType() == Type::UByteTy
- && "Funny-looking structure index in GEP");
+ && "Funny-looking structure index in GEP");
// Use the TargetData structure to pick out what the layout of
// the structure is in memory. Since the structure index must
// be constant, we can get its value and use it to find the
unsigned idxValue = CUI->getValue();
unsigned FieldOff = TD.getStructLayout(StTy)->MemberOffsets[idxValue];
if (FieldOff) {
- NextReg = makeAnotherReg(Type::UIntTy);
- // Emit an ADD to add FieldOff to the basePtr.
- BMI(MBB, IP, X86::ADDri32, 2,NextReg).addReg(BaseReg).addZImm(FieldOff);
+ NextReg = makeAnotherReg(Type::UIntTy);
+ // Emit an ADD to add FieldOff to the basePtr.
+ BMI(MBB, IP, X86::ADDri32, 2,NextReg).addReg(BaseReg).addZImm(FieldOff);
}
// The next type is the member of the structure selected by the
// index.
- Ty = StTy->getElementTypes()[idxValue];
+ Ty = StTy->getElementType(idxValue);
} else if (const SequentialType *SqTy = cast<SequentialType>(Ty)) {
// It's an array or pointer access: [ArraySize x ElementType].
if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) {
if (!CSI->isNullValue()) {
unsigned Offset = elementSize*CSI->getValue();
- NextReg = makeAnotherReg(Type::UIntTy);
+ NextReg = makeAnotherReg(Type::UIntTy);
BMI(MBB, IP, X86::ADDri32, 2,NextReg).addReg(BaseReg).addZImm(Offset);
}
} else if (elementSize == 1) {
// If the element size is 1, we don't have to multiply, just add
unsigned idxReg = getReg(idx, MBB, IP);
- NextReg = makeAnotherReg(Type::UIntTy);
+ NextReg = makeAnotherReg(Type::UIntTy);
BMI(MBB, IP, X86::ADDrr32, 2, NextReg).addReg(BaseReg).addReg(idxReg);
} else {
unsigned idxReg = getReg(idx, MBB, IP);
doMultiplyConst(MBB, IP, OffsetReg, Type::IntTy, idxReg, elementSize);
// Emit an ADD to add OffsetReg to the basePtr.
- NextReg = makeAnotherReg(Type::UIntTy);
+ NextReg = makeAnotherReg(Type::UIntTy);
BMI(MBB, IP, X86::ADDrr32, 2,NextReg).addReg(BaseReg).addReg(OffsetReg);
}
}
std::vector<ValueRecord> Args;
Args.push_back(ValueRecord(Arg, Type::UIntTy));
MachineInstr *TheCall = BuildMI(X86::CALLpcrel32,
- 1).addExternalSymbol("malloc", true);
+ 1).addExternalSymbol("malloc", true);
doCall(ValueRecord(getReg(I), I.getType()), TheCall, Args);
}
std::vector<ValueRecord> Args;
Args.push_back(ValueRecord(I.getOperand(0)));
MachineInstr *TheCall = BuildMI(X86::CALLpcrel32,
- 1).addExternalSymbol("free", true);
+ 1).addExternalSymbol("free", true);
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) {
+FunctionPass *llvm::createX86SimpleInstructionSelector(TargetMachine &TM) {
return new ISel(TM);
}