2002-10-25 22:55:53 +00:00
|
|
|
//===-- InstSelectSimple.cpp - A simple instruction selector for x86 ------===//
|
|
|
|
//
|
2003-01-13 00:32:26 +00:00
|
|
|
// This file defines a simple peephole instruction selector for the x86 target
|
2002-10-25 22:55:53 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "X86.h"
|
2002-10-29 21:05:24 +00:00
|
|
|
#include "X86InstrInfo.h"
|
2002-11-17 21:11:55 +00:00
|
|
|
#include "X86InstrBuilder.h"
|
2002-10-25 22:55:53 +00:00
|
|
|
#include "llvm/Function.h"
|
2003-05-13 20:21:19 +00:00
|
|
|
#include "llvm/Instructions.h"
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
#include "llvm/DerivedTypes.h"
|
2002-10-27 21:16:59 +00:00
|
|
|
#include "llvm/Constants.h"
|
2002-10-29 22:37:54 +00:00
|
|
|
#include "llvm/Pass.h"
|
2003-05-08 19:44:13 +00:00
|
|
|
#include "llvm/Intrinsics.h"
|
2002-10-29 17:43:55 +00:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2002-11-20 00:58:23 +00:00
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
2002-12-25 05:13:53 +00:00
|
|
|
#include "llvm/CodeGen/SSARegMap.h"
|
2002-12-28 21:08:28 +00:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
2003-01-13 00:32:26 +00:00
|
|
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
2002-11-20 00:58:23 +00:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
#include "llvm/Target/MRegisterInfo.h"
|
2003-05-13 20:21:19 +00:00
|
|
|
#include "llvm/Support/InstVisitor.h"
|
2002-10-25 22:55:53 +00:00
|
|
|
|
2002-12-13 10:09:43 +00:00
|
|
|
/// BMI - A special BuildMI variant that takes an iterator to insert the
|
2003-04-25 21:58:54 +00:00
|
|
|
/// instruction at as well as a basic block. This is the version for when you
|
|
|
|
/// have a destination register in mind.
|
2002-12-13 11:22:48 +00:00
|
|
|
inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB,
|
2002-12-13 10:09:43 +00:00
|
|
|
MachineBasicBlock::iterator &I,
|
2003-06-03 15:41:58 +00:00
|
|
|
int Opcode, unsigned NumOperands,
|
2002-12-13 10:09:43 +00:00
|
|
|
unsigned DestReg) {
|
2002-12-13 13:04:04 +00:00
|
|
|
assert(I >= MBB->begin() && I <= MBB->end() && "Bad iterator!");
|
2002-12-13 10:09:43 +00:00
|
|
|
MachineInstr *MI = new MachineInstr(Opcode, NumOperands+1, true, true);
|
2002-12-24 00:03:11 +00:00
|
|
|
I = MBB->insert(I, MI)+1;
|
2002-12-13 10:09:43 +00:00
|
|
|
return MachineInstrBuilder(MI).addReg(DestReg, MOTy::Def);
|
|
|
|
}
|
|
|
|
|
2002-12-13 10:50:40 +00:00
|
|
|
/// BMI - A special BuildMI variant that takes an iterator to insert the
|
|
|
|
/// instruction at as well as a basic block.
|
2002-12-13 11:22:48 +00:00
|
|
|
inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB,
|
2002-12-13 10:50:40 +00:00
|
|
|
MachineBasicBlock::iterator &I,
|
2003-06-03 15:41:58 +00:00
|
|
|
int Opcode, unsigned NumOperands) {
|
2003-04-25 21:58:54 +00:00
|
|
|
assert(I >= MBB->begin() && I <= MBB->end() && "Bad iterator!");
|
2002-12-13 10:50:40 +00:00
|
|
|
MachineInstr *MI = new MachineInstr(Opcode, NumOperands, true, true);
|
2002-12-24 00:03:11 +00:00
|
|
|
I = MBB->insert(I, MI)+1;
|
2002-12-13 10:50:40 +00:00
|
|
|
return MachineInstrBuilder(MI);
|
|
|
|
}
|
|
|
|
|
2002-12-13 10:09:43 +00:00
|
|
|
|
2002-10-25 22:55:53 +00:00
|
|
|
namespace {
|
2002-10-29 22:37:54 +00:00
|
|
|
struct ISel : public FunctionPass, InstVisitor<ISel> {
|
|
|
|
TargetMachine &TM;
|
2003-05-08 19:44:13 +00:00
|
|
|
MachineFunction *F; // The function we are compiling into
|
|
|
|
MachineBasicBlock *BB; // The current MBB we are compiling
|
|
|
|
int VarArgsFrameIndex; // FrameIndex for start of varargs area
|
2002-10-25 22:55:53 +00:00
|
|
|
|
|
|
|
std::map<Value*, unsigned> RegMap; // Mapping between Val's and SSA Regs
|
|
|
|
|
2002-12-13 10:09:43 +00:00
|
|
|
// MBBMap - Mapping between LLVM BB -> Machine BB
|
|
|
|
std::map<const BasicBlock*, MachineBasicBlock*> MBBMap;
|
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
ISel(TargetMachine &tm) : TM(tm), F(0), BB(0) {}
|
2002-10-25 22:55:53 +00:00
|
|
|
|
|
|
|
/// runOnFunction - Top level implementation of instruction selection for
|
|
|
|
/// the entire function.
|
|
|
|
///
|
2002-10-29 22:37:54 +00:00
|
|
|
bool runOnFunction(Function &Fn) {
|
2002-10-29 23:40:58 +00:00
|
|
|
F = &MachineFunction::construct(&Fn, TM);
|
2002-12-13 10:09:43 +00:00
|
|
|
|
2002-12-28 20:24:02 +00:00
|
|
|
// Create all of the machine basic blocks for the function...
|
2002-12-13 10:09:43 +00:00
|
|
|
for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
|
|
|
|
F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I));
|
|
|
|
|
2002-12-16 22:54:46 +00:00
|
|
|
BB = &F->front();
|
2003-05-06 21:32:22 +00:00
|
|
|
|
|
|
|
// Copy incoming arguments off of the stack...
|
2002-12-28 20:24:02 +00:00
|
|
|
LoadArgumentsToVirtualRegs(Fn);
|
2002-12-16 22:54:46 +00:00
|
|
|
|
2002-12-13 10:09:43 +00:00
|
|
|
// Instruction select everything except PHI nodes
|
2002-10-29 22:37:54 +00:00
|
|
|
visit(Fn);
|
2002-12-13 10:09:43 +00:00
|
|
|
|
|
|
|
// Select the PHI nodes
|
|
|
|
SelectPHINodes();
|
|
|
|
|
2002-10-25 22:55:53 +00:00
|
|
|
RegMap.clear();
|
2002-12-13 10:09:43 +00:00
|
|
|
MBBMap.clear();
|
2002-10-29 22:37:54 +00:00
|
|
|
F = 0;
|
2003-07-26 23:05:37 +00:00
|
|
|
// We always build a machine code representation for the function
|
|
|
|
return true;
|
2002-10-25 22:55:53 +00:00
|
|
|
}
|
|
|
|
|
2002-12-15 21:13:40 +00:00
|
|
|
virtual const char *getPassName() const {
|
|
|
|
return "X86 Simple Instruction Selection";
|
|
|
|
}
|
|
|
|
|
2002-10-25 22:55:53 +00:00
|
|
|
/// visitBasicBlock - This method is called when we are visiting a new basic
|
2002-10-29 20:48:56 +00:00
|
|
|
/// block. This simply creates a new MachineBasicBlock to emit code into
|
|
|
|
/// and adds it to the current MachineFunction. Subsequent visit* for
|
|
|
|
/// instructions will be invoked for all instructions in the basic block.
|
2002-10-25 22:55:53 +00:00
|
|
|
///
|
|
|
|
void visitBasicBlock(BasicBlock &LLVM_BB) {
|
2002-12-13 10:09:43 +00:00
|
|
|
BB = MBBMap[&LLVM_BB];
|
2002-10-25 22:55:53 +00:00
|
|
|
}
|
|
|
|
|
2002-12-28 20:24:02 +00:00
|
|
|
/// LoadArgumentsToVirtualRegs - Load all of the arguments to this function
|
|
|
|
/// from the stack into virtual registers.
|
|
|
|
///
|
|
|
|
void LoadArgumentsToVirtualRegs(Function &F);
|
2002-12-13 10:09:43 +00:00
|
|
|
|
|
|
|
/// SelectPHINodes - Insert machine code to generate phis. This is tricky
|
|
|
|
/// because we have to generate our sources into the source basic blocks,
|
|
|
|
/// not the current one.
|
|
|
|
///
|
|
|
|
void SelectPHINodes();
|
|
|
|
|
2002-10-25 22:55:53 +00:00
|
|
|
// Visitation methods for various instructions. These methods simply emit
|
|
|
|
// fixed X86 code for each instruction.
|
|
|
|
//
|
2002-11-22 11:07:01 +00:00
|
|
|
|
|
|
|
// Control flow operators
|
2002-10-25 22:55:53 +00:00
|
|
|
void visitReturnInst(ReturnInst &RI);
|
2002-11-02 19:27:56 +00:00
|
|
|
void visitBranchInst(BranchInst &BI);
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
struct ValueRecord {
|
2003-08-04 02:12:48 +00:00
|
|
|
Value *Val;
|
2003-01-13 00:32:26 +00:00
|
|
|
unsigned Reg;
|
|
|
|
const Type *Ty;
|
2003-08-04 02:12:48 +00:00
|
|
|
ValueRecord(unsigned R, const Type *T) : Val(0), Reg(R), Ty(T) {}
|
|
|
|
ValueRecord(Value *V) : Val(V), Reg(0), Ty(V->getType()) {}
|
2003-01-13 00:32:26 +00:00
|
|
|
};
|
|
|
|
void doCall(const ValueRecord &Ret, MachineInstr *CallMI,
|
|
|
|
const std::vector<ValueRecord> &Args);
|
2002-11-22 11:07:01 +00:00
|
|
|
void visitCallInst(CallInst &I);
|
2003-05-08 19:44:13 +00:00
|
|
|
void visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &I);
|
2002-11-02 20:04:26 +00:00
|
|
|
|
|
|
|
// Arithmetic operators
|
2002-11-02 20:54:46 +00:00
|
|
|
void visitSimpleBinary(BinaryOperator &B, unsigned OpcodeClass);
|
2002-11-02 20:13:22 +00:00
|
|
|
void visitAdd(BinaryOperator &B) { visitSimpleBinary(B, 0); }
|
|
|
|
void visitSub(BinaryOperator &B) { visitSimpleBinary(B, 1); }
|
2002-12-16 19:32:50 +00:00
|
|
|
void doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI,
|
2003-01-13 00:32:26 +00:00
|
|
|
unsigned DestReg, const Type *DestTy,
|
|
|
|
unsigned Op0Reg, unsigned Op1Reg);
|
2002-11-02 20:28:58 +00:00
|
|
|
void visitMul(BinaryOperator &B);
|
2002-11-02 20:04:26 +00:00
|
|
|
|
2002-11-02 20:54:46 +00:00
|
|
|
void visitDiv(BinaryOperator &B) { visitDivRem(B); }
|
|
|
|
void visitRem(BinaryOperator &B) { visitDivRem(B); }
|
|
|
|
void visitDivRem(BinaryOperator &B);
|
|
|
|
|
2002-11-02 20:04:26 +00:00
|
|
|
// Bitwise operators
|
2002-11-02 20:13:22 +00:00
|
|
|
void visitAnd(BinaryOperator &B) { visitSimpleBinary(B, 2); }
|
|
|
|
void visitOr (BinaryOperator &B) { visitSimpleBinary(B, 3); }
|
|
|
|
void visitXor(BinaryOperator &B) { visitSimpleBinary(B, 4); }
|
2002-11-02 20:04:26 +00:00
|
|
|
|
2003-01-16 16:43:00 +00:00
|
|
|
// Comparison operators...
|
|
|
|
void visitSetCondInst(SetCondInst &I);
|
|
|
|
bool EmitComparisonGetSignedness(unsigned OpNum, Value *Op0, Value *Op1);
|
2002-11-17 21:11:55 +00:00
|
|
|
|
|
|
|
// Memory Instructions
|
2003-01-13 00:32:26 +00:00
|
|
|
MachineInstr *doFPLoad(MachineBasicBlock *MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
|
|
|
const Type *Ty, unsigned DestReg);
|
2002-11-17 21:11:55 +00:00
|
|
|
void visitLoadInst(LoadInst &I);
|
2003-01-13 00:32:26 +00:00
|
|
|
void doFPStore(const Type *Ty, unsigned DestAddrReg, unsigned SrcReg);
|
2002-11-17 21:11:55 +00:00
|
|
|
void visitStoreInst(StoreInst &I);
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
void visitGetElementPtrInst(GetElementPtrInst &I);
|
|
|
|
void visitAllocaInst(AllocaInst &I);
|
2003-01-13 00:32:26 +00:00
|
|
|
void visitMallocInst(MallocInst &I);
|
|
|
|
void visitFreeInst(FreeInst &I);
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
|
2002-11-02 20:04:26 +00:00
|
|
|
// Other operators
|
2002-10-31 23:03:59 +00:00
|
|
|
void visitShiftInst(ShiftInst &I);
|
2002-12-13 10:09:43 +00:00
|
|
|
void visitPHINode(PHINode &I) {} // PHI nodes handled by second pass
|
2002-11-22 11:07:01 +00:00
|
|
|
void visitCastInst(CastInst &I);
|
2003-05-08 19:44:13 +00:00
|
|
|
void visitVarArgInst(VarArgInst &I);
|
2002-10-25 22:55:53 +00:00
|
|
|
|
|
|
|
void visitInstruction(Instruction &I) {
|
|
|
|
std::cerr << "Cannot instruction select: " << I;
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2002-12-13 07:56:18 +00:00
|
|
|
/// promote32 - Make a value 32-bits wide, and put it somewhere.
|
2003-01-13 00:32:26 +00:00
|
|
|
///
|
|
|
|
void promote32(unsigned targetReg, const ValueRecord &VR);
|
|
|
|
|
|
|
|
/// EmitByteSwap - Byteswap SrcReg into DestReg.
|
|
|
|
///
|
|
|
|
void EmitByteSwap(unsigned DestReg, unsigned SrcReg, unsigned Class);
|
2002-12-13 07:56:18 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
/// emitGEPOperation - Common code shared between visitGetElementPtrInst and
|
|
|
|
/// constant expression GEP support.
|
|
|
|
///
|
2002-12-13 10:50:40 +00:00
|
|
|
void emitGEPOperation(MachineBasicBlock *BB, MachineBasicBlock::iterator&IP,
|
2002-12-13 10:09:43 +00:00
|
|
|
Value *Src, User::op_iterator IdxBegin,
|
2002-12-13 06:56:29 +00:00
|
|
|
User::op_iterator IdxEnd, unsigned TargetReg);
|
|
|
|
|
2003-04-23 17:22:12 +00:00
|
|
|
/// emitCastOperation - Common code shared between visitCastInst and
|
|
|
|
/// constant expression cast support.
|
|
|
|
void emitCastOperation(MachineBasicBlock *BB,MachineBasicBlock::iterator&IP,
|
|
|
|
Value *Src, const Type *DestTy, unsigned TargetReg);
|
|
|
|
|
2003-05-08 20:49:25 +00:00
|
|
|
/// emitSimpleBinaryOperation - Common code shared between visitSimpleBinary
|
|
|
|
/// and constant expression support.
|
|
|
|
void emitSimpleBinaryOperation(MachineBasicBlock *BB,
|
|
|
|
MachineBasicBlock::iterator &IP,
|
|
|
|
Value *Op0, Value *Op1,
|
|
|
|
unsigned OperatorClass, unsigned TargetReg);
|
|
|
|
|
2002-10-27 21:16:59 +00:00
|
|
|
/// copyConstantToRegister - Output the instructions required to put the
|
|
|
|
/// specified constant into the specified register.
|
|
|
|
///
|
2002-12-16 19:32:50 +00:00
|
|
|
void copyConstantToRegister(MachineBasicBlock *MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
|
|
|
Constant *C, unsigned Reg);
|
2002-10-27 21:16:59 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
/// makeAnotherReg - This method returns the next register number we haven't
|
|
|
|
/// yet used.
|
|
|
|
///
|
|
|
|
/// Long values are handled somewhat specially. They are always allocated
|
|
|
|
/// as pairs of 32 bit integer values. The register number returned is the
|
|
|
|
/// lower 32 bits of the long value, and the regNum+1 is the upper 32 bits
|
|
|
|
/// of the long value.
|
|
|
|
///
|
2002-12-13 06:56:29 +00:00
|
|
|
unsigned makeAnotherReg(const Type *Ty) {
|
2003-07-30 05:33:48 +00:00
|
|
|
assert(dynamic_cast<const X86RegisterInfo*>(TM.getRegisterInfo()) &&
|
|
|
|
"Current target doesn't have X86 reg info??");
|
|
|
|
const X86RegisterInfo *MRI =
|
|
|
|
static_cast<const X86RegisterInfo*>(TM.getRegisterInfo());
|
2003-01-13 00:32:26 +00:00
|
|
|
if (Ty == Type::LongTy || Ty == Type::ULongTy) {
|
2003-07-30 05:33:48 +00:00
|
|
|
const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy);
|
2003-01-13 00:32:26 +00:00
|
|
|
// Create the lower part
|
|
|
|
F->getSSARegMap()->createVirtualRegister(RC);
|
|
|
|
// Create the upper part.
|
|
|
|
return F->getSSARegMap()->createVirtualRegister(RC)-1;
|
|
|
|
}
|
|
|
|
|
2002-12-13 06:56:29 +00:00
|
|
|
// Add the mapping of regnumber => reg class to MachineFunction
|
2003-07-30 05:33:48 +00:00
|
|
|
const TargetRegisterClass *RC = MRI->getRegClassForType(Ty);
|
2003-01-13 00:32:26 +00:00
|
|
|
return F->getSSARegMap()->createVirtualRegister(RC);
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
}
|
|
|
|
|
2002-10-25 22:55:53 +00:00
|
|
|
/// getReg - This method turns an LLVM value into a register number. This
|
|
|
|
/// is guaranteed to produce the same register number for a particular value
|
|
|
|
/// every time it is queried.
|
|
|
|
///
|
|
|
|
unsigned getReg(Value &V) { return getReg(&V); } // Allow references
|
2002-12-13 10:50:40 +00:00
|
|
|
unsigned getReg(Value *V) {
|
|
|
|
// Just append to the end of the current bb.
|
|
|
|
MachineBasicBlock::iterator It = BB->end();
|
|
|
|
return getReg(V, BB, It);
|
|
|
|
}
|
2002-12-13 11:22:48 +00:00
|
|
|
unsigned getReg(Value *V, MachineBasicBlock *MBB,
|
2002-12-13 10:50:40 +00:00
|
|
|
MachineBasicBlock::iterator &IPt) {
|
2002-10-25 22:55:53 +00:00
|
|
|
unsigned &Reg = RegMap[V];
|
2002-11-20 00:58:23 +00:00
|
|
|
if (Reg == 0) {
|
2002-12-13 06:56:29 +00:00
|
|
|
Reg = makeAnotherReg(V->getType());
|
2002-11-20 00:58:23 +00:00
|
|
|
RegMap[V] = Reg;
|
|
|
|
}
|
2002-10-25 22:55:53 +00:00
|
|
|
|
2002-10-27 21:23:43 +00:00
|
|
|
// If this operand is a constant, emit the code to copy the constant into
|
|
|
|
// the register here...
|
|
|
|
//
|
2002-12-04 06:45:19 +00:00
|
|
|
if (Constant *C = dyn_cast<Constant>(V)) {
|
2002-12-16 19:32:50 +00:00
|
|
|
copyConstantToRegister(MBB, IPt, C, Reg);
|
2002-12-16 22:54:46 +00:00
|
|
|
RegMap.erase(V); // Assign a new name to this constant if ref'd again
|
2002-12-04 06:45:19 +00:00
|
|
|
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
|
|
|
|
// Move the address of the global into the register
|
2003-01-13 00:32:26 +00:00
|
|
|
BMI(MBB, IPt, X86::MOVir32, 1, Reg).addGlobalAddress(GV);
|
2002-12-16 22:54:46 +00:00
|
|
|
RegMap.erase(V); // Assign a new name to this address if ref'd again
|
2002-12-04 06:45:19 +00:00
|
|
|
}
|
2002-10-27 21:16:59 +00:00
|
|
|
|
2002-10-25 22:55:53 +00:00
|
|
|
return Reg;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2002-11-17 20:07:45 +00:00
|
|
|
/// TypeClass - Used by the X86 backend to group LLVM types by their basic X86
|
|
|
|
/// Representation.
|
|
|
|
///
|
|
|
|
enum TypeClass {
|
2002-12-25 05:13:53 +00:00
|
|
|
cByte, cShort, cInt, cFP, cLong
|
2002-11-17 20:07:45 +00:00
|
|
|
};
|
|
|
|
|
2002-11-02 01:15:18 +00:00
|
|
|
/// getClass - Turn a primitive type into a "class" number which is based on the
|
|
|
|
/// size of the type, and whether or not it is floating point.
|
|
|
|
///
|
2002-11-17 20:07:45 +00:00
|
|
|
static inline TypeClass getClass(const Type *Ty) {
|
2002-11-02 01:15:18 +00:00
|
|
|
switch (Ty->getPrimitiveID()) {
|
|
|
|
case Type::SByteTyID:
|
2002-11-17 20:07:45 +00:00
|
|
|
case Type::UByteTyID: return cByte; // Byte operands are class #0
|
2002-11-02 01:15:18 +00:00
|
|
|
case Type::ShortTyID:
|
2002-11-17 20:07:45 +00:00
|
|
|
case Type::UShortTyID: return cShort; // Short operands are class #1
|
2002-11-02 01:15:18 +00:00
|
|
|
case Type::IntTyID:
|
|
|
|
case Type::UIntTyID:
|
2002-11-17 20:07:45 +00:00
|
|
|
case Type::PointerTyID: return cInt; // Int's and pointers are class #2
|
2002-11-02 01:15:18 +00:00
|
|
|
|
2002-12-25 05:13:53 +00:00
|
|
|
case Type::FloatTyID:
|
|
|
|
case Type::DoubleTyID: return cFP; // Floating Point is #3
|
2003-01-13 00:32:26 +00:00
|
|
|
|
2002-11-02 01:15:18 +00:00
|
|
|
case Type::LongTyID:
|
2003-01-13 00:32:26 +00:00
|
|
|
case Type::ULongTyID: return cLong; // Longs are class #4
|
2002-11-02 01:15:18 +00:00
|
|
|
default:
|
|
|
|
assert(0 && "Invalid type to getClass!");
|
2002-11-17 20:07:45 +00:00
|
|
|
return cByte; // not reached
|
2002-11-02 01:15:18 +00:00
|
|
|
}
|
|
|
|
}
|
2002-10-27 21:16:59 +00:00
|
|
|
|
2002-12-15 08:02:15 +00:00
|
|
|
// getClassB - Just like getClass, but treat boolean values as bytes.
|
|
|
|
static inline TypeClass getClassB(const Type *Ty) {
|
|
|
|
if (Ty == Type::BoolTy) return cByte;
|
|
|
|
return getClass(Ty);
|
|
|
|
}
|
|
|
|
|
2002-11-17 21:56:38 +00:00
|
|
|
|
2002-10-27 21:16:59 +00:00
|
|
|
/// copyConstantToRegister - Output the instructions required to put the
|
|
|
|
/// specified constant into the specified register.
|
|
|
|
///
|
2002-12-16 19:32:50 +00:00
|
|
|
void ISel::copyConstantToRegister(MachineBasicBlock *MBB,
|
|
|
|
MachineBasicBlock::iterator &IP,
|
|
|
|
Constant *C, unsigned R) {
|
2002-12-13 06:56:29 +00:00
|
|
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
|
2003-05-08 20:49:25 +00:00
|
|
|
unsigned Class = 0;
|
|
|
|
switch (CE->getOpcode()) {
|
|
|
|
case Instruction::GetElementPtr:
|
2002-12-16 04:23:29 +00:00
|
|
|
emitGEPOperation(MBB, IP, CE->getOperand(0),
|
2002-12-13 10:09:43 +00:00
|
|
|
CE->op_begin()+1, CE->op_end(), R);
|
2002-12-13 06:56:29 +00:00
|
|
|
return;
|
2003-05-08 20:49:25 +00:00
|
|
|
case Instruction::Cast:
|
2003-04-23 17:22:12 +00:00
|
|
|
emitCastOperation(MBB, IP, CE->getOperand(0), CE->getType(), R);
|
2003-04-21 21:33:44 +00:00
|
|
|
return;
|
2002-12-13 06:56:29 +00:00
|
|
|
|
2003-05-08 20:49:25 +00:00
|
|
|
case Instruction::Xor: ++Class; // FALL THROUGH
|
|
|
|
case Instruction::Or: ++Class; // FALL THROUGH
|
|
|
|
case Instruction::And: ++Class; // FALL THROUGH
|
|
|
|
case Instruction::Sub: ++Class; // FALL THROUGH
|
|
|
|
case Instruction::Add:
|
|
|
|
emitSimpleBinaryOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1),
|
|
|
|
Class, R);
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
std::cerr << "Offending expr: " << C << "\n";
|
|
|
|
assert(0 && "Constant expressions not yet handled!\n");
|
|
|
|
}
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
}
|
2002-10-27 21:16:59 +00:00
|
|
|
|
2002-11-02 01:15:18 +00:00
|
|
|
if (C->getType()->isIntegral()) {
|
2002-12-15 08:02:15 +00:00
|
|
|
unsigned Class = getClassB(C->getType());
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
if (Class == cLong) {
|
|
|
|
// Copy the value into the register pair.
|
2003-07-23 15:22:26 +00:00
|
|
|
uint64_t Val = cast<ConstantInt>(C)->getRawValue();
|
2003-01-13 00:32:26 +00:00
|
|
|
BMI(MBB, IP, X86::MOVir32, 1, R).addZImm(Val & 0xFFFFFFFF);
|
|
|
|
BMI(MBB, IP, X86::MOVir32, 1, R+1).addZImm(Val >> 32);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-12-25 05:13:53 +00:00
|
|
|
assert(Class <= cInt && "Type not handled yet!");
|
2002-11-02 01:15:18 +00:00
|
|
|
|
|
|
|
static const unsigned IntegralOpcodeTab[] = {
|
|
|
|
X86::MOVir8, X86::MOVir16, X86::MOVir32
|
|
|
|
};
|
|
|
|
|
2002-12-15 08:02:15 +00:00
|
|
|
if (C->getType() == Type::BoolTy) {
|
|
|
|
BMI(MBB, IP, X86::MOVir8, 1, R).addZImm(C == ConstantBool::True);
|
2002-11-02 01:15:18 +00:00
|
|
|
} else {
|
2003-07-23 15:22:26 +00:00
|
|
|
ConstantInt *CI = cast<ConstantInt>(C);
|
|
|
|
BMI(MBB, IP, IntegralOpcodeTab[Class], 1, R).addZImm(CI->getRawValue());
|
2002-11-02 01:15:18 +00:00
|
|
|
}
|
2002-12-25 05:13:53 +00:00
|
|
|
} else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
|
|
|
|
double Value = CFP->getValue();
|
|
|
|
if (Value == +0.0)
|
|
|
|
BMI(MBB, IP, X86::FLD0, 0, R);
|
|
|
|
else if (Value == +1.0)
|
|
|
|
BMI(MBB, IP, X86::FLD1, 0, R);
|
|
|
|
else {
|
2003-01-13 00:32:26 +00:00
|
|
|
// Otherwise we need to spill the constant to memory...
|
|
|
|
MachineConstantPool *CP = F->getConstantPool();
|
|
|
|
unsigned CPI = CP->getConstantPoolIndex(CFP);
|
|
|
|
addConstantPoolReference(doFPLoad(MBB, IP, CFP->getType(), R), CPI);
|
2002-12-25 05:13:53 +00:00
|
|
|
}
|
|
|
|
|
2002-12-13 10:50:40 +00:00
|
|
|
} else if (isa<ConstantPointerNull>(C)) {
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
// Copy zero (null pointer) to the register.
|
2002-12-13 11:22:48 +00:00
|
|
|
BMI(MBB, IP, X86::MOVir32, 1, R).addZImm(0);
|
2002-12-13 06:56:29 +00:00
|
|
|
} else if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)) {
|
2002-12-16 04:23:29 +00:00
|
|
|
unsigned SrcReg = getReg(CPR->getValue(), MBB, IP);
|
2002-12-13 11:22:48 +00:00
|
|
|
BMI(MBB, IP, X86::MOVrr32, 1, R).addReg(SrcReg);
|
2002-11-02 01:15:18 +00:00
|
|
|
} else {
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
std::cerr << "Offending constant: " << C << "\n";
|
2002-11-02 01:15:18 +00:00
|
|
|
assert(0 && "Type not handled yet!");
|
2002-10-27 21:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-12-28 20:24:02 +00:00
|
|
|
/// LoadArgumentsToVirtualRegs - Load all of the arguments to this function from
|
|
|
|
/// the stack into virtual registers.
|
|
|
|
///
|
|
|
|
void ISel::LoadArgumentsToVirtualRegs(Function &Fn) {
|
|
|
|
// Emit instructions to load the arguments... On entry to a function on the
|
|
|
|
// X86, the stack frame looks like this:
|
|
|
|
//
|
|
|
|
// [ESP] -- return address
|
2003-01-13 00:32:26 +00:00
|
|
|
// [ESP + 4] -- first argument (leftmost lexically)
|
|
|
|
// [ESP + 8] -- second argument, if first argument is four bytes in size
|
2002-12-28 20:24:02 +00:00
|
|
|
// ...
|
|
|
|
//
|
2003-01-16 02:20:12 +00:00
|
|
|
unsigned ArgOffset = 0; // Frame mechanisms handle retaddr slot
|
2002-12-28 21:08:28 +00:00
|
|
|
MachineFrameInfo *MFI = F->getFrameInfo();
|
2002-12-28 20:24:02 +00:00
|
|
|
|
|
|
|
for (Function::aiterator I = Fn.abegin(), E = Fn.aend(); I != E; ++I) {
|
|
|
|
unsigned Reg = getReg(*I);
|
|
|
|
|
|
|
|
int FI; // Frame object index
|
|
|
|
switch (getClassB(I->getType())) {
|
|
|
|
case cByte:
|
2002-12-28 21:08:28 +00:00
|
|
|
FI = MFI->CreateFixedObject(1, ArgOffset);
|
2002-12-28 20:24:02 +00:00
|
|
|
addFrameReference(BuildMI(BB, X86::MOVmr8, 4, Reg), FI);
|
|
|
|
break;
|
|
|
|
case cShort:
|
2002-12-28 21:08:28 +00:00
|
|
|
FI = MFI->CreateFixedObject(2, ArgOffset);
|
2002-12-28 20:24:02 +00:00
|
|
|
addFrameReference(BuildMI(BB, X86::MOVmr16, 4, Reg), FI);
|
|
|
|
break;
|
|
|
|
case cInt:
|
2002-12-28 21:08:28 +00:00
|
|
|
FI = MFI->CreateFixedObject(4, ArgOffset);
|
2002-12-28 20:24:02 +00:00
|
|
|
addFrameReference(BuildMI(BB, X86::MOVmr32, 4, Reg), FI);
|
|
|
|
break;
|
2003-01-13 00:32:26 +00:00
|
|
|
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);
|
|
|
|
ArgOffset += 4; // longs require 4 additional bytes
|
|
|
|
break;
|
2002-12-28 20:24:02 +00:00
|
|
|
case cFP:
|
|
|
|
unsigned Opcode;
|
|
|
|
if (I->getType() == Type::FloatTy) {
|
|
|
|
Opcode = X86::FLDr32;
|
2002-12-28 21:08:28 +00:00
|
|
|
FI = MFI->CreateFixedObject(4, ArgOffset);
|
2002-12-28 20:24:02 +00:00
|
|
|
} else {
|
|
|
|
Opcode = X86::FLDr64;
|
2002-12-28 21:08:28 +00:00
|
|
|
FI = MFI->CreateFixedObject(8, ArgOffset);
|
2003-01-13 00:32:26 +00:00
|
|
|
ArgOffset += 4; // doubles require 4 additional bytes
|
2002-12-28 20:24:02 +00:00
|
|
|
}
|
|
|
|
addFrameReference(BuildMI(BB, Opcode, 4, Reg), FI);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0 && "Unhandled argument type!");
|
|
|
|
}
|
2003-01-13 00:32:26 +00:00
|
|
|
ArgOffset += 4; // Each argument takes at least 4 bytes on the stack...
|
2002-12-28 20:24:02 +00:00
|
|
|
}
|
2003-05-08 19:44:13 +00:00
|
|
|
|
|
|
|
// If the function takes variable number of arguments, add a frame offset for
|
|
|
|
// the start of the first vararg value... this is used to expand
|
|
|
|
// llvm.va_start.
|
|
|
|
if (Fn.getFunctionType()->isVarArg())
|
|
|
|
VarArgsFrameIndex = MFI->CreateFixedObject(1, ArgOffset);
|
2002-12-28 20:24:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-12-13 10:09:43 +00:00
|
|
|
/// SelectPHINodes - Insert machine code to generate phis. This is tricky
|
|
|
|
/// because we have to generate our sources into the source basic blocks, not
|
|
|
|
/// the current one.
|
|
|
|
///
|
|
|
|
void ISel::SelectPHINodes() {
|
2003-01-14 22:00:31 +00:00
|
|
|
const TargetInstrInfo &TII = TM.getInstrInfo();
|
2002-12-13 10:09:43 +00:00
|
|
|
const Function &LF = *F->getFunction(); // The LLVM function...
|
|
|
|
for (Function::const_iterator I = LF.begin(), E = LF.end(); I != E; ++I) {
|
|
|
|
const BasicBlock *BB = I;
|
|
|
|
MachineBasicBlock *MBB = MBBMap[I];
|
|
|
|
|
|
|
|
// Loop over all of the PHI nodes in the LLVM basic block...
|
|
|
|
unsigned NumPHIs = 0;
|
|
|
|
for (BasicBlock::const_iterator I = BB->begin();
|
2003-04-23 17:22:12 +00:00
|
|
|
PHINode *PN = (PHINode*)dyn_cast<PHINode>(I); ++I) {
|
2003-01-13 00:32:26 +00:00
|
|
|
|
2002-12-13 10:09:43 +00:00
|
|
|
// Create a new machine instr PHI node, and insert it.
|
2003-01-13 00:32:26 +00:00
|
|
|
unsigned PHIReg = getReg(*PN);
|
|
|
|
MachineInstr *PhiMI = BuildMI(X86::PHI, PN->getNumOperands(), PHIReg);
|
|
|
|
MBB->insert(MBB->begin()+NumPHIs++, 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);
|
|
|
|
}
|
2002-12-13 10:09:43 +00:00
|
|
|
|
2003-05-12 14:22:21 +00:00
|
|
|
// PHIValues - Map of blocks to incoming virtual registers. We use this
|
|
|
|
// so that we only initialize one incoming value for a particular block,
|
|
|
|
// even if the block has multiple entries in the PHI node.
|
|
|
|
//
|
|
|
|
std::map<MachineBasicBlock*, unsigned> PHIValues;
|
|
|
|
|
2002-12-13 10:09:43 +00:00
|
|
|
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
|
|
|
|
MachineBasicBlock *PredMBB = MBBMap[PN->getIncomingBlock(i)];
|
2003-05-12 14:22:21 +00:00
|
|
|
unsigned ValReg;
|
|
|
|
std::map<MachineBasicBlock*, unsigned>::iterator EntryIt =
|
|
|
|
PHIValues.lower_bound(PredMBB);
|
|
|
|
|
|
|
|
if (EntryIt != PHIValues.end() && EntryIt->first == PredMBB) {
|
|
|
|
// We already inserted an initialization of the register for this
|
|
|
|
// predecessor. Recycle it.
|
|
|
|
ValReg = EntryIt->second;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// Get the incoming value into a virtual register. If it is not
|
|
|
|
// already available in a virtual register, insert the computation
|
|
|
|
// code into PredMBB
|
|
|
|
//
|
|
|
|
MachineBasicBlock::iterator PI = PredMBB->end();
|
|
|
|
while (PI != PredMBB->begin() &&
|
|
|
|
TII.isTerminatorInstr((*(PI-1))->getOpcode()))
|
|
|
|
--PI;
|
|
|
|
ValReg = getReg(PN->getIncomingValue(i), PredMBB, PI);
|
|
|
|
|
|
|
|
// Remember that we inserted a value for this PHI for this predecessor
|
|
|
|
PHIValues.insert(EntryIt, std::make_pair(PredMBB, ValReg));
|
|
|
|
}
|
2002-12-13 10:09:43 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
PhiMI->addRegOperand(ValReg);
|
|
|
|
PhiMI->addMachineBasicBlockOperand(PredMBB);
|
|
|
|
if (LongPhiMI) {
|
|
|
|
LongPhiMI->addRegOperand(ValReg+1);
|
|
|
|
LongPhiMI->addMachineBasicBlockOperand(PredMBB);
|
|
|
|
}
|
2002-12-13 10:09:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-16 16:43:00 +00:00
|
|
|
// canFoldSetCCIntoBranch - Return the setcc instruction if we can fold it into
|
|
|
|
// the conditional branch instruction which is the only user of the cc
|
|
|
|
// instruction. This is the case if the conditional branch is the only user of
|
|
|
|
// the setcc, and if the setcc is in the same basic block as the conditional
|
|
|
|
// branch. We also don't handle long arguments below, so we reject them here as
|
|
|
|
// well.
|
|
|
|
//
|
|
|
|
static SetCondInst *canFoldSetCCIntoBranch(Value *V) {
|
|
|
|
if (SetCondInst *SCI = dyn_cast<SetCondInst>(V))
|
|
|
|
if (SCI->use_size() == 1 && isa<BranchInst>(SCI->use_back()) &&
|
|
|
|
SCI->getParent() == cast<BranchInst>(SCI->use_back())->getParent()) {
|
|
|
|
const Type *Ty = SCI->getOperand(0)->getType();
|
|
|
|
if (Ty != Type::LongTy && Ty != Type::ULongTy)
|
|
|
|
return SCI;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2002-12-13 10:09:43 +00:00
|
|
|
|
2003-01-16 16:43:00 +00:00
|
|
|
// Return a fixed numbering for setcc instructions which does not depend on the
|
|
|
|
// order of the opcodes.
|
|
|
|
//
|
|
|
|
static unsigned getSetCCNumber(unsigned Opcode) {
|
|
|
|
switch(Opcode) {
|
|
|
|
default: assert(0 && "Unknown setcc instruction!");
|
|
|
|
case Instruction::SetEQ: return 0;
|
|
|
|
case Instruction::SetNE: return 1;
|
|
|
|
case Instruction::SetLT: return 2;
|
2003-01-16 18:07:23 +00:00
|
|
|
case Instruction::SetGE: return 3;
|
|
|
|
case Instruction::SetGT: return 4;
|
|
|
|
case Instruction::SetLE: return 5;
|
2003-01-16 16:43:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// LLVM -> X86 signed X86 unsigned
|
|
|
|
// ----- ---------- ------------
|
|
|
|
// seteq -> sete sete
|
|
|
|
// setne -> setne setne
|
|
|
|
// setlt -> setl setb
|
2003-01-16 18:07:23 +00:00
|
|
|
// setge -> setge setae
|
2003-01-16 16:43:00 +00:00
|
|
|
// setgt -> setg seta
|
|
|
|
// setle -> setle setbe
|
|
|
|
static const unsigned SetCCOpcodeTab[2][6] = {
|
2003-01-16 18:07:23 +00:00
|
|
|
{X86::SETEr, X86::SETNEr, X86::SETBr, X86::SETAEr, X86::SETAr, X86::SETBEr},
|
|
|
|
{X86::SETEr, X86::SETNEr, X86::SETLr, X86::SETGEr, X86::SETGr, X86::SETLEr},
|
2003-01-16 16:43:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
bool ISel::EmitComparisonGetSignedness(unsigned OpNum, Value *Op0, Value *Op1) {
|
2002-11-17 21:56:38 +00:00
|
|
|
|
2002-11-07 17:59:21 +00:00
|
|
|
// The arguments are already supposed to be of the same type.
|
2003-01-16 16:43:00 +00:00
|
|
|
const Type *CompTy = Op0->getType();
|
2003-01-13 00:32:26 +00:00
|
|
|
bool isSigned = CompTy->isSigned();
|
|
|
|
unsigned Class = getClassB(CompTy);
|
2003-06-05 19:30:30 +00:00
|
|
|
unsigned Op0r = getReg(Op0);
|
|
|
|
|
|
|
|
// Special case handling of: cmp R, i
|
|
|
|
if (Class == cByte || Class == cShort || Class == cInt)
|
|
|
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
|
2003-07-23 15:22:26 +00:00
|
|
|
uint64_t Op1v = cast<ConstantInt>(CI)->getRawValue();
|
|
|
|
|
2003-06-05 19:30:30 +00:00
|
|
|
// Mask off any upper bits of the constant, if there are any...
|
|
|
|
Op1v &= (1ULL << (8 << Class)) - 1;
|
|
|
|
|
|
|
|
switch (Class) {
|
|
|
|
case cByte: BuildMI(BB, X86::CMPri8, 2).addReg(Op0r).addZImm(Op1v);break;
|
|
|
|
case cShort: BuildMI(BB, X86::CMPri16,2).addReg(Op0r).addZImm(Op1v);break;
|
|
|
|
case cInt: BuildMI(BB, X86::CMPri32,2).addReg(Op0r).addZImm(Op1v);break;
|
|
|
|
default:
|
|
|
|
assert(0 && "Invalid class!");
|
|
|
|
}
|
|
|
|
return isSigned;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned Op1r = getReg(Op1);
|
2002-11-21 15:52:38 +00:00
|
|
|
switch (Class) {
|
2003-01-13 00:32:26 +00:00
|
|
|
default: assert(0 && "Unknown type class!");
|
2002-11-21 15:52:38 +00:00
|
|
|
// Emit: cmp <var1>, <var2> (do the comparison). We can
|
|
|
|
// compare 8-bit with 8-bit, 16-bit with 16-bit, 32-bit with
|
|
|
|
// 32-bit.
|
|
|
|
case cByte:
|
2003-06-05 19:30:30 +00:00
|
|
|
BuildMI(BB, X86::CMPrr8, 2).addReg(Op0r).addReg(Op1r);
|
2002-11-21 15:52:38 +00:00
|
|
|
break;
|
|
|
|
case cShort:
|
2003-06-05 19:30:30 +00:00
|
|
|
BuildMI(BB, X86::CMPrr16, 2).addReg(Op0r).addReg(Op1r);
|
2002-11-21 15:52:38 +00:00
|
|
|
break;
|
|
|
|
case cInt:
|
2003-06-05 19:30:30 +00:00
|
|
|
BuildMI(BB, X86::CMPrr32, 2).addReg(Op0r).addReg(Op1r);
|
2002-11-21 15:52:38 +00:00
|
|
|
break;
|
2003-01-13 00:32:26 +00:00
|
|
|
case cFP:
|
2003-06-05 19:30:30 +00:00
|
|
|
BuildMI(BB, X86::FpUCOM, 2).addReg(Op0r).addReg(Op1r);
|
2003-01-13 00:32:26 +00:00
|
|
|
BuildMI(BB, X86::FNSTSWr8, 0);
|
|
|
|
BuildMI(BB, X86::SAHF, 1);
|
|
|
|
isSigned = false; // Compare with unsigned operators
|
2002-11-21 15:52:38 +00:00
|
|
|
break;
|
2003-01-13 00:32:26 +00:00
|
|
|
|
2002-11-21 15:52:38 +00:00
|
|
|
case cLong:
|
2003-01-13 00:32:26 +00:00
|
|
|
if (OpNum < 2) { // seteq, setne
|
|
|
|
unsigned LoTmp = makeAnotherReg(Type::IntTy);
|
|
|
|
unsigned HiTmp = makeAnotherReg(Type::IntTy);
|
|
|
|
unsigned FinalTmp = makeAnotherReg(Type::IntTy);
|
2003-06-05 19:30:30 +00:00
|
|
|
BuildMI(BB, X86::XORrr32, 2, LoTmp).addReg(Op0r).addReg(Op1r);
|
|
|
|
BuildMI(BB, X86::XORrr32, 2, HiTmp).addReg(Op0r+1).addReg(Op1r+1);
|
2003-01-13 00:32:26 +00:00
|
|
|
BuildMI(BB, X86::ORrr32, 2, FinalTmp).addReg(LoTmp).addReg(HiTmp);
|
|
|
|
break; // Allow the sete or setne to be generated from flags set by OR
|
|
|
|
} else {
|
|
|
|
// Emit a sequence of code which compares the high and low parts once
|
|
|
|
// each, then uses a conditional move to handle the overflow case. For
|
|
|
|
// example, a setlt for long would generate code like this:
|
|
|
|
//
|
|
|
|
// AL = lo(op1) < lo(op2) // Signedness depends on operands
|
|
|
|
// BL = hi(op1) < hi(op2) // Always unsigned comparison
|
|
|
|
// dest = hi(op1) == hi(op2) ? AL : BL;
|
|
|
|
//
|
2002-11-21 15:52:38 +00:00
|
|
|
|
2003-01-16 16:43:00 +00:00
|
|
|
// FIXME: This would be much better if we had hierarchical register
|
2003-01-13 00:32:26 +00:00
|
|
|
// classes! Until then, hardcode registers so that we can deal with their
|
|
|
|
// aliases (because we don't have conditional byte moves).
|
|
|
|
//
|
2003-06-05 19:30:30 +00:00
|
|
|
BuildMI(BB, X86::CMPrr32, 2).addReg(Op0r).addReg(Op1r);
|
2003-01-16 16:43:00 +00:00
|
|
|
BuildMI(BB, SetCCOpcodeTab[0][OpNum], 0, X86::AL);
|
2003-06-05 19:30:30 +00:00
|
|
|
BuildMI(BB, X86::CMPrr32, 2).addReg(Op0r+1).addReg(Op1r+1);
|
2003-01-16 16:43:00 +00:00
|
|
|
BuildMI(BB, SetCCOpcodeTab[isSigned][OpNum], 0, X86::BL);
|
2003-01-13 00:32:26 +00:00
|
|
|
BuildMI(BB, X86::CMOVErr16, 2, X86::BX).addReg(X86::BX).addReg(X86::AX);
|
2003-01-16 16:43:00 +00:00
|
|
|
// NOTE: visitSetCondInst knows that the value is dumped into the BL
|
|
|
|
// register at this point for long values...
|
|
|
|
return isSigned;
|
2003-01-13 00:32:26 +00:00
|
|
|
}
|
2002-11-21 15:52:38 +00:00
|
|
|
}
|
2003-01-16 16:43:00 +00:00
|
|
|
return isSigned;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// SetCC instructions - Here we just emit boilerplate code to set a byte-sized
|
|
|
|
/// register, then move it to wherever the result should be.
|
|
|
|
///
|
|
|
|
void ISel::visitSetCondInst(SetCondInst &I) {
|
|
|
|
if (canFoldSetCCIntoBranch(&I)) return; // Fold this into a branch...
|
|
|
|
|
|
|
|
unsigned OpNum = getSetCCNumber(I.getOpcode());
|
|
|
|
unsigned DestReg = getReg(I);
|
|
|
|
bool isSigned = EmitComparisonGetSignedness(OpNum, I.getOperand(0),
|
|
|
|
I.getOperand(1));
|
2002-11-21 15:52:38 +00:00
|
|
|
|
2003-01-16 16:43:00 +00:00
|
|
|
if (getClassB(I.getOperand(0)->getType()) != cLong || OpNum < 2) {
|
|
|
|
// Handle normal comparisons with a setcc instruction...
|
|
|
|
BuildMI(BB, SetCCOpcodeTab[isSigned][OpNum], 0, DestReg);
|
|
|
|
} else {
|
|
|
|
// Handle long comparisons by copying the value which is already in BL into
|
|
|
|
// the register we want...
|
|
|
|
BuildMI(BB, X86::MOVrr8, 1, DestReg).addReg(X86::BL);
|
|
|
|
}
|
2002-11-07 17:59:21 +00:00
|
|
|
}
|
2002-11-02 19:45:49 +00:00
|
|
|
|
2002-11-30 11:57:28 +00:00
|
|
|
/// promote32 - Emit instructions to turn a narrow operand into a 32-bit-wide
|
|
|
|
/// operand, in the specified target register.
|
2003-01-13 00:32:26 +00:00
|
|
|
void ISel::promote32(unsigned targetReg, const ValueRecord &VR) {
|
|
|
|
bool isUnsigned = VR.Ty->isUnsigned();
|
2003-08-04 02:12:48 +00:00
|
|
|
|
|
|
|
// Make sure we have the register number for this value...
|
|
|
|
unsigned Reg = VR.Val ? getReg(VR.Val) : VR.Reg;
|
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
switch (getClassB(VR.Ty)) {
|
2002-12-25 05:13:53 +00:00
|
|
|
case cByte:
|
|
|
|
// Extend value into target register (8->32)
|
|
|
|
if (isUnsigned)
|
2003-08-04 02:12:48 +00:00
|
|
|
BuildMI(BB, X86::MOVZXr32r8, 1, targetReg).addReg(Reg);
|
2002-12-25 05:13:53 +00:00
|
|
|
else
|
2003-08-04 02:12:48 +00:00
|
|
|
BuildMI(BB, X86::MOVSXr32r8, 1, targetReg).addReg(Reg);
|
2002-12-25 05:13:53 +00:00
|
|
|
break;
|
|
|
|
case cShort:
|
|
|
|
// Extend value into target register (16->32)
|
|
|
|
if (isUnsigned)
|
2003-08-04 02:12:48 +00:00
|
|
|
BuildMI(BB, X86::MOVZXr32r16, 1, targetReg).addReg(Reg);
|
2002-12-25 05:13:53 +00:00
|
|
|
else
|
2003-08-04 02:12:48 +00:00
|
|
|
BuildMI(BB, X86::MOVSXr32r16, 1, targetReg).addReg(Reg);
|
2002-12-25 05:13:53 +00:00
|
|
|
break;
|
|
|
|
case cInt:
|
|
|
|
// Move value into target register (32->32)
|
2003-08-04 02:12:48 +00:00
|
|
|
BuildMI(BB, X86::MOVrr32, 1, targetReg).addReg(Reg);
|
2002-12-25 05:13:53 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0 && "Unpromotable operand class in promote32");
|
|
|
|
}
|
2002-11-30 11:57:28 +00:00
|
|
|
}
|
2002-10-27 21:16:59 +00:00
|
|
|
|
2002-10-25 22:55:53 +00:00
|
|
|
/// 'ret' instruction - Here we are interested in meeting the x86 ABI. As such,
|
|
|
|
/// we have the following possibilities:
|
|
|
|
///
|
|
|
|
/// ret void: No return value, simply emit a 'ret' instruction
|
|
|
|
/// ret sbyte, ubyte : Extend value into EAX and return
|
|
|
|
/// ret short, ushort: Extend value into EAX and return
|
|
|
|
/// ret int, uint : Move value into EAX and return
|
|
|
|
/// ret pointer : Move value into EAX and return
|
2002-11-17 21:56:38 +00:00
|
|
|
/// ret long, ulong : Move value into EAX/EDX and return
|
|
|
|
/// ret float/double : Top of FP stack
|
2002-10-25 22:55:53 +00:00
|
|
|
///
|
2003-01-13 00:32:26 +00:00
|
|
|
void ISel::visitReturnInst(ReturnInst &I) {
|
2002-12-25 05:13:53 +00:00
|
|
|
if (I.getNumOperands() == 0) {
|
|
|
|
BuildMI(BB, X86::RET, 0); // Just emit a 'ret' instruction
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Value *RetVal = I.getOperand(0);
|
2003-01-13 00:32:26 +00:00
|
|
|
unsigned RetReg = getReg(RetVal);
|
|
|
|
switch (getClassB(RetVal->getType())) {
|
2002-12-25 05:13:53 +00:00
|
|
|
case cByte: // integral return values: extend or move into EAX and return
|
|
|
|
case cShort:
|
|
|
|
case cInt:
|
2003-01-13 00:32:26 +00:00
|
|
|
promote32(X86::EAX, ValueRecord(RetReg, RetVal->getType()));
|
2003-05-06 21:32:22 +00:00
|
|
|
// Declare that EAX is live on exit
|
2003-05-07 19:21:28 +00:00
|
|
|
BuildMI(BB, X86::IMPLICIT_USE, 2).addReg(X86::EAX).addReg(X86::ESP);
|
2002-12-25 05:13:53 +00:00
|
|
|
break;
|
|
|
|
case cFP: // Floats & Doubles: Return in ST(0)
|
2003-01-13 00:32:26 +00:00
|
|
|
BuildMI(BB, X86::FpSETRESULT, 1).addReg(RetReg);
|
2003-05-06 21:32:22 +00:00
|
|
|
// Declare that top-of-stack is live on exit
|
2003-05-07 19:21:28 +00:00
|
|
|
BuildMI(BB, X86::IMPLICIT_USE, 2).addReg(X86::ST0).addReg(X86::ESP);
|
2002-12-25 05:13:53 +00:00
|
|
|
break;
|
|
|
|
case cLong:
|
2003-01-13 00:32:26 +00:00
|
|
|
BuildMI(BB, X86::MOVrr32, 1, X86::EAX).addReg(RetReg);
|
|
|
|
BuildMI(BB, X86::MOVrr32, 1, X86::EDX).addReg(RetReg+1);
|
2003-05-06 21:32:22 +00:00
|
|
|
// Declare that EAX & EDX are live on exit
|
2003-05-07 19:21:28 +00:00
|
|
|
BuildMI(BB, X86::IMPLICIT_USE, 3).addReg(X86::EAX).addReg(X86::EDX).addReg(X86::ESP);
|
2003-01-13 00:32:26 +00:00
|
|
|
break;
|
2002-12-25 05:13:53 +00:00
|
|
|
default:
|
2003-01-13 00:32:26 +00:00
|
|
|
visitInstruction(I);
|
2002-12-25 05:13:53 +00:00
|
|
|
}
|
2002-11-17 20:07:45 +00:00
|
|
|
// Emit a 'ret' instruction
|
2002-12-25 05:13:53 +00:00
|
|
|
BuildMI(BB, X86::RET, 0);
|
2002-10-25 22:55:53 +00:00
|
|
|
}
|
|
|
|
|
2003-01-16 18:07:23 +00:00
|
|
|
// getBlockAfter - Return the basic block which occurs lexically after the
|
|
|
|
// specified one.
|
|
|
|
static inline BasicBlock *getBlockAfter(BasicBlock *BB) {
|
|
|
|
Function::iterator I = BB; ++I; // Get iterator to next block
|
|
|
|
return I != BB->getParent()->end() ? &*I : 0;
|
|
|
|
}
|
|
|
|
|
2002-11-02 19:45:49 +00:00
|
|
|
/// 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
|
2003-01-16 16:43:00 +00:00
|
|
|
/// just make a fall-through (but we don't currently).
|
2002-11-02 19:45:49 +00:00
|
|
|
///
|
2002-12-25 05:13:53 +00:00
|
|
|
void ISel::visitBranchInst(BranchInst &BI) {
|
2003-01-16 18:07:23 +00:00
|
|
|
BasicBlock *NextBB = getBlockAfter(BI.getParent()); // BB after current one
|
|
|
|
|
|
|
|
if (!BI.isConditional()) { // Unconditional branch?
|
|
|
|
if (BI.getSuccessor(0) != NextBB)
|
|
|
|
BuildMI(BB, X86::JMP, 1).addPCDisp(BI.getSuccessor(0));
|
2003-01-16 16:43:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// See if we can fold the setcc into the branch itself...
|
|
|
|
SetCondInst *SCI = canFoldSetCCIntoBranch(BI.getCondition());
|
|
|
|
if (SCI == 0) {
|
|
|
|
// Nope, cannot fold setcc into this branch. Emit a branch on a condition
|
|
|
|
// computed some other way...
|
2002-12-28 20:24:02 +00:00
|
|
|
unsigned condReg = getReg(BI.getCondition());
|
2002-12-25 05:13:53 +00:00
|
|
|
BuildMI(BB, X86::CMPri8, 2).addReg(condReg).addZImm(0);
|
2003-01-16 18:07:23 +00:00
|
|
|
if (BI.getSuccessor(1) == NextBB) {
|
|
|
|
if (BI.getSuccessor(0) != NextBB)
|
|
|
|
BuildMI(BB, X86::JNE, 1).addPCDisp(BI.getSuccessor(0));
|
|
|
|
} else {
|
|
|
|
BuildMI(BB, X86::JE, 1).addPCDisp(BI.getSuccessor(1));
|
|
|
|
|
|
|
|
if (BI.getSuccessor(0) != NextBB)
|
|
|
|
BuildMI(BB, X86::JMP, 1).addPCDisp(BI.getSuccessor(0));
|
|
|
|
}
|
2003-01-16 16:43:00 +00:00
|
|
|
return;
|
2002-12-25 05:13:53 +00:00
|
|
|
}
|
2003-01-16 16:43:00 +00:00
|
|
|
|
|
|
|
unsigned OpNum = getSetCCNumber(SCI->getOpcode());
|
|
|
|
bool isSigned = EmitComparisonGetSignedness(OpNum, SCI->getOperand(0),
|
|
|
|
SCI->getOperand(1));
|
|
|
|
|
|
|
|
// LLVM -> X86 signed X86 unsigned
|
|
|
|
// ----- ---------- ------------
|
|
|
|
// seteq -> je je
|
|
|
|
// setne -> jne jne
|
|
|
|
// setlt -> jl jb
|
2003-01-16 18:07:23 +00:00
|
|
|
// setge -> jge jae
|
2003-01-16 16:43:00 +00:00
|
|
|
// setgt -> jg ja
|
|
|
|
// setle -> jle jbe
|
|
|
|
static const unsigned OpcodeTab[2][6] = {
|
2003-01-16 18:07:23 +00:00
|
|
|
{ X86::JE, X86::JNE, X86::JB, X86::JAE, X86::JA, X86::JBE },
|
|
|
|
{ X86::JE, X86::JNE, X86::JL, X86::JGE, X86::JG, X86::JLE },
|
2003-01-16 16:43:00 +00:00
|
|
|
};
|
|
|
|
|
2003-01-16 18:07:23 +00:00
|
|
|
if (BI.getSuccessor(0) != NextBB) {
|
|
|
|
BuildMI(BB, OpcodeTab[isSigned][OpNum], 1).addPCDisp(BI.getSuccessor(0));
|
|
|
|
if (BI.getSuccessor(1) != NextBB)
|
|
|
|
BuildMI(BB, X86::JMP, 1).addPCDisp(BI.getSuccessor(1));
|
|
|
|
} else {
|
|
|
|
// Change to the inverse condition...
|
|
|
|
if (BI.getSuccessor(1) != NextBB) {
|
|
|
|
OpNum ^= 1;
|
|
|
|
BuildMI(BB, OpcodeTab[isSigned][OpNum], 1).addPCDisp(BI.getSuccessor(1));
|
|
|
|
}
|
|
|
|
}
|
2002-11-02 19:27:56 +00:00
|
|
|
}
|
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
/// doCall - This emits an abstract call instruction, setting up the arguments
|
|
|
|
/// and the return value as appropriate. For the actual function call itself,
|
|
|
|
/// it inserts the specified CallMI instruction into the stream.
|
|
|
|
///
|
|
|
|
void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
|
|
|
|
const std::vector<ValueRecord> &Args) {
|
|
|
|
|
2002-12-28 20:24:02 +00:00
|
|
|
// Count how many bytes are to be pushed on the stack...
|
|
|
|
unsigned NumBytes = 0;
|
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
if (!Args.empty()) {
|
|
|
|
for (unsigned i = 0, e = Args.size(); i != e; ++i)
|
|
|
|
switch (getClassB(Args[i].Ty)) {
|
2002-12-28 20:24:02 +00:00
|
|
|
case cByte: case cShort: case cInt:
|
2003-01-13 00:32:26 +00:00
|
|
|
NumBytes += 4; break;
|
2002-12-28 20:24:02 +00:00
|
|
|
case cLong:
|
2003-01-13 00:32:26 +00:00
|
|
|
NumBytes += 8; break;
|
2002-12-28 20:24:02 +00:00
|
|
|
case cFP:
|
2003-01-13 00:32:26 +00:00
|
|
|
NumBytes += Args[i].Ty == Type::FloatTy ? 4 : 8;
|
2002-12-28 20:24:02 +00:00
|
|
|
break;
|
|
|
|
default: assert(0 && "Unknown class!");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust the stack pointer for the new arguments...
|
|
|
|
BuildMI(BB, X86::ADJCALLSTACKDOWN, 1).addZImm(NumBytes);
|
|
|
|
|
|
|
|
// Arguments go on the stack in reverse order, as specified by the ABI.
|
|
|
|
unsigned ArgOffset = 0;
|
2003-01-13 00:32:26 +00:00
|
|
|
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
|
2003-08-04 02:12:48 +00:00
|
|
|
unsigned ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg;
|
2003-01-13 00:32:26 +00:00
|
|
|
switch (getClassB(Args[i].Ty)) {
|
2002-12-28 20:24:02 +00:00
|
|
|
case cByte:
|
|
|
|
case cShort: {
|
|
|
|
// Promote arg to 32 bits wide into a temporary register...
|
|
|
|
unsigned R = makeAnotherReg(Type::UIntTy);
|
2003-01-13 00:32:26 +00:00
|
|
|
promote32(R, Args[i]);
|
2002-12-28 20:24:02 +00:00
|
|
|
addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
|
|
|
|
X86::ESP, ArgOffset).addReg(R);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case cInt:
|
|
|
|
addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
|
2003-01-13 00:32:26 +00:00
|
|
|
X86::ESP, ArgOffset).addReg(ArgReg);
|
2002-12-28 20:24:02 +00:00
|
|
|
break;
|
2003-01-13 00:32:26 +00:00
|
|
|
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;
|
|
|
|
|
2002-12-28 20:24:02 +00:00
|
|
|
case cFP:
|
2003-01-13 00:32:26 +00:00
|
|
|
if (Args[i].Ty == Type::FloatTy) {
|
2002-12-28 20:24:02 +00:00
|
|
|
addRegOffset(BuildMI(BB, X86::FSTr32, 5),
|
2003-01-13 00:32:26 +00:00
|
|
|
X86::ESP, ArgOffset).addReg(ArgReg);
|
2002-12-28 20:24:02 +00:00
|
|
|
} else {
|
2003-01-13 00:32:26 +00:00
|
|
|
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.
|
2002-12-28 20:24:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
default: assert(0 && "Unknown class!");
|
2002-12-28 20:24:02 +00:00
|
|
|
}
|
|
|
|
ArgOffset += 4;
|
2002-11-29 12:01:58 +00:00
|
|
|
}
|
2002-12-13 14:13:27 +00:00
|
|
|
} else {
|
2003-01-13 00:32:26 +00:00
|
|
|
BuildMI(BB, X86::ADJCALLSTACKDOWN, 1).addZImm(0);
|
2002-12-13 14:13:27 +00:00
|
|
|
}
|
2002-12-04 19:22:53 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
BB->push_back(CallMI);
|
|
|
|
|
2002-12-28 20:24:02 +00:00
|
|
|
BuildMI(BB, X86::ADJCALLSTACKUP, 1).addZImm(NumBytes);
|
2002-12-04 23:45:28 +00:00
|
|
|
|
|
|
|
// If there is a return value, scavenge the result from the location the call
|
|
|
|
// leaves it in...
|
|
|
|
//
|
2003-01-13 00:32:26 +00:00
|
|
|
if (Ret.Ty != Type::VoidTy) {
|
|
|
|
unsigned DestClass = getClassB(Ret.Ty);
|
|
|
|
switch (DestClass) {
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
case cByte:
|
|
|
|
case cShort:
|
|
|
|
case cInt: {
|
|
|
|
// Integral results are in %eax, or the appropriate portion
|
|
|
|
// thereof.
|
|
|
|
static const unsigned regRegMove[] = {
|
|
|
|
X86::MOVrr8, X86::MOVrr16, X86::MOVrr32
|
|
|
|
};
|
|
|
|
static const unsigned AReg[] = { X86::AL, X86::AX, X86::EAX };
|
2003-01-13 00:32:26 +00:00
|
|
|
BuildMI(BB, regRegMove[DestClass], 1, Ret.Reg).addReg(AReg[DestClass]);
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
break;
|
|
|
|
}
|
2002-12-25 05:13:53 +00:00
|
|
|
case cFP: // Floating-point return values live in %ST(0)
|
2003-01-13 00:32:26 +00:00
|
|
|
BuildMI(BB, X86::FpGETRESULT, 1, Ret.Reg);
|
2002-12-04 23:50:28 +00:00
|
|
|
break;
|
2003-01-13 00:32:26 +00:00
|
|
|
case cLong: // Long values are left in EDX:EAX
|
|
|
|
BuildMI(BB, X86::MOVrr32, 1, Ret.Reg).addReg(X86::EAX);
|
|
|
|
BuildMI(BB, X86::MOVrr32, 1, Ret.Reg+1).addReg(X86::EDX);
|
|
|
|
break;
|
|
|
|
default: assert(0 && "Unknown class!");
|
2002-12-04 23:50:28 +00:00
|
|
|
}
|
2002-12-04 23:45:28 +00:00
|
|
|
}
|
2002-11-22 11:07:01 +00:00
|
|
|
}
|
2002-11-02 19:27:56 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
/// visitCallInst - Push args on stack and do a procedure call instruction.
|
|
|
|
void ISel::visitCallInst(CallInst &CI) {
|
|
|
|
MachineInstr *TheCall;
|
|
|
|
if (Function *F = CI.getCalledFunction()) {
|
2003-05-08 19:44:13 +00:00
|
|
|
// Is it an intrinsic function call?
|
|
|
|
if (LLVMIntrinsic::ID ID = (LLVMIntrinsic::ID)F->getIntrinsicID()) {
|
|
|
|
visitIntrinsicCall(ID, CI); // Special intrinsics are not handled here
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
// Emit a CALL instruction with PC-relative displacement.
|
|
|
|
TheCall = BuildMI(X86::CALLpcrel32, 1).addGlobalAddress(F, true);
|
|
|
|
} else { // Emit an indirect call...
|
|
|
|
unsigned Reg = getReg(CI.getCalledValue());
|
|
|
|
TheCall = BuildMI(X86::CALLr32, 1).addReg(Reg);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<ValueRecord> Args;
|
|
|
|
for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
|
2003-08-04 02:12:48 +00:00
|
|
|
Args.push_back(ValueRecord(CI.getOperand(i)));
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
unsigned DestReg = CI.getType() != Type::VoidTy ? getReg(CI) : 0;
|
|
|
|
doCall(ValueRecord(DestReg, CI.getType()), TheCall, Args);
|
|
|
|
}
|
|
|
|
|
2003-05-08 19:44:13 +00:00
|
|
|
void ISel::visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &CI) {
|
|
|
|
unsigned TmpReg1, TmpReg2;
|
|
|
|
switch (ID) {
|
|
|
|
case LLVMIntrinsic::va_start:
|
|
|
|
// Get the address of the first vararg value...
|
|
|
|
TmpReg1 = makeAnotherReg(Type::UIntTy);
|
|
|
|
addFrameReference(BuildMI(BB, X86::LEAr32, 5, TmpReg1), VarArgsFrameIndex);
|
|
|
|
TmpReg2 = getReg(CI.getOperand(1));
|
|
|
|
addDirectMem(BuildMI(BB, X86::MOVrm32, 5), TmpReg2).addReg(TmpReg1);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case LLVMIntrinsic::va_end: return; // Noop on X86
|
|
|
|
case LLVMIntrinsic::va_copy:
|
|
|
|
TmpReg1 = getReg(CI.getOperand(2)); // Get existing va_list
|
|
|
|
TmpReg2 = getReg(CI.getOperand(1)); // Get va_list* to store into
|
|
|
|
addDirectMem(BuildMI(BB, X86::MOVrm32, 5), TmpReg2).addReg(TmpReg1);
|
|
|
|
return;
|
|
|
|
|
2003-06-29 16:42:32 +00:00
|
|
|
case LLVMIntrinsic::longjmp:
|
|
|
|
BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("abort", true);
|
2003-07-18 20:23:43 +00:00
|
|
|
return;
|
|
|
|
|
2003-06-29 16:42:32 +00:00
|
|
|
case LLVMIntrinsic::setjmp:
|
2003-06-30 19:35:54 +00:00
|
|
|
// Setjmp always returns zero...
|
|
|
|
BuildMI(BB, X86::MOVir32, 1, getReg(CI)).addZImm(0);
|
2003-06-29 16:42:32 +00:00
|
|
|
return;
|
2003-05-08 19:44:13 +00:00
|
|
|
default: assert(0 && "Unknown intrinsic for X86!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-05-08 20:49:25 +00:00
|
|
|
/// visitSimpleBinary - Implement simple binary operators for integral types...
|
|
|
|
/// OperatorClass is one of: 0 for Add, 1 for Sub, 2 for And, 3 for Or, 4 for
|
|
|
|
/// Xor.
|
|
|
|
void ISel::visitSimpleBinary(BinaryOperator &B, unsigned OperatorClass) {
|
|
|
|
unsigned DestReg = getReg(B);
|
|
|
|
MachineBasicBlock::iterator MI = BB->end();
|
|
|
|
emitSimpleBinaryOperation(BB, MI, B.getOperand(0), B.getOperand(1),
|
|
|
|
OperatorClass, DestReg);
|
|
|
|
}
|
2003-01-13 00:32:26 +00:00
|
|
|
|
2002-11-02 20:13:22 +00:00
|
|
|
/// visitSimpleBinary - Implement simple binary operators for integral types...
|
|
|
|
/// OperatorClass is one of: 0 for Add, 1 for Sub, 2 for And, 3 for Or,
|
|
|
|
/// 4 for Xor.
|
|
|
|
///
|
2003-05-08 20:49:25 +00:00
|
|
|
/// emitSimpleBinaryOperation - Common code shared between visitSimpleBinary
|
|
|
|
/// and constant expression support.
|
|
|
|
void ISel::emitSimpleBinaryOperation(MachineBasicBlock *BB,
|
|
|
|
MachineBasicBlock::iterator &IP,
|
|
|
|
Value *Op0, Value *Op1,
|
|
|
|
unsigned OperatorClass,unsigned TargetReg){
|
|
|
|
unsigned Class = getClassB(Op0->getType());
|
2003-06-05 18:28:55 +00:00
|
|
|
if (!isa<ConstantInt>(Op1) || Class == cLong) {
|
|
|
|
static const unsigned OpcodeTab[][4] = {
|
|
|
|
// Arithmetic operators
|
|
|
|
{ X86::ADDrr8, X86::ADDrr16, X86::ADDrr32, X86::FpADD }, // ADD
|
|
|
|
{ X86::SUBrr8, X86::SUBrr16, X86::SUBrr32, X86::FpSUB }, // SUB
|
|
|
|
|
|
|
|
// Bitwise operators
|
|
|
|
{ X86::ANDrr8, X86::ANDrr16, X86::ANDrr32, 0 }, // AND
|
|
|
|
{ X86:: ORrr8, X86:: ORrr16, X86:: ORrr32, 0 }, // OR
|
|
|
|
{ X86::XORrr8, X86::XORrr16, X86::XORrr32, 0 }, // XOR
|
|
|
|
};
|
|
|
|
|
|
|
|
bool isLong = false;
|
|
|
|
if (Class == cLong) {
|
|
|
|
isLong = true;
|
|
|
|
Class = cInt; // Bottom 32 bits are handled just like ints
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned Opcode = OpcodeTab[OperatorClass][Class];
|
|
|
|
assert(Opcode && "Floating point arguments to logical inst?");
|
|
|
|
unsigned Op0r = getReg(Op0, BB, IP);
|
|
|
|
unsigned Op1r = getReg(Op1, BB, IP);
|
|
|
|
BMI(BB, IP, Opcode, 2, TargetReg).addReg(Op0r).addReg(Op1r);
|
|
|
|
|
|
|
|
if (isLong) { // Handle the upper 32 bits of long values...
|
|
|
|
static const unsigned TopTab[] = {
|
|
|
|
X86::ADCrr32, X86::SBBrr32, X86::ANDrr32, X86::ORrr32, X86::XORrr32
|
|
|
|
};
|
|
|
|
BMI(BB, IP, TopTab[OperatorClass], 2,
|
|
|
|
TargetReg+1).addReg(Op0r+1).addReg(Op1r+1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Special case: op Reg, <const>
|
|
|
|
ConstantInt *Op1C = cast<ConstantInt>(Op1);
|
2002-11-02 20:04:26 +00:00
|
|
|
|
2003-06-05 18:28:55 +00:00
|
|
|
static const unsigned OpcodeTab[][3] = {
|
|
|
|
// Arithmetic operators
|
|
|
|
{ X86::ADDri8, X86::ADDri16, X86::ADDri32 }, // ADD
|
|
|
|
{ X86::SUBri8, X86::SUBri16, X86::SUBri32 }, // SUB
|
|
|
|
|
|
|
|
// Bitwise operators
|
|
|
|
{ X86::ANDri8, X86::ANDri16, X86::ANDri32 }, // AND
|
|
|
|
{ X86:: ORri8, X86:: ORri16, X86:: ORri32 }, // OR
|
|
|
|
{ X86::XORri8, X86::XORri16, X86::XORri32 }, // XOR
|
|
|
|
};
|
2002-11-02 20:13:22 +00:00
|
|
|
|
2003-06-05 18:28:55 +00:00
|
|
|
assert(Class < 3 && "General code handles 64-bit integer types!");
|
|
|
|
unsigned Opcode = OpcodeTab[OperatorClass][Class];
|
|
|
|
unsigned Op0r = getReg(Op0, BB, IP);
|
2003-07-23 15:22:26 +00:00
|
|
|
uint64_t Op1v = cast<ConstantInt>(Op1C)->getRawValue();
|
2003-01-13 00:32:26 +00:00
|
|
|
|
2003-06-05 18:28:55 +00:00
|
|
|
// Mask off any upper bits of the constant, if there are any...
|
|
|
|
Op1v &= (1ULL << (8 << Class)) - 1;
|
|
|
|
BMI(BB, IP, Opcode, 2, TargetReg).addReg(Op0r).addZImm(Op1v);
|
2003-01-13 00:32:26 +00:00
|
|
|
}
|
2002-11-02 20:04:26 +00:00
|
|
|
}
|
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
/// doMultiply - Emit appropriate instructions to multiply together the
|
|
|
|
/// registers op0Reg and op1Reg, and put the result in DestReg. The type of the
|
|
|
|
/// result should be given as DestTy.
|
|
|
|
///
|
2002-12-16 19:32:50 +00:00
|
|
|
void ISel::doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI,
|
2003-01-13 00:32:26 +00:00
|
|
|
unsigned DestReg, const Type *DestTy,
|
2002-12-16 19:32:50 +00:00
|
|
|
unsigned op0Reg, unsigned op1Reg) {
|
2003-01-13 00:32:26 +00:00
|
|
|
unsigned Class = getClass(DestTy);
|
2002-12-25 05:13:53 +00:00
|
|
|
switch (Class) {
|
|
|
|
case cFP: // Floating point multiply
|
2003-01-13 00:32:26 +00:00
|
|
|
BMI(BB, MBBI, X86::FpMUL, 2, DestReg).addReg(op0Reg).addReg(op1Reg);
|
2002-12-25 05:13:53 +00:00
|
|
|
return;
|
2003-06-21 17:16:58 +00:00
|
|
|
case cInt:
|
|
|
|
case cShort:
|
|
|
|
BMI(BB, MBBI, Class == cInt ? X86::IMULr32 : X86::IMULr16, 2, DestReg)
|
|
|
|
.addReg(op0Reg).addReg(op1Reg);
|
|
|
|
return;
|
|
|
|
case cByte:
|
|
|
|
// Must use the MUL instruction, which forces use of AL...
|
|
|
|
BMI(MBB, MBBI, X86::MOVrr8, 1, X86::AL).addReg(op0Reg);
|
|
|
|
BMI(MBB, MBBI, X86::MULr8, 1).addReg(op1Reg);
|
|
|
|
BMI(MBB, MBBI, X86::MOVrr8, 1, DestReg).addReg(X86::AL);
|
|
|
|
return;
|
2002-12-25 05:13:53 +00:00
|
|
|
default:
|
2003-01-13 00:32:26 +00:00
|
|
|
case cLong: assert(0 && "doMultiply cannot operate on LONG values!");
|
2002-12-25 05:13:53 +00:00
|
|
|
}
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// visitMul - Multiplies are not simple binary operators because they must deal
|
|
|
|
/// with the EAX register explicitly.
|
|
|
|
///
|
|
|
|
void ISel::visitMul(BinaryOperator &I) {
|
2002-12-13 13:07:42 +00:00
|
|
|
unsigned Op0Reg = getReg(I.getOperand(0));
|
|
|
|
unsigned Op1Reg = getReg(I.getOperand(1));
|
2003-01-13 00:32:26 +00:00
|
|
|
unsigned DestReg = getReg(I);
|
|
|
|
|
|
|
|
// Simple scalar multiply?
|
|
|
|
if (I.getType() != Type::LongTy && I.getType() != Type::ULongTy) {
|
|
|
|
MachineBasicBlock::iterator MBBI = BB->end();
|
|
|
|
doMultiply(BB, MBBI, DestReg, I.getType(), Op0Reg, Op1Reg);
|
|
|
|
} else {
|
|
|
|
// Long value. We have to do things the hard way...
|
|
|
|
// Multiply the two low parts... capturing carry into EDX
|
|
|
|
BuildMI(BB, X86::MOVrr32, 1, X86::EAX).addReg(Op0Reg);
|
|
|
|
BuildMI(BB, X86::MULr32, 1).addReg(Op1Reg); // AL*BL
|
|
|
|
|
|
|
|
unsigned OverflowReg = makeAnotherReg(Type::UIntTy);
|
|
|
|
BuildMI(BB, X86::MOVrr32, 1, DestReg).addReg(X86::EAX); // AL*BL
|
|
|
|
BuildMI(BB, X86::MOVrr32, 1, OverflowReg).addReg(X86::EDX); // AL*BL >> 32
|
|
|
|
|
|
|
|
MachineBasicBlock::iterator MBBI = BB->end();
|
2003-06-21 18:15:27 +00:00
|
|
|
unsigned AHBLReg = makeAnotherReg(Type::UIntTy); // AH*BL
|
|
|
|
BMI(BB, MBBI, X86::IMULr32, 2, AHBLReg).addReg(Op0Reg+1).addReg(Op1Reg);
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
unsigned AHBLplusOverflowReg = makeAnotherReg(Type::UIntTy);
|
|
|
|
BuildMI(BB, X86::ADDrr32, 2, // AH*BL+(AL*BL >> 32)
|
|
|
|
AHBLplusOverflowReg).addReg(AHBLReg).addReg(OverflowReg);
|
|
|
|
|
|
|
|
MBBI = BB->end();
|
2003-06-21 18:15:27 +00:00
|
|
|
unsigned ALBHReg = makeAnotherReg(Type::UIntTy); // AL*BH
|
|
|
|
BMI(BB, MBBI, X86::IMULr32, 2, ALBHReg).addReg(Op0Reg).addReg(Op1Reg+1);
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
BuildMI(BB, X86::ADDrr32, 2, // AL*BH + AH*BL + (AL*BL >> 32)
|
|
|
|
DestReg+1).addReg(AHBLplusOverflowReg).addReg(ALBHReg);
|
|
|
|
}
|
2002-11-02 20:54:46 +00:00
|
|
|
}
|
|
|
|
|
2002-11-17 21:56:38 +00:00
|
|
|
|
2002-11-02 20:54:46 +00:00
|
|
|
/// visitDivRem - Handle division and remainder instructions... these
|
|
|
|
/// instruction both require the same instructions to be generated, they just
|
|
|
|
/// select the result from a different register. Note that both of these
|
|
|
|
/// instructions work differently for signed and unsigned operands.
|
|
|
|
///
|
|
|
|
void ISel::visitDivRem(BinaryOperator &I) {
|
2003-08-04 02:12:48 +00:00
|
|
|
unsigned Class = getClass(I.getType());
|
|
|
|
unsigned Op0Reg, Op1Reg, ResultReg = getReg(I);
|
2002-12-25 05:13:53 +00:00
|
|
|
|
|
|
|
switch (Class) {
|
2003-01-13 00:32:26 +00:00
|
|
|
case cFP: // Floating point divide
|
2003-08-04 02:12:48 +00:00
|
|
|
if (I.getOpcode() == Instruction::Div) {
|
|
|
|
Op0Reg = getReg(I.getOperand(0));
|
|
|
|
Op1Reg = getReg(I.getOperand(1));
|
2002-12-25 05:13:53 +00:00
|
|
|
BuildMI(BB, X86::FpDIV, 2, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
|
2003-08-04 02:12:48 +00:00
|
|
|
} else { // Floating point remainder...
|
2003-01-13 00:32:26 +00:00
|
|
|
MachineInstr *TheCall =
|
|
|
|
BuildMI(X86::CALLpcrel32, 1).addExternalSymbol("fmod", true);
|
|
|
|
std::vector<ValueRecord> Args;
|
2003-08-04 02:12:48 +00:00
|
|
|
Args.push_back(ValueRecord(I.getOperand(0)));
|
|
|
|
Args.push_back(ValueRecord(I.getOperand(1)));
|
2003-01-13 00:32:26 +00:00
|
|
|
doCall(ValueRecord(ResultReg, Type::DoubleTy), TheCall, Args);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
case cLong: {
|
|
|
|
static const char *FnName[] =
|
|
|
|
{ "__moddi3", "__divdi3", "__umoddi3", "__udivdi3" };
|
|
|
|
|
|
|
|
unsigned NameIdx = I.getType()->isUnsigned()*2;
|
|
|
|
NameIdx += I.getOpcode() == Instruction::Div;
|
|
|
|
MachineInstr *TheCall =
|
|
|
|
BuildMI(X86::CALLpcrel32, 1).addExternalSymbol(FnName[NameIdx], true);
|
|
|
|
|
|
|
|
std::vector<ValueRecord> Args;
|
2003-08-04 02:12:48 +00:00
|
|
|
Args.push_back(ValueRecord(I.getOperand(0)));
|
|
|
|
Args.push_back(ValueRecord(I.getOperand(1)));
|
2003-01-13 00:32:26 +00:00
|
|
|
doCall(ValueRecord(ResultReg, Type::LongTy), TheCall, Args);
|
2002-12-25 05:13:53 +00:00
|
|
|
return;
|
2003-01-13 00:32:26 +00:00
|
|
|
}
|
|
|
|
case cByte: case cShort: case cInt:
|
|
|
|
break; // Small integerals, handled below...
|
|
|
|
default: assert(0 && "Unknown class!");
|
2002-12-25 05:13:53 +00:00
|
|
|
}
|
2002-11-02 20:54:46 +00:00
|
|
|
|
|
|
|
static const unsigned Regs[] ={ X86::AL , X86::AX , X86::EAX };
|
|
|
|
static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 };
|
2003-06-22 03:31:18 +00:00
|
|
|
static const unsigned SarOpcode[]={ X86::SARir8, X86::SARir16, X86::SARir32 };
|
2002-11-02 20:54:46 +00:00
|
|
|
static const unsigned ClrOpcode[]={ X86::XORrr8, X86::XORrr16, X86::XORrr32 };
|
|
|
|
static const unsigned ExtRegs[] ={ X86::AH , X86::DX , X86::EDX };
|
|
|
|
|
|
|
|
static const unsigned DivOpcode[][4] = {
|
2003-01-13 00:32:26 +00:00
|
|
|
{ X86::DIVr8 , X86::DIVr16 , X86::DIVr32 , 0 }, // Unsigned division
|
|
|
|
{ X86::IDIVr8, X86::IDIVr16, X86::IDIVr32, 0 }, // Signed division
|
2002-11-02 20:54:46 +00:00
|
|
|
};
|
2002-11-02 20:28:58 +00:00
|
|
|
|
2002-11-02 20:54:46 +00:00
|
|
|
bool isSigned = I.getType()->isSigned();
|
|
|
|
unsigned Reg = Regs[Class];
|
|
|
|
unsigned ExtReg = ExtRegs[Class];
|
|
|
|
|
|
|
|
// Put the first operand into one of the A registers...
|
2003-08-04 02:12:48 +00:00
|
|
|
Op0Reg = getReg(I.getOperand(0));
|
2002-11-02 20:54:46 +00:00
|
|
|
BuildMI(BB, MovOpcode[Class], 1, Reg).addReg(Op0Reg);
|
|
|
|
|
|
|
|
if (isSigned) {
|
|
|
|
// Emit a sign extension instruction...
|
2003-06-22 03:31:18 +00:00
|
|
|
unsigned ShiftResult = makeAnotherReg(I.getType());
|
|
|
|
BuildMI(BB, SarOpcode[Class], 2, ShiftResult).addReg(Op0Reg).addZImm(31);
|
|
|
|
BuildMI(BB, MovOpcode[Class], 1, ExtReg).addReg(ShiftResult);
|
2002-11-02 20:54:46 +00:00
|
|
|
} else {
|
|
|
|
// If unsigned, emit a zeroing instruction... (reg = xor reg, reg)
|
|
|
|
BuildMI(BB, ClrOpcode[Class], 2, ExtReg).addReg(ExtReg).addReg(ExtReg);
|
|
|
|
}
|
|
|
|
|
2002-11-17 21:56:38 +00:00
|
|
|
// Emit the appropriate divide or remainder instruction...
|
2003-08-04 02:12:48 +00:00
|
|
|
Op1Reg = getReg(I.getOperand(1));
|
2002-11-21 18:54:29 +00:00
|
|
|
BuildMI(BB, DivOpcode[isSigned][Class], 1).addReg(Op1Reg);
|
2002-11-17 21:56:38 +00:00
|
|
|
|
2002-11-02 20:54:46 +00:00
|
|
|
// Figure out which register we want to pick the result out of...
|
|
|
|
unsigned DestReg = (I.getOpcode() == Instruction::Div) ? Reg : ExtReg;
|
|
|
|
|
|
|
|
// Put the result into the destination register...
|
2002-12-25 05:13:53 +00:00
|
|
|
BuildMI(BB, MovOpcode[Class], 1, ResultReg).addReg(DestReg);
|
2002-11-02 20:28:58 +00:00
|
|
|
}
|
2002-11-02 20:04:26 +00:00
|
|
|
|
2002-11-17 21:56:38 +00:00
|
|
|
|
2002-10-31 23:03:59 +00:00
|
|
|
/// Shift instructions: 'shl', 'sar', 'shr' - Some special cases here
|
|
|
|
/// for constant immediate shift values, and for constant immediate
|
|
|
|
/// shift values equal to 1. Even the general case is sort of special,
|
|
|
|
/// because the shift amount has to be in CL, not just any old register.
|
|
|
|
///
|
2003-01-13 00:32:26 +00:00
|
|
|
void ISel::visitShiftInst(ShiftInst &I) {
|
|
|
|
unsigned SrcReg = getReg(I.getOperand(0));
|
2002-11-02 20:54:46 +00:00
|
|
|
unsigned DestReg = getReg(I);
|
2002-11-02 01:41:55 +00:00
|
|
|
bool isLeftShift = I.getOpcode() == Instruction::Shl;
|
2003-01-13 00:32:26 +00:00
|
|
|
bool isSigned = I.getType()->isSigned();
|
|
|
|
unsigned Class = getClass(I.getType());
|
|
|
|
|
|
|
|
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
|
|
|
|
};
|
2002-11-02 01:15:18 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
static const unsigned NonConstantOperand[][4] = {
|
|
|
|
{ X86::SHRrr8, X86::SHRrr16, X86::SHRrr32 }, // SHR
|
|
|
|
{ X86::SARrr8, X86::SARrr16, X86::SARrr32 }, // SAR
|
|
|
|
{ X86::SHLrr8, X86::SHLrr16, X86::SHLrr32 }, // SHL
|
|
|
|
{ X86::SHLrr8, X86::SHLrr16, X86::SHLrr32 }, // SAL = SHL
|
|
|
|
};
|
2002-11-02 01:15:18 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
// Longs, as usual, are handled specially...
|
|
|
|
if (Class == cLong) {
|
|
|
|
// If we have a constant shift, we can generate much more efficient code
|
|
|
|
// than otherwise...
|
|
|
|
//
|
|
|
|
if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(I.getOperand(1))) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
} 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2003-06-01 01:56:54 +00:00
|
|
|
unsigned TmpReg = makeAnotherReg(Type::IntTy);
|
|
|
|
|
|
|
|
if (!isLeftShift && isSigned) {
|
|
|
|
// 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);
|
|
|
|
} else {
|
|
|
|
// Other shifts use a fixed zero value if the shift is more than 32
|
|
|
|
// bits.
|
|
|
|
BuildMI(BB, X86::MOVir32, 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 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);
|
|
|
|
// TmpReg3 = shl inLo, CL
|
|
|
|
BuildMI(BB, 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);
|
|
|
|
|
|
|
|
// DestHi = (>32) ? TmpReg3 : TmpReg2;
|
|
|
|
BuildMI(BB, X86::CMOVNErr32, 2,
|
|
|
|
DestReg+1).addReg(TmpReg2).addReg(TmpReg3);
|
|
|
|
// DestLo = (>32) ? TmpReg : TmpReg3;
|
|
|
|
BuildMI(BB, X86::CMOVNErr32, 2, DestReg).addReg(TmpReg3).addReg(TmpReg);
|
|
|
|
} else {
|
|
|
|
// TmpReg2 = shrd inLo, inHi
|
|
|
|
BuildMI(BB, X86::SHRDrr32, 2, TmpReg2).addReg(SrcReg).addReg(SrcReg+1);
|
|
|
|
// TmpReg3 = s[ah]r inHi, CL
|
|
|
|
BuildMI(BB, 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);
|
|
|
|
|
|
|
|
// DestLo = (>32) ? TmpReg3 : TmpReg2;
|
|
|
|
BuildMI(BB, X86::CMOVNErr32, 2,
|
|
|
|
DestReg).addReg(TmpReg2).addReg(TmpReg3);
|
|
|
|
|
|
|
|
// DestHi = (>32) ? TmpReg : TmpReg3;
|
|
|
|
BuildMI(BB, X86::CMOVNErr32, 2,
|
|
|
|
DestReg+1).addReg(TmpReg3).addReg(TmpReg);
|
|
|
|
}
|
2002-10-31 23:03:59 +00:00
|
|
|
}
|
2003-01-13 00:32:26 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-11-02 01:41:55 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(I.getOperand(1))) {
|
|
|
|
// The shift amount is constant, guaranteed to be a ubyte. Get its value.
|
|
|
|
assert(CUI->getType() == Type::UByteTy && "Shift amount not a ubyte?");
|
2002-11-02 01:15:18 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
const unsigned *Opc = ConstantOperand[isLeftShift*2+isSigned];
|
|
|
|
BuildMI(BB, 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)));
|
|
|
|
|
|
|
|
const unsigned *Opc = NonConstantOperand[isLeftShift*2+isSigned];
|
|
|
|
BuildMI(BB, Opc[Class], 1, DestReg).addReg(SrcReg);
|
|
|
|
}
|
|
|
|
}
|
2002-11-02 01:15:18 +00:00
|
|
|
|
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
/// doFPLoad - This method is used to load an FP value from memory using the
|
|
|
|
/// current endianness. NOTE: This method returns a partially constructed load
|
|
|
|
/// instruction which needs to have the memory source filled in still.
|
|
|
|
///
|
|
|
|
MachineInstr *ISel::doFPLoad(MachineBasicBlock *MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
|
|
|
const Type *Ty, unsigned DestReg) {
|
|
|
|
assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
|
|
|
|
unsigned LoadOpcode = Ty == Type::FloatTy ? X86::FLDr32 : X86::FLDr64;
|
|
|
|
|
|
|
|
if (TM.getTargetData().isLittleEndian()) // fast path...
|
|
|
|
return BMI(MBB, MBBI, LoadOpcode, 4, DestReg);
|
|
|
|
|
|
|
|
// If we are big-endian, start by creating an LEA instruction to represent the
|
|
|
|
// address of the memory location to load from...
|
|
|
|
//
|
|
|
|
unsigned SrcAddrReg = makeAnotherReg(Type::UIntTy);
|
|
|
|
MachineInstr *Result = BMI(MBB, MBBI, X86::LEAr32, 5, SrcAddrReg);
|
|
|
|
|
|
|
|
// Allocate a temporary stack slot to transform the value into...
|
|
|
|
int FrameIdx = F->getFrameInfo()->CreateStackObject(Ty, TM.getTargetData());
|
|
|
|
|
|
|
|
// Perform the bswaps 32 bits at a time...
|
|
|
|
unsigned TmpReg1 = makeAnotherReg(Type::UIntTy);
|
|
|
|
unsigned TmpReg2 = makeAnotherReg(Type::UIntTy);
|
|
|
|
addDirectMem(BMI(MBB, MBBI, X86::MOVmr32, 4, TmpReg1), SrcAddrReg);
|
|
|
|
BMI(MBB, MBBI, X86::BSWAPr32, 1, TmpReg2).addReg(TmpReg1);
|
|
|
|
unsigned Offset = (Ty == Type::DoubleTy) << 2;
|
|
|
|
addFrameReference(BMI(MBB, MBBI, X86::MOVrm32, 5),
|
|
|
|
FrameIdx, Offset).addReg(TmpReg2);
|
|
|
|
|
|
|
|
if (Ty == Type::DoubleTy) { // Swap the other 32 bits of a double value...
|
|
|
|
TmpReg1 = makeAnotherReg(Type::UIntTy);
|
|
|
|
TmpReg2 = makeAnotherReg(Type::UIntTy);
|
|
|
|
|
|
|
|
addRegOffset(BMI(MBB, MBBI, X86::MOVmr32, 4, TmpReg1), SrcAddrReg, 4);
|
|
|
|
BMI(MBB, MBBI, X86::BSWAPr32, 1, TmpReg2).addReg(TmpReg1);
|
|
|
|
unsigned Offset = (Ty == Type::DoubleTy) << 2;
|
|
|
|
addFrameReference(BMI(MBB, MBBI, X86::MOVrm32,5), FrameIdx).addReg(TmpReg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we can reload the final byteswapped result into the final destination.
|
|
|
|
addFrameReference(BMI(MBB, MBBI, LoadOpcode, 4, DestReg), FrameIdx);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitByteSwap - Byteswap SrcReg into DestReg.
|
|
|
|
///
|
|
|
|
void ISel::EmitByteSwap(unsigned DestReg, unsigned SrcReg, unsigned Class) {
|
|
|
|
// Emit the byte swap instruction...
|
|
|
|
switch (Class) {
|
|
|
|
case cByte:
|
2003-04-22 17:54:23 +00:00
|
|
|
// No byteswap necessary for 8 bit value...
|
2003-01-13 00:32:26 +00:00
|
|
|
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
|
2003-04-22 17:54:23 +00:00
|
|
|
// 16-bit bswap. XCHG is necessarily not in SSA form, so we force things
|
2003-01-13 00:32:26 +00:00
|
|
|
// 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!");
|
|
|
|
}
|
2002-10-31 23:03:59 +00:00
|
|
|
}
|
|
|
|
|
2002-11-17 21:56:38 +00:00
|
|
|
|
2002-11-17 21:11:55 +00:00
|
|
|
/// visitLoadInst - Implement LLVM load instructions in terms of the x86 'mov'
|
2002-12-24 00:03:11 +00:00
|
|
|
/// instruction. The load and store instructions are the only place where we
|
|
|
|
/// need to worry about the memory layout of the target machine.
|
2002-11-17 21:11:55 +00:00
|
|
|
///
|
|
|
|
void ISel::visitLoadInst(LoadInst &I) {
|
2002-12-24 00:03:11 +00:00
|
|
|
bool isLittleEndian = TM.getTargetData().isLittleEndian();
|
|
|
|
bool hasLongPointers = TM.getTargetData().getPointerSize() == 8;
|
2002-12-25 05:13:53 +00:00
|
|
|
unsigned SrcAddrReg = getReg(I.getOperand(0));
|
|
|
|
unsigned DestReg = getReg(I);
|
2002-12-24 00:03:11 +00:00
|
|
|
|
2003-07-17 21:30:06 +00:00
|
|
|
unsigned Class = getClassB(I.getType());
|
2002-12-25 05:13:53 +00:00
|
|
|
switch (Class) {
|
|
|
|
case cFP: {
|
2003-01-13 00:32:26 +00:00
|
|
|
MachineBasicBlock::iterator MBBI = BB->end();
|
|
|
|
addDirectMem(doFPLoad(BB, MBBI, I.getType(), DestReg), SrcAddrReg);
|
2002-12-25 05:13:53 +00:00
|
|
|
return;
|
|
|
|
}
|
2003-01-13 00:32:26 +00:00
|
|
|
case cLong: case cInt: case cShort: case cByte:
|
|
|
|
break; // Integers of various sizes handled below
|
|
|
|
default: assert(0 && "Unknown memory class!");
|
2002-12-25 05:13:53 +00:00
|
|
|
}
|
2002-12-24 00:03:11 +00:00
|
|
|
|
|
|
|
// We need to adjust the input pointer if we are emulating a big-endian
|
|
|
|
// long-pointer target. On these systems, the pointer that we are interested
|
|
|
|
// in is in the upper part of the eight byte memory image of the pointer. It
|
|
|
|
// also happens to be byte-swapped, but this will be handled later.
|
|
|
|
//
|
|
|
|
if (!isLittleEndian && hasLongPointers && isa<PointerType>(I.getType())) {
|
|
|
|
unsigned R = makeAnotherReg(Type::UIntTy);
|
|
|
|
BuildMI(BB, X86::ADDri32, 2, R).addReg(SrcAddrReg).addZImm(4);
|
|
|
|
SrcAddrReg = R;
|
|
|
|
}
|
2002-12-25 05:13:53 +00:00
|
|
|
|
2002-12-24 00:03:11 +00:00
|
|
|
unsigned IReg = DestReg;
|
2003-01-13 00:32:26 +00:00
|
|
|
if (!isLittleEndian) // If big endian we need an intermediate stage
|
|
|
|
DestReg = makeAnotherReg(Class != cLong ? I.getType() : Type::UIntTy);
|
2002-12-25 05:13:53 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
static const unsigned Opcode[] = {
|
|
|
|
X86::MOVmr8, X86::MOVmr16, X86::MOVmr32, 0, X86::MOVmr32
|
|
|
|
};
|
2002-12-24 00:03:11 +00:00
|
|
|
addDirectMem(BuildMI(BB, Opcode[Class], 4, DestReg), SrcAddrReg);
|
2002-11-17 21:11:55 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
// Handle long values now...
|
|
|
|
if (Class == cLong) {
|
|
|
|
if (isLittleEndian) {
|
|
|
|
addRegOffset(BuildMI(BB, X86::MOVmr32, 4, DestReg+1), SrcAddrReg, 4);
|
|
|
|
} else {
|
|
|
|
EmitByteSwap(IReg+1, DestReg, cInt);
|
|
|
|
unsigned TempReg = makeAnotherReg(Type::IntTy);
|
|
|
|
addRegOffset(BuildMI(BB, X86::MOVmr32, 4, TempReg), SrcAddrReg, 4);
|
|
|
|
EmitByteSwap(IReg, TempReg, cInt);
|
2002-12-25 05:13:53 +00:00
|
|
|
}
|
2003-01-13 00:32:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isLittleEndian)
|
|
|
|
EmitByteSwap(IReg, DestReg, Class);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// doFPStore - This method is used to store an FP value to memory using the
|
|
|
|
/// current endianness.
|
|
|
|
///
|
|
|
|
void ISel::doFPStore(const Type *Ty, unsigned DestAddrReg, unsigned SrcReg) {
|
|
|
|
assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
|
|
|
|
unsigned StoreOpcode = Ty == Type::FloatTy ? X86::FSTr32 : X86::FSTr64;
|
|
|
|
|
|
|
|
if (TM.getTargetData().isLittleEndian()) { // fast path...
|
|
|
|
addDirectMem(BuildMI(BB, StoreOpcode,5), DestAddrReg).addReg(SrcReg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate a temporary stack slot to transform the value into...
|
|
|
|
int FrameIdx = F->getFrameInfo()->CreateStackObject(Ty, TM.getTargetData());
|
|
|
|
unsigned SrcAddrReg = makeAnotherReg(Type::UIntTy);
|
|
|
|
addFrameReference(BuildMI(BB, X86::LEAr32, 5, SrcAddrReg), FrameIdx);
|
|
|
|
|
|
|
|
// Store the value into a temporary stack slot...
|
|
|
|
addDirectMem(BuildMI(BB, StoreOpcode, 5), SrcAddrReg).addReg(SrcReg);
|
|
|
|
|
|
|
|
// Perform the bswaps 32 bits at a time...
|
|
|
|
unsigned TmpReg1 = makeAnotherReg(Type::UIntTy);
|
|
|
|
unsigned TmpReg2 = makeAnotherReg(Type::UIntTy);
|
|
|
|
addDirectMem(BuildMI(BB, X86::MOVmr32, 4, TmpReg1), SrcAddrReg);
|
|
|
|
BuildMI(BB, X86::BSWAPr32, 1, TmpReg2).addReg(TmpReg1);
|
|
|
|
unsigned Offset = (Ty == Type::DoubleTy) << 2;
|
|
|
|
addRegOffset(BuildMI(BB, X86::MOVrm32, 5),
|
|
|
|
DestAddrReg, Offset).addReg(TmpReg2);
|
|
|
|
|
|
|
|
if (Ty == Type::DoubleTy) { // Swap the other 32 bits of a double value...
|
|
|
|
TmpReg1 = makeAnotherReg(Type::UIntTy);
|
|
|
|
TmpReg2 = makeAnotherReg(Type::UIntTy);
|
|
|
|
|
|
|
|
addRegOffset(BuildMI(BB, X86::MOVmr32, 4, TmpReg1), SrcAddrReg, 4);
|
|
|
|
BuildMI(BB, X86::BSWAPr32, 1, TmpReg2).addReg(TmpReg1);
|
|
|
|
unsigned Offset = (Ty == Type::DoubleTy) << 2;
|
|
|
|
addDirectMem(BuildMI(BB, X86::MOVrm32, 5), DestAddrReg).addReg(TmpReg2);
|
2002-12-24 00:03:11 +00:00
|
|
|
}
|
2002-11-17 21:11:55 +00:00
|
|
|
}
|
|
|
|
|
2002-11-17 21:56:38 +00:00
|
|
|
|
2002-11-17 21:11:55 +00:00
|
|
|
/// visitStoreInst - Implement LLVM store instructions in terms of the x86 'mov'
|
|
|
|
/// instruction.
|
|
|
|
///
|
|
|
|
void ISel::visitStoreInst(StoreInst &I) {
|
2002-12-24 00:03:11 +00:00
|
|
|
bool isLittleEndian = TM.getTargetData().isLittleEndian();
|
|
|
|
bool hasLongPointers = TM.getTargetData().getPointerSize() == 8;
|
2003-01-13 00:32:26 +00:00
|
|
|
unsigned ValReg = getReg(I.getOperand(0));
|
|
|
|
unsigned AddressReg = getReg(I.getOperand(1));
|
2002-12-24 00:03:11 +00:00
|
|
|
|
2003-07-17 21:30:06 +00:00
|
|
|
unsigned Class = getClassB(I.getOperand(0)->getType());
|
2002-12-25 05:13:53 +00:00
|
|
|
switch (Class) {
|
2003-01-13 00:32:26 +00:00
|
|
|
case cLong:
|
|
|
|
if (isLittleEndian) {
|
|
|
|
addDirectMem(BuildMI(BB, X86::MOVrm32, 1+4), AddressReg).addReg(ValReg);
|
|
|
|
addRegOffset(BuildMI(BB, X86::MOVrm32, 1+4),
|
|
|
|
AddressReg, 4).addReg(ValReg+1);
|
|
|
|
} else {
|
|
|
|
unsigned T1 = makeAnotherReg(Type::IntTy);
|
|
|
|
unsigned T2 = makeAnotherReg(Type::IntTy);
|
|
|
|
EmitByteSwap(T1, ValReg , cInt);
|
|
|
|
EmitByteSwap(T2, ValReg+1, cInt);
|
|
|
|
addDirectMem(BuildMI(BB, X86::MOVrm32, 1+4), AddressReg).addReg(T2);
|
|
|
|
addRegOffset(BuildMI(BB, X86::MOVrm32, 1+4), AddressReg, 4).addReg(T1);
|
|
|
|
}
|
2002-12-25 05:13:53 +00:00
|
|
|
return;
|
2003-01-13 00:32:26 +00:00
|
|
|
case cFP:
|
|
|
|
doFPStore(I.getOperand(0)->getType(), AddressReg, ValReg);
|
|
|
|
return;
|
|
|
|
case cInt: case cShort: case cByte:
|
|
|
|
break; // Integers of various sizes handled below
|
|
|
|
default: assert(0 && "Unknown memory class!");
|
2002-12-25 05:13:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!isLittleEndian && hasLongPointers &&
|
|
|
|
isa<PointerType>(I.getOperand(0)->getType())) {
|
2002-12-24 00:03:11 +00:00
|
|
|
unsigned R = makeAnotherReg(Type::UIntTy);
|
|
|
|
BuildMI(BB, X86::ADDri32, 2, R).addReg(AddressReg).addZImm(4);
|
|
|
|
AddressReg = R;
|
|
|
|
}
|
|
|
|
|
2002-12-25 05:13:53 +00:00
|
|
|
if (!isLittleEndian && Class != cByte) {
|
2003-01-13 00:32:26 +00:00
|
|
|
unsigned R = makeAnotherReg(I.getOperand(0)->getType());
|
|
|
|
EmitByteSwap(R, ValReg, Class);
|
|
|
|
ValReg = R;
|
2002-12-24 00:03:11 +00:00
|
|
|
}
|
|
|
|
|
2002-12-25 05:13:53 +00:00
|
|
|
static const unsigned Opcode[] = { X86::MOVrm8, X86::MOVrm16, X86::MOVrm32 };
|
2002-11-17 21:11:55 +00:00
|
|
|
addDirectMem(BuildMI(BB, Opcode[Class], 1+4), AddressReg).addReg(ValReg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-26 10:43:30 +00:00
|
|
|
/// visitCastInst - Here we have various kinds of copying with or without
|
|
|
|
/// sign extension going on.
|
2003-01-13 00:32:26 +00:00
|
|
|
void ISel::visitCastInst(CastInst &CI) {
|
2003-06-21 16:01:24 +00:00
|
|
|
Value *Op = CI.getOperand(0);
|
|
|
|
// If this is a cast from a 32-bit integer to a Long type, and the only uses
|
|
|
|
// of the case are GEP instructions, then the cast does not need to be
|
|
|
|
// generated explicitly, it will be folded into the GEP.
|
|
|
|
if (CI.getType() == Type::LongTy &&
|
|
|
|
(Op->getType() == Type::IntTy || Op->getType() == Type::UIntTy)) {
|
|
|
|
bool AllUsesAreGEPs = true;
|
|
|
|
for (Value::use_iterator I = CI.use_begin(), E = CI.use_end(); I != E; ++I)
|
|
|
|
if (!isa<GetElementPtrInst>(*I)) {
|
|
|
|
AllUsesAreGEPs = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// No need to codegen this cast if all users are getelementptr instrs...
|
|
|
|
if (AllUsesAreGEPs) return;
|
|
|
|
}
|
|
|
|
|
2003-04-23 17:22:12 +00:00
|
|
|
unsigned DestReg = getReg(CI);
|
|
|
|
MachineBasicBlock::iterator MI = BB->end();
|
2003-06-21 16:01:24 +00:00
|
|
|
emitCastOperation(BB, MI, Op, CI.getType(), DestReg);
|
2003-04-23 17:22:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// emitCastOperation - Common code shared between visitCastInst and
|
|
|
|
/// constant expression cast support.
|
|
|
|
void ISel::emitCastOperation(MachineBasicBlock *BB,
|
|
|
|
MachineBasicBlock::iterator &IP,
|
|
|
|
Value *Src, const Type *DestTy,
|
|
|
|
unsigned DestReg) {
|
2003-04-23 17:57:48 +00:00
|
|
|
unsigned SrcReg = getReg(Src, BB, IP);
|
2003-01-13 00:32:26 +00:00
|
|
|
const Type *SrcTy = Src->getType();
|
|
|
|
unsigned SrcClass = getClassB(SrcTy);
|
|
|
|
unsigned DestClass = getClassB(DestTy);
|
|
|
|
|
|
|
|
// Implement casts to bool by using compare on the operand followed by set if
|
|
|
|
// not zero on the result.
|
|
|
|
if (DestTy == Type::BoolTy) {
|
2003-06-01 03:38:24 +00:00
|
|
|
switch (SrcClass) {
|
|
|
|
case cByte:
|
|
|
|
BMI(BB, IP, X86::TESTrr8, 2).addReg(SrcReg).addReg(SrcReg);
|
|
|
|
break;
|
|
|
|
case cShort:
|
|
|
|
BMI(BB, IP, X86::TESTrr16, 2).addReg(SrcReg).addReg(SrcReg);
|
|
|
|
break;
|
|
|
|
case cInt:
|
|
|
|
BMI(BB, IP, X86::TESTrr32, 2).addReg(SrcReg).addReg(SrcReg);
|
|
|
|
break;
|
|
|
|
case cLong: {
|
|
|
|
unsigned TmpReg = makeAnotherReg(Type::IntTy);
|
|
|
|
BMI(BB, IP, X86::ORrr32, 2, TmpReg).addReg(SrcReg).addReg(SrcReg+1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case cFP:
|
|
|
|
assert(0 && "FIXME: implement cast FP to bool");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the zero flag is not set, then the value is true, set the byte to
|
|
|
|
// true.
|
2003-04-23 17:22:12 +00:00
|
|
|
BMI(BB, IP, X86::SETNEr, 1, DestReg);
|
2003-01-13 00:32:26 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-12-13 11:31:59 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
static const unsigned RegRegMove[] = {
|
|
|
|
X86::MOVrr8, X86::MOVrr16, X86::MOVrr32, X86::FpMOV, X86::MOVrr32
|
2002-12-06 10:49:33 +00:00
|
|
|
};
|
2002-12-25 05:13:53 +00:00
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
// Implement casts between values of the same type class (as determined by
|
|
|
|
// getClass) by using a register-to-register move.
|
|
|
|
if (SrcClass == DestClass) {
|
|
|
|
if (SrcClass <= cInt || (SrcClass == cFP && SrcTy == DestTy)) {
|
2003-04-23 17:22:12 +00:00
|
|
|
BMI(BB, IP, RegRegMove[SrcClass], 1, DestReg).addReg(SrcReg);
|
2003-01-13 00:32:26 +00:00
|
|
|
} else if (SrcClass == cFP) {
|
|
|
|
if (SrcTy == Type::FloatTy) { // double -> float
|
|
|
|
assert(DestTy == Type::DoubleTy && "Unknown cFP member!");
|
2003-04-23 17:22:12 +00:00
|
|
|
BMI(BB, IP, X86::FpMOV, 1, DestReg).addReg(SrcReg);
|
2003-01-13 00:32:26 +00:00
|
|
|
} 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();
|
|
|
|
int FrameIdx = F->getFrameInfo()->CreateStackObject(4, FltAlign);
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, X86::FSTr32, 5), FrameIdx).addReg(SrcReg);
|
|
|
|
addFrameReference(BMI(BB, IP, X86::FLDr32, 5, DestReg), FrameIdx);
|
2003-01-13 00:32:26 +00:00
|
|
|
}
|
|
|
|
} else if (SrcClass == cLong) {
|
2003-04-23 17:22:12 +00:00
|
|
|
BMI(BB, IP, X86::MOVrr32, 1, DestReg).addReg(SrcReg);
|
|
|
|
BMI(BB, IP, X86::MOVrr32, 1, DestReg+1).addReg(SrcReg+1);
|
2003-01-13 00:32:26 +00:00
|
|
|
} else {
|
2003-05-12 20:16:58 +00:00
|
|
|
assert(0 && "Cannot handle this type of cast instruction!");
|
2003-04-23 17:22:12 +00:00
|
|
|
abort();
|
2003-01-13 00:32:26 +00:00
|
|
|
}
|
2002-12-25 05:13:53 +00:00
|
|
|
return;
|
|
|
|
}
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
// Handle cast of SMALLER int to LARGER int using a move with sign extension
|
|
|
|
// or zero extension, depending on whether the source type was signed.
|
|
|
|
if (SrcClass <= cInt && (DestClass <= cInt || DestClass == cLong) &&
|
|
|
|
SrcClass < DestClass) {
|
|
|
|
bool isLong = DestClass == cLong;
|
|
|
|
if (isLong) DestClass = cInt;
|
|
|
|
|
|
|
|
static const unsigned Opc[][4] = {
|
|
|
|
{ X86::MOVSXr16r8, X86::MOVSXr32r8, X86::MOVSXr32r16, X86::MOVrr32 }, // s
|
|
|
|
{ X86::MOVZXr16r8, X86::MOVZXr32r8, X86::MOVZXr32r16, X86::MOVrr32 } // u
|
|
|
|
};
|
|
|
|
|
|
|
|
bool isUnsigned = SrcTy->isUnsigned();
|
2003-04-23 17:22:12 +00:00
|
|
|
BMI(BB, IP, Opc[isUnsigned][SrcClass + DestClass - 1], 1,
|
|
|
|
DestReg).addReg(SrcReg);
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
if (isLong) { // Handle upper 32 bits as appropriate...
|
|
|
|
if (isUnsigned) // Zero out top bits...
|
2003-04-23 17:22:12 +00:00
|
|
|
BMI(BB, IP, X86::MOVir32, 1, DestReg+1).addZImm(0);
|
2003-01-13 00:32:26 +00:00
|
|
|
else // Sign extend bottom half...
|
2003-04-23 17:22:12 +00:00
|
|
|
BMI(BB, IP, X86::SARir32, 2, DestReg+1).addReg(DestReg).addZImm(31);
|
2002-12-06 10:49:33 +00:00
|
|
|
}
|
2003-01-13 00:32:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Special case long -> int ...
|
|
|
|
if (SrcClass == cLong && DestClass == cInt) {
|
2003-04-23 17:22:12 +00:00
|
|
|
BMI(BB, IP, X86::MOVrr32, 1, DestReg).addReg(SrcReg);
|
2003-01-13 00:32:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle cast of LARGER int to SMALLER int using a move to EAX followed by a
|
|
|
|
// move out of AX or AL.
|
|
|
|
if ((SrcClass <= cInt || SrcClass == cLong) && DestClass <= cInt
|
|
|
|
&& SrcClass > DestClass) {
|
|
|
|
static const unsigned AReg[] = { X86::AL, X86::AX, X86::EAX, 0, X86::EAX };
|
2003-04-23 17:22:12 +00:00
|
|
|
BMI(BB, IP, RegRegMove[SrcClass], 1, AReg[SrcClass]).addReg(SrcReg);
|
|
|
|
BMI(BB, IP, RegRegMove[DestClass], 1, DestReg).addReg(AReg[DestClass]);
|
2003-01-13 00:32:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle casts from integer to floating point now...
|
|
|
|
if (DestClass == cFP) {
|
2003-05-12 20:36:13 +00:00
|
|
|
// Promote the integer to a type supported by FLD. We do this because there
|
|
|
|
// are no unsigned FLD instructions, so we must promote an unsigned value to
|
|
|
|
// a larger signed value, then use FLD on the larger value.
|
|
|
|
//
|
|
|
|
const Type *PromoteType = 0;
|
|
|
|
unsigned PromoteOpcode;
|
|
|
|
switch (SrcTy->getPrimitiveID()) {
|
|
|
|
case Type::BoolTyID:
|
|
|
|
case Type::SByteTyID:
|
|
|
|
// We don't have the facilities for directly loading byte sized data from
|
|
|
|
// memory (even signed). Promote it to 16 bits.
|
|
|
|
PromoteType = Type::ShortTy;
|
|
|
|
PromoteOpcode = X86::MOVSXr16r8;
|
|
|
|
break;
|
|
|
|
case Type::UByteTyID:
|
|
|
|
PromoteType = Type::ShortTy;
|
|
|
|
PromoteOpcode = X86::MOVZXr16r8;
|
|
|
|
break;
|
|
|
|
case Type::UShortTyID:
|
|
|
|
PromoteType = Type::IntTy;
|
|
|
|
PromoteOpcode = X86::MOVZXr32r16;
|
|
|
|
break;
|
|
|
|
case Type::UIntTyID: {
|
|
|
|
// 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);
|
|
|
|
SrcTy = Type::LongTy;
|
|
|
|
SrcClass = cLong;
|
|
|
|
SrcReg = TmpReg;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Type::ULongTyID:
|
|
|
|
assert("FIXME: not implemented: cast ulong X to fp type!");
|
|
|
|
default: // No promotion needed...
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PromoteType) {
|
|
|
|
unsigned TmpReg = makeAnotherReg(PromoteType);
|
2003-04-23 17:22:12 +00:00
|
|
|
BMI(BB, IP, SrcTy->isSigned() ? X86::MOVSXr16r8 : X86::MOVZXr16r8,
|
|
|
|
1, TmpReg).addReg(SrcReg);
|
2003-05-12 20:36:13 +00:00
|
|
|
SrcTy = PromoteType;
|
|
|
|
SrcClass = getClass(PromoteType);
|
2003-01-13 00:32:26 +00:00
|
|
|
SrcReg = TmpReg;
|
2002-12-06 10:49:33 +00:00
|
|
|
}
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
// Spill the integer to memory and reload it from there...
|
|
|
|
int FrameIdx =
|
|
|
|
F->getFrameInfo()->CreateStackObject(SrcTy, TM.getTargetData());
|
|
|
|
|
|
|
|
if (SrcClass == cLong) {
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, X86::MOVrm32, 5), FrameIdx).addReg(SrcReg);
|
|
|
|
addFrameReference(BMI(BB, IP, X86::MOVrm32, 5),
|
2003-01-13 00:32:26 +00:00
|
|
|
FrameIdx, 4).addReg(SrcReg+1);
|
|
|
|
} else {
|
|
|
|
static const unsigned Op1[] = { X86::MOVrm8, X86::MOVrm16, X86::MOVrm32 };
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, Op1[SrcClass], 5), FrameIdx).addReg(SrcReg);
|
2003-01-13 00:32:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const unsigned Op2[] =
|
2003-05-12 20:36:13 +00:00
|
|
|
{ 0/*byte*/, X86::FILDr16, X86::FILDr32, 0/*FP*/, X86::FILDr64 };
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, Op2[SrcClass], 5, DestReg), FrameIdx);
|
2003-01-13 00:32:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle casts from floating point to integer now...
|
|
|
|
if (SrcClass == cFP) {
|
|
|
|
// Change the floating point control register to use "round towards zero"
|
|
|
|
// mode when truncating to an integer value.
|
|
|
|
//
|
|
|
|
int CWFrameIdx = F->getFrameInfo()->CreateStackObject(2, 2);
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, X86::FNSTCWm16, 4), CWFrameIdx);
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
// Load the old value of the high byte of the control word...
|
|
|
|
unsigned HighPartOfCW = makeAnotherReg(Type::UByteTy);
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, X86::MOVmr8, 4, HighPartOfCW), CWFrameIdx, 1);
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
// Set the high part to be round to zero...
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, X86::MOVim8, 5), CWFrameIdx, 1).addZImm(12);
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
// Reload the modified control word now...
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, X86::FLDCWm16, 4), CWFrameIdx);
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
// Restore the memory image of control word to original value
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, X86::MOVrm8, 5),
|
2003-01-13 00:32:26 +00:00
|
|
|
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
|
|
|
|
// larger classes because we only have signed FP stores.
|
|
|
|
unsigned StoreClass = DestClass;
|
|
|
|
const Type *StoreTy = DestTy;
|
|
|
|
if (StoreClass == cByte || DestTy->isUnsigned())
|
|
|
|
switch (StoreClass) {
|
|
|
|
case cByte: StoreTy = Type::ShortTy; StoreClass = cShort; break;
|
|
|
|
case cShort: StoreTy = Type::IntTy; StoreClass = cInt; break;
|
|
|
|
case cInt: StoreTy = Type::LongTy; StoreClass = cLong; break;
|
2003-07-18 20:23:43 +00:00
|
|
|
// 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;
|
2003-01-13 00:32:26 +00:00
|
|
|
default: assert(0 && "Unknown store class!");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Spill the integer to memory and reload it from there...
|
|
|
|
int FrameIdx =
|
|
|
|
F->getFrameInfo()->CreateStackObject(StoreTy, TM.getTargetData());
|
|
|
|
|
|
|
|
static const unsigned Op1[] =
|
|
|
|
{ 0, X86::FISTr16, X86::FISTr32, 0, X86::FISTPr64 };
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, Op1[StoreClass], 5), FrameIdx).addReg(SrcReg);
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
if (DestClass == cLong) {
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, X86::MOVmr32, 4, DestReg), FrameIdx);
|
|
|
|
addFrameReference(BMI(BB, IP, X86::MOVmr32, 4, DestReg+1), FrameIdx, 4);
|
2003-01-13 00:32:26 +00:00
|
|
|
} else {
|
|
|
|
static const unsigned Op2[] = { X86::MOVmr8, X86::MOVmr16, X86::MOVmr32 };
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, Op2[DestClass], 4, DestReg), FrameIdx);
|
2003-01-13 00:32:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reload the original control word now...
|
2003-04-23 17:22:12 +00:00
|
|
|
addFrameReference(BMI(BB, IP, X86::FLDCWm16, 4), CWFrameIdx);
|
2003-01-13 00:32:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-12-06 10:49:33 +00:00
|
|
|
// Anything we haven't handled already, we can't (yet) handle at all.
|
2003-05-12 20:16:58 +00:00
|
|
|
assert(0 && "Unhandled cast instruction!");
|
2003-04-23 17:22:12 +00:00
|
|
|
abort();
|
2002-11-22 11:07:01 +00:00
|
|
|
}
|
2002-10-31 23:03:59 +00:00
|
|
|
|
2003-05-08 19:44:13 +00:00
|
|
|
/// visitVarArgInst - Implement the va_arg instruction...
|
|
|
|
///
|
|
|
|
void ISel::visitVarArgInst(VarArgInst &I) {
|
|
|
|
unsigned SrcReg = getReg(I.getOperand(0));
|
|
|
|
unsigned DestReg = getReg(I);
|
|
|
|
|
|
|
|
// Load the va_list into a register...
|
|
|
|
unsigned VAList = makeAnotherReg(Type::UIntTy);
|
|
|
|
addDirectMem(BuildMI(BB, X86::MOVmr32, 4, VAList), SrcReg);
|
|
|
|
|
|
|
|
unsigned Size;
|
|
|
|
switch (I.getType()->getPrimitiveID()) {
|
|
|
|
default:
|
|
|
|
std::cerr << I;
|
|
|
|
assert(0 && "Error: bad type for va_arg instruction!");
|
|
|
|
return;
|
|
|
|
case Type::PointerTyID:
|
|
|
|
case Type::UIntTyID:
|
|
|
|
case Type::IntTyID:
|
|
|
|
Size = 4;
|
|
|
|
addDirectMem(BuildMI(BB, X86::MOVmr32, 4, DestReg), VAList);
|
|
|
|
break;
|
|
|
|
case Type::ULongTyID:
|
|
|
|
case Type::LongTyID:
|
|
|
|
Size = 8;
|
|
|
|
addDirectMem(BuildMI(BB, X86::MOVmr32, 4, DestReg), VAList);
|
|
|
|
addRegOffset(BuildMI(BB, X86::MOVmr32, 4, DestReg+1), VAList, 4);
|
|
|
|
break;
|
|
|
|
case Type::DoubleTyID:
|
|
|
|
Size = 8;
|
|
|
|
addDirectMem(BuildMI(BB, X86::FLDr64, 4, DestReg), VAList);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Increment the VAList pointer...
|
|
|
|
unsigned NextVAList = makeAnotherReg(Type::UIntTy);
|
|
|
|
BuildMI(BB, X86::ADDri32, 2, NextVAList).addReg(VAList).addZImm(Size);
|
|
|
|
|
|
|
|
// Update the VAList in memory...
|
|
|
|
addDirectMem(BuildMI(BB, X86::MOVrm32, 5), SrcReg).addReg(NextVAList);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-12-16 19:32:50 +00:00
|
|
|
// ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N. It
|
|
|
|
// returns zero when the input is not exactly a power of two.
|
|
|
|
static unsigned ExactLog2(unsigned Val) {
|
|
|
|
if (Val == 0) return 0;
|
|
|
|
unsigned Count = 0;
|
|
|
|
while (Val != 1) {
|
|
|
|
if (Val & 1) return 0;
|
|
|
|
Val >>= 1;
|
|
|
|
++Count;
|
|
|
|
}
|
|
|
|
return Count+1;
|
|
|
|
}
|
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
void ISel::visitGetElementPtrInst(GetElementPtrInst &I) {
|
|
|
|
unsigned outputReg = getReg(I);
|
2002-12-13 10:50:40 +00:00
|
|
|
MachineBasicBlock::iterator MI = BB->end();
|
|
|
|
emitGEPOperation(BB, MI, I.getOperand(0),
|
2002-12-16 04:23:29 +00:00
|
|
|
I.op_begin()+1, I.op_end(), outputReg);
|
2002-12-13 06:56:29 +00:00
|
|
|
}
|
|
|
|
|
2002-12-13 11:22:48 +00:00
|
|
|
void ISel::emitGEPOperation(MachineBasicBlock *MBB,
|
2002-12-13 10:50:40 +00:00
|
|
|
MachineBasicBlock::iterator &IP,
|
2002-12-13 10:09:43 +00:00
|
|
|
Value *Src, User::op_iterator IdxBegin,
|
2002-12-13 06:56:29 +00:00
|
|
|
User::op_iterator IdxEnd, unsigned TargetReg) {
|
|
|
|
const TargetData &TD = TM.getTargetData();
|
|
|
|
const Type *Ty = Src->getType();
|
2003-01-13 00:32:26 +00:00
|
|
|
unsigned BaseReg = getReg(Src, MBB, IP);
|
2002-12-13 06:56:29 +00:00
|
|
|
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
// GEPs have zero or more indices; we must perform a struct access
|
|
|
|
// or array access for each one.
|
2002-12-13 06:56:29 +00:00
|
|
|
for (GetElementPtrInst::op_iterator oi = IdxBegin,
|
|
|
|
oe = IdxEnd; oi != oe; ++oi) {
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
Value *idx = *oi;
|
2003-01-13 00:32:26 +00:00
|
|
|
unsigned NextReg = BaseReg;
|
2002-12-28 20:24:02 +00:00
|
|
|
if (const StructType *StTy = dyn_cast<StructType>(Ty)) {
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
// It's a struct access. idx is the index into the structure,
|
|
|
|
// which names the field. This index must have ubyte type.
|
2002-12-28 20:24:02 +00:00
|
|
|
const ConstantUInt *CUI = cast<ConstantUInt>(idx);
|
|
|
|
assert(CUI->getType() == Type::UByteTy
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
&& "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
|
|
|
|
// right byte offset from the StructLayout class's list of
|
|
|
|
// structure member offsets.
|
2002-12-24 00:03:11 +00:00
|
|
|
unsigned idxValue = CUI->getValue();
|
2003-01-13 00:32:26 +00:00
|
|
|
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);
|
|
|
|
}
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
// The next type is the member of the structure selected by the
|
|
|
|
// index.
|
2002-12-28 20:24:02 +00:00
|
|
|
Ty = StTy->getElementTypes()[idxValue];
|
|
|
|
} else if (const SequentialType *SqTy = cast<SequentialType>(Ty)) {
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
// It's an array or pointer access: [ArraySize x ElementType].
|
2002-12-16 19:32:50 +00:00
|
|
|
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
// idx is the index into the array. Unlike with structure
|
|
|
|
// indices, we may not know its actual value at code-generation
|
|
|
|
// time.
|
2002-12-16 19:32:50 +00:00
|
|
|
assert(idx->getType() == Type::LongTy && "Bad GEP array index!");
|
|
|
|
|
2003-06-21 16:01:24 +00:00
|
|
|
// Most GEP instructions use a [cast (int/uint) to LongTy] as their
|
|
|
|
// operand on X86. Handle this case directly now...
|
|
|
|
if (CastInst *CI = dyn_cast<CastInst>(idx))
|
|
|
|
if (CI->getOperand(0)->getType() == Type::IntTy ||
|
|
|
|
CI->getOperand(0)->getType() == Type::UIntTy)
|
|
|
|
idx = CI->getOperand(0);
|
|
|
|
|
2003-01-13 00:32:26 +00:00
|
|
|
// We want to add BaseReg to(idxReg * sizeof ElementType). First, we
|
2002-12-16 19:32:50 +00:00
|
|
|
// must find the size of the pointed-to type (Not coincidentally, the next
|
|
|
|
// type is the type of the elements in the array).
|
|
|
|
Ty = SqTy->getElementType();
|
|
|
|
unsigned elementSize = TD.getTypeSize(Ty);
|
|
|
|
|
|
|
|
// If idxReg is a constant, we don't need to perform the multiply!
|
|
|
|
if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(idx)) {
|
2003-01-13 00:32:26 +00:00
|
|
|
if (!CSI->isNullValue()) {
|
2002-12-16 19:32:50 +00:00
|
|
|
unsigned Offset = elementSize*CSI->getValue();
|
2003-01-13 00:32:26 +00:00
|
|
|
NextReg = makeAnotherReg(Type::UIntTy);
|
|
|
|
BMI(MBB, IP, X86::ADDri32, 2,NextReg).addReg(BaseReg).addZImm(Offset);
|
2002-12-16 19:32:50 +00:00
|
|
|
}
|
|
|
|
} else if (elementSize == 1) {
|
|
|
|
// If the element size is 1, we don't have to multiply, just add
|
|
|
|
unsigned idxReg = getReg(idx, MBB, IP);
|
2003-01-13 00:32:26 +00:00
|
|
|
NextReg = makeAnotherReg(Type::UIntTy);
|
|
|
|
BMI(MBB, IP, X86::ADDrr32, 2, NextReg).addReg(BaseReg).addReg(idxReg);
|
2002-12-16 19:32:50 +00:00
|
|
|
} else {
|
|
|
|
unsigned idxReg = getReg(idx, MBB, IP);
|
|
|
|
unsigned OffsetReg = makeAnotherReg(Type::UIntTy);
|
|
|
|
if (unsigned Shift = ExactLog2(elementSize)) {
|
|
|
|
// If the element size is exactly a power of 2, use a shift to get it.
|
|
|
|
BMI(MBB, IP, X86::SHLir32, 2,
|
|
|
|
OffsetReg).addReg(idxReg).addZImm(Shift-1);
|
|
|
|
} else {
|
|
|
|
// Most general case, emit a multiply...
|
|
|
|
unsigned elementSizeReg = makeAnotherReg(Type::LongTy);
|
|
|
|
BMI(MBB, IP, X86::MOVir32, 1, elementSizeReg).addZImm(elementSize);
|
|
|
|
|
|
|
|
// Emit a MUL to multiply the register holding the index by
|
|
|
|
// elementSize, putting the result in OffsetReg.
|
2003-01-13 00:32:26 +00:00
|
|
|
doMultiply(MBB, IP, OffsetReg, Type::IntTy, idxReg, elementSizeReg);
|
2002-12-16 19:32:50 +00:00
|
|
|
}
|
|
|
|
// Emit an ADD to add OffsetReg to the basePtr.
|
2003-01-13 00:32:26 +00:00
|
|
|
NextReg = makeAnotherReg(Type::UIntTy);
|
|
|
|
BMI(MBB, IP, X86::ADDrr32, 2,NextReg).addReg(BaseReg).addReg(OffsetReg);
|
2002-12-16 19:32:50 +00:00
|
|
|
}
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
}
|
|
|
|
// Now that we are here, further indices refer to subtypes of this
|
2003-01-13 00:32:26 +00:00
|
|
|
// one, so we don't need to worry about BaseReg itself, anymore.
|
|
|
|
BaseReg = NextReg;
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
}
|
|
|
|
// After we have processed all the indices, the result is left in
|
2003-01-13 00:32:26 +00:00
|
|
|
// BaseReg. Move it to the register where we were expected to
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
// put the answer. A 32-bit move should do it, because we are in
|
|
|
|
// ILP32 land.
|
2003-01-13 00:32:26 +00:00
|
|
|
BMI(MBB, IP, X86::MOVrr32, 1, TargetReg).addReg(BaseReg);
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-12-28 20:24:02 +00:00
|
|
|
/// visitAllocaInst - If this is a fixed size alloca, allocate space from the
|
|
|
|
/// frame manager, otherwise do it the hard way.
|
|
|
|
///
|
|
|
|
void ISel::visitAllocaInst(AllocaInst &I) {
|
|
|
|
// Find the data size of the alloca inst's getAllocatedType.
|
|
|
|
const Type *Ty = I.getAllocatedType();
|
|
|
|
unsigned TySize = TM.getTargetData().getTypeSize(Ty);
|
2002-12-13 06:46:31 +00:00
|
|
|
|
2002-12-28 20:24:02 +00:00
|
|
|
// If this is a fixed size alloca in the entry block for the function,
|
|
|
|
// statically stack allocate the space.
|
|
|
|
//
|
|
|
|
if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(I.getArraySize())) {
|
|
|
|
if (I.getParent() == I.getParent()->getParent()->begin()) {
|
|
|
|
TySize *= CUI->getValue(); // Get total allocated size...
|
|
|
|
unsigned Alignment = TM.getTargetData().getTypeAlignment(Ty);
|
|
|
|
|
|
|
|
// Create a new stack object using the frame manager...
|
|
|
|
int FrameIdx = F->getFrameInfo()->CreateStackObject(TySize, Alignment);
|
|
|
|
addFrameReference(BuildMI(BB, X86::LEAr32, 5, getReg(I)), FrameIdx);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a register to hold the temporary result of multiplying the type size
|
|
|
|
// constant by the variable amount.
|
|
|
|
unsigned TotalSizeReg = makeAnotherReg(Type::UIntTy);
|
|
|
|
unsigned SrcReg1 = getReg(I.getArraySize());
|
|
|
|
unsigned SizeReg = makeAnotherReg(Type::UIntTy);
|
|
|
|
BuildMI(BB, X86::MOVir32, 1, SizeReg).addZImm(TySize);
|
|
|
|
|
|
|
|
// TotalSizeReg = mul <numelements>, <TypeSize>
|
|
|
|
MachineBasicBlock::iterator MBBI = BB->end();
|
|
|
|
doMultiply(BB, MBBI, TotalSizeReg, Type::UIntTy, SrcReg1, SizeReg);
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
|
2002-12-28 20:24:02 +00:00
|
|
|
// AddedSize = add <TotalSizeReg>, 15
|
|
|
|
unsigned AddedSizeReg = makeAnotherReg(Type::UIntTy);
|
|
|
|
BuildMI(BB, X86::ADDri32, 2, AddedSizeReg).addReg(TotalSizeReg).addZImm(15);
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
|
2002-12-28 20:24:02 +00:00
|
|
|
// AlignedSize = and <AddedSize>, ~15
|
|
|
|
unsigned AlignedSize = makeAnotherReg(Type::UIntTy);
|
|
|
|
BuildMI(BB, X86::ANDri32, 2, AlignedSize).addReg(AddedSizeReg).addZImm(~15);
|
|
|
|
|
2002-12-13 06:46:31 +00:00
|
|
|
// Subtract size from stack pointer, thereby allocating some space.
|
2003-01-13 00:32:26 +00:00
|
|
|
BuildMI(BB, X86::SUBrr32, 2, X86::ESP).addReg(X86::ESP).addReg(AlignedSize);
|
2002-12-28 20:24:02 +00:00
|
|
|
|
2002-12-13 06:46:31 +00:00
|
|
|
// Put a pointer to the space into the result register, by copying
|
|
|
|
// the stack pointer.
|
2002-12-28 20:24:02 +00:00
|
|
|
BuildMI(BB, X86::MOVrr32, 1, getReg(I)).addReg(X86::ESP);
|
|
|
|
|
2003-05-03 02:18:17 +00:00
|
|
|
// Inform the Frame Information that we have just allocated a variable-sized
|
2002-12-28 20:24:02 +00:00
|
|
|
// object.
|
|
|
|
F->getFrameInfo()->CreateVariableSizedObject();
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
}
|
2003-01-13 00:32:26 +00:00
|
|
|
|
|
|
|
/// visitMallocInst - Malloc instructions are code generated into direct calls
|
|
|
|
/// to the library malloc.
|
|
|
|
///
|
|
|
|
void ISel::visitMallocInst(MallocInst &I) {
|
|
|
|
unsigned AllocSize = TM.getTargetData().getTypeSize(I.getAllocatedType());
|
|
|
|
unsigned Arg;
|
|
|
|
|
|
|
|
if (ConstantUInt *C = dyn_cast<ConstantUInt>(I.getOperand(0))) {
|
|
|
|
Arg = getReg(ConstantUInt::get(Type::UIntTy, C->getValue() * AllocSize));
|
|
|
|
} else {
|
|
|
|
Arg = makeAnotherReg(Type::UIntTy);
|
|
|
|
unsigned Op0Reg = getReg(ConstantUInt::get(Type::UIntTy, AllocSize));
|
|
|
|
unsigned Op1Reg = getReg(I.getOperand(0));
|
|
|
|
MachineBasicBlock::iterator MBBI = BB->end();
|
|
|
|
doMultiply(BB, MBBI, Arg, Type::UIntTy, Op0Reg, Op1Reg);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<ValueRecord> Args;
|
|
|
|
Args.push_back(ValueRecord(Arg, Type::UIntTy));
|
|
|
|
MachineInstr *TheCall = BuildMI(X86::CALLpcrel32,
|
|
|
|
1).addExternalSymbol("malloc", true);
|
|
|
|
doCall(ValueRecord(getReg(I), I.getType()), TheCall, Args);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// visitFreeInst - Free instructions are code gen'd to call the free libc
|
|
|
|
/// function.
|
|
|
|
///
|
|
|
|
void ISel::visitFreeInst(FreeInst &I) {
|
|
|
|
std::vector<ValueRecord> Args;
|
2003-08-04 02:12:48 +00:00
|
|
|
Args.push_back(ValueRecord(I.getOperand(0)));
|
2003-01-13 00:32:26 +00:00
|
|
|
MachineInstr *TheCall = BuildMI(X86::CALLpcrel32,
|
|
|
|
1).addExternalSymbol("free", true);
|
|
|
|
doCall(ValueRecord(0, Type::VoidTy), TheCall, Args);
|
|
|
|
}
|
|
|
|
|
This checkin is brought to you by the brian gaeke allnighter fund.
(lib/Target/X86) InstSelectSimple.cpp:
Include llvm/DerivedTypes.h and iostream.
Refactor visitMul out into a wrapper around doMultiply(), so that we
can do multiplications on temporary values when we are doing
getelementptrs.
Refactor part of getReg out into makeAnotherReg, so that we can create
registers willy-nilly to hold temporary values, when we are doing
getelementptrs.
Add stub implementations of visitMallocInst and visitAllocaInst.
Add initial implementation of visitGetElementPtrInst.
In copyConstantToRegister:
We throw a *lot* of our asserts here. So, when we want to throw an
assert, print out to stderr whatever expr or whatever constant made
us barf.
Support copying ConstantPointerNull to register, using a move immediate
of zero.
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
Teach visitCallInst to extract byte- and short-class return values
from subregs of EAX. Add a FIXME note about how we would do it for
float-class return values.
Add a FIXME note about how we would cast float to int and back.
X86InstrInfo.def:
Rename FLDr4 and FLDr8 to FLDr32 and FLDr64, so that they match the meanings
of the numbers in the other instruction names. All uses modified.
(tools/jello) GlobalVars.cpp:
Include iostream.
If we have to emit a floating-point constant to memory, gamble and use
the same method as for ints.
If we have to emit a ConstantPointerNull to memory, try using a "void *"
and "NULL".
Otherwise, if we are going to throw an assert, print out whatever constant
made us barf, first.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4973 91177308-0d34-0410-b5e6-96231b3b80d8
2002-12-12 15:33:40 +00:00
|
|
|
|
2003-07-26 23:49:58 +00:00
|
|
|
/// createX86SimpleInstructionSelector - This pass converts an LLVM function
|
2002-10-29 22:37:54 +00:00
|
|
|
/// into a machine code representation is a very simple peep-hole fashion. The
|
2002-10-25 22:55:53 +00:00
|
|
|
/// generated code sucks but the implementation is nice and simple.
|
|
|
|
///
|
2003-07-26 23:49:58 +00:00
|
|
|
Pass *createX86SimpleInstructionSelector(TargetMachine &TM) {
|
2002-10-29 22:37:54 +00:00
|
|
|
return new ISel(TM);
|
2002-10-25 22:55:53 +00:00
|
|
|
}
|