#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
-#include "llvm/Intrinsics.h"
+#include "llvm/IntrinsicLowering.h"
#include "llvm/Pass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.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.
///
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);
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.
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
}
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:
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);
+ 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);
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;
}
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));
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)
// 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),
+ addRegOffset(BuildMI(BB, X86::MOVmr32, 5),
X86::ESP, ArgOffset).addReg(R);
break;
}
case cInt:
- addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
+ addRegOffset(BuildMI(BB, X86::MOVmr32, 5),
X86::ESP, ArgOffset).addReg(ArgReg);
break;
case cLong:
- addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
+ addRegOffset(BuildMI(BB, X86::MOVmr32, 5),
X86::ESP, ArgOffset).addReg(ArgReg);
- addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
+ addRegOffset(BuildMI(BB, X86::MOVmr32, 5),
X86::ESP, ArgOffset+4).addReg(ArgReg+1);
ArgOffset += 4; // 8 byte entry, not 4.
break;
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) {
+/// 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(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 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;
+ }
- case LLVMIntrinsic::longjmp:
- case LLVMIntrinsic::siglongjmp:
- BuildMI(BB, X86::CALLpcrel32, 1).addExternalSymbol("abort", true);
+ // 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.
switch (Class) {
case cFP: // Floating point divide
if (isDiv) {
- BuildMI(BB, X86::FpDIV, 2, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
+ BMI(BB, IP, X86::FpDIV, 2, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
} else { // Floating point remainder...
MachineInstr *TheCall =
BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("fmod", true);
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] = {
unsigned ExtReg = ExtRegs[Class];
// Put the first operand into one of the A registers...
- 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(Ty);
- BuildMI(BB, SarOpcode[Class], 2, ShiftResult).addReg(Op0Reg).addZImm(31);
- BuildMI(BB, MovOpcode[Class], 1, ExtReg).addReg(ShiftResult);
+ 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...
- 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 = 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);
+ 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 {
- 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);
+ 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);
+ 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::SARir32 : X86::SHRir32;
- BuildMI(BB, Opcode, 2, DestReg).addReg(SrcReg+1).addZImm(Amount);
- BuildMI(BB, X86::MOVir32, 1, DestReg+1).addZImm(0);
+ 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 {
// 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);
+ 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;
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),
+ 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),
+ addFrameReference(BMI(BB, IP, X86::MOVmr8, 5),
CWFrameIdx, 1).addReg(HighPartOfCW);
// We don't have the facilities for directly storing byte sized data 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);
}
// 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].
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);
}