From bc1d27aa6e80022d507ce4811566b4af4257ee45 Mon Sep 17 00:00:00 2001 From: Brian Gaeke Date: Wed, 3 Mar 2004 23:03:14 +0000 Subject: [PATCH] Support add - note, still missing important copyConstantToRegister stuff git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12106 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/InstSelectSimple.cpp | 151 ++++++++++++++++++++++- lib/Target/Sparc/SparcInstrInfo.td | 14 ++- lib/Target/Sparc/SparcV8ISelSimple.cpp | 151 ++++++++++++++++++++++- lib/Target/SparcV8/InstSelectSimple.cpp | 151 ++++++++++++++++++++++- lib/Target/SparcV8/SparcV8ISelSimple.cpp | 151 ++++++++++++++++++++++- lib/Target/SparcV8/SparcV8InstrInfo.td | 14 ++- 6 files changed, 618 insertions(+), 14 deletions(-) diff --git a/lib/Target/Sparc/InstSelectSimple.cpp b/lib/Target/Sparc/InstSelectSimple.cpp index c195611618b..63d3dcc4904 100644 --- a/lib/Target/Sparc/InstSelectSimple.cpp +++ b/lib/Target/Sparc/InstSelectSimple.cpp @@ -12,11 +12,14 @@ //===----------------------------------------------------------------------===// #include "SparcV8.h" +#include "SparcV8InstrInfo.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicLowering.h" #include "llvm/Pass.h" +#include "llvm/Constants.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/SSARegMap.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/InstVisitor.h" @@ -54,6 +57,7 @@ namespace { BB = MBBMap[&LLVM_BB]; } + void visitBinaryOperator(BinaryOperator &I); void visitReturnInst(ReturnInst &RI); void visitInstruction(Instruction &I) { @@ -65,10 +69,72 @@ namespace { /// function, lowering any calls to unknown intrinsic functions into the /// equivalent LLVM code. void LowerUnknownIntrinsicFunctionCalls(Function &F); - - void visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI); + /// copyConstantToRegister - Output the instructions required to put the + /// specified constant into the specified register. + /// + void copyConstantToRegister(MachineBasicBlock *MBB, + MachineBasicBlock::iterator IP, + Constant *C, unsigned R); + + /// 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. + /// + unsigned makeAnotherReg(const Type *Ty) { + assert(dynamic_cast(TM.getRegisterInfo()) && + "Current target doesn't have SparcV8 reg info??"); + const SparcV8RegisterInfo *MRI = + static_cast(TM.getRegisterInfo()); + if (Ty == Type::LongTy || Ty == Type::ULongTy) { + const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy); + // Create the lower part + F->getSSARegMap()->createVirtualRegister(RC); + // Create the upper part. + return F->getSSARegMap()->createVirtualRegister(RC)-1; + } + + // Add the mapping of regnumber => reg class to MachineFunction + const TargetRegisterClass *RC = MRI->getRegClassForType(Ty); + return F->getSSARegMap()->createVirtualRegister(RC); + } + + unsigned getReg(Value &V) { return getReg (&V); } // allow refs. + unsigned getReg(Value *V) { + // Just append to the end of the current bb. + MachineBasicBlock::iterator It = BB->end(); + return getReg(V, BB, It); + } + unsigned getReg(Value *V, MachineBasicBlock *MBB, + MachineBasicBlock::iterator IPt) { + unsigned &Reg = RegMap[V]; + if (Reg == 0) { + Reg = makeAnotherReg(V->getType()); + RegMap[V] = Reg; + } + // If this operand is a constant, emit the code to copy the constant into + // the register here... + // + if (Constant *C = dyn_cast(V)) { + copyConstantToRegister(MBB, IPt, C, Reg); + RegMap.erase(V); // Assign a new name to this constant if ref'd again + } else if (GlobalValue *GV = dyn_cast(V)) { + // Move the address of the global into the register + // X86 does: + // BuildMI(*MBB, IPt, V8::ORrr, 2, Reg).addReg(G0).addGlobalAddress(GV); + // We need to use SETHI and OR. + assert (0 && "Can't move address of global yet"); + RegMap.erase(V); // Assign a new name to this address if ref'd again + } + + return Reg; + } + }; } @@ -76,6 +142,40 @@ FunctionPass *llvm::createSparcV8SimpleInstructionSelector(TargetMachine &TM) { return new V8ISel(TM); } +enum TypeClass { + cByte, cShort, cInt, cFloat, cDouble +}; + +static TypeClass getClass (const Type *T) { + switch (T->getPrimitiveID ()) { + case Type::UByteTyID: case Type::SByteTyID: return cByte; + case Type::UShortTyID: case Type::ShortTyID: return cShort; + case Type::UIntTyID: case Type::IntTyID: return cInt; + case Type::FloatTyID: return cFloat; + case Type::DoubleTyID: return cDouble; + default: + assert (0 && "Type of unknown class passed to getClass?"); + return cByte; + } +} + +/// copyConstantToRegister - Output the instructions required to put the +/// specified constant into the specified register. +/// +void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB, + MachineBasicBlock::iterator IP, + Constant *C, unsigned R) { + if (C->getType()->isIntegral()) { + unsigned Class = getClass(C->getType()); + + ConstantInt *CI = cast(C); + // cByte: or %g0, , + // cShort or cInt: sethi, then or + // BuildMI(*MBB, IP, , <#regs>, R).addImm(CI->getRawValue()); + } + + assert (0 && "Can't copy constants into registers yet"); +} bool V8ISel::runOnFunction(Function &Fn) { // First pass over the function, lower any unknown intrinsic functions @@ -113,13 +213,58 @@ bool V8ISel::runOnFunction(Function &Fn) { void V8ISel::visitReturnInst(ReturnInst &I) { if (I.getNumOperands() == 0) { - // Just emit a 'ret' instruction + // Just emit a 'jmpl' instruction to return. BuildMI(BB, V8::JMPLi, 2, V8::G0).addZImm(8).addReg(V8::I7); return; } visitInstruction(I); } +void V8ISel::visitBinaryOperator (BinaryOperator &I) { + unsigned DestReg = getReg (I); + unsigned Op0Reg = getReg (I.getOperand (0)); + unsigned Op1Reg = getReg (I.getOperand (1)); + + unsigned ResultReg = makeAnotherReg (I.getType ()); + switch (I.getOpcode ()) { + case Instruction::Add: + BuildMI (BB, V8::ADDrr, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg); + break; + default: + visitInstruction (I); + return; + } + + switch (getClass (I.getType ())) { + case cByte: + if (I.getType ()->isSigned ()) { // add byte + BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff); + } else { // add ubyte + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (24); + BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (24); + } + break; + case cShort: + if (I.getType ()->isSigned ()) { // add short + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (16); + BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (16); + } else { // add ushort + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (24); + BuildMI (BB, V8::SRLri, 2, DestReg).addReg (TmpReg).addZImm (24); + } + break; + case cInt: + BuildMI (BB, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (ResultReg); + break; + default: + visitInstruction (I); + return; + } +} + /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the /// function, lowering any calls to unknown intrinsic functions into the diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index 1d7d973e411..96e2dd19756 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -62,7 +62,19 @@ def CALL : InstV8 { let Name = "call"; } -// Section B.25: Jump and Link - p126 +// Section B.11 - Logical Instructions, p. 106 +def ANDri : F3_2<2, 0b000001, "and">; +def ORrr : F3_1<2, 0b000010, "or">; + +// Section B.12 - Shift Instructions, p. 107 +def SLLri : F3_1<2, 0b100101, "sll">; +def SRLri : F3_1<2, 0b100110, "srl">; +def SRAri : F3_1<2, 0b100111, "sra">; + +// Section B.13 - Add Instructions, p. 108 +def ADDrr : F3_1<2, 0b000000, "add">; + +// Section B.25 - Jump and Link, p. 126 def JMPLr : F3_1<2, 0b111000, "jmpl">; // jmpl [rs1+rs2], rd def JMPLi : F3_2<2, 0b111000, "jmpl">; // jmpl [rs1+imm], rd diff --git a/lib/Target/Sparc/SparcV8ISelSimple.cpp b/lib/Target/Sparc/SparcV8ISelSimple.cpp index c195611618b..63d3dcc4904 100644 --- a/lib/Target/Sparc/SparcV8ISelSimple.cpp +++ b/lib/Target/Sparc/SparcV8ISelSimple.cpp @@ -12,11 +12,14 @@ //===----------------------------------------------------------------------===// #include "SparcV8.h" +#include "SparcV8InstrInfo.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicLowering.h" #include "llvm/Pass.h" +#include "llvm/Constants.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/SSARegMap.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/InstVisitor.h" @@ -54,6 +57,7 @@ namespace { BB = MBBMap[&LLVM_BB]; } + void visitBinaryOperator(BinaryOperator &I); void visitReturnInst(ReturnInst &RI); void visitInstruction(Instruction &I) { @@ -65,10 +69,72 @@ namespace { /// function, lowering any calls to unknown intrinsic functions into the /// equivalent LLVM code. void LowerUnknownIntrinsicFunctionCalls(Function &F); - - void visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI); + /// copyConstantToRegister - Output the instructions required to put the + /// specified constant into the specified register. + /// + void copyConstantToRegister(MachineBasicBlock *MBB, + MachineBasicBlock::iterator IP, + Constant *C, unsigned R); + + /// 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. + /// + unsigned makeAnotherReg(const Type *Ty) { + assert(dynamic_cast(TM.getRegisterInfo()) && + "Current target doesn't have SparcV8 reg info??"); + const SparcV8RegisterInfo *MRI = + static_cast(TM.getRegisterInfo()); + if (Ty == Type::LongTy || Ty == Type::ULongTy) { + const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy); + // Create the lower part + F->getSSARegMap()->createVirtualRegister(RC); + // Create the upper part. + return F->getSSARegMap()->createVirtualRegister(RC)-1; + } + + // Add the mapping of regnumber => reg class to MachineFunction + const TargetRegisterClass *RC = MRI->getRegClassForType(Ty); + return F->getSSARegMap()->createVirtualRegister(RC); + } + + unsigned getReg(Value &V) { return getReg (&V); } // allow refs. + unsigned getReg(Value *V) { + // Just append to the end of the current bb. + MachineBasicBlock::iterator It = BB->end(); + return getReg(V, BB, It); + } + unsigned getReg(Value *V, MachineBasicBlock *MBB, + MachineBasicBlock::iterator IPt) { + unsigned &Reg = RegMap[V]; + if (Reg == 0) { + Reg = makeAnotherReg(V->getType()); + RegMap[V] = Reg; + } + // If this operand is a constant, emit the code to copy the constant into + // the register here... + // + if (Constant *C = dyn_cast(V)) { + copyConstantToRegister(MBB, IPt, C, Reg); + RegMap.erase(V); // Assign a new name to this constant if ref'd again + } else if (GlobalValue *GV = dyn_cast(V)) { + // Move the address of the global into the register + // X86 does: + // BuildMI(*MBB, IPt, V8::ORrr, 2, Reg).addReg(G0).addGlobalAddress(GV); + // We need to use SETHI and OR. + assert (0 && "Can't move address of global yet"); + RegMap.erase(V); // Assign a new name to this address if ref'd again + } + + return Reg; + } + }; } @@ -76,6 +142,40 @@ FunctionPass *llvm::createSparcV8SimpleInstructionSelector(TargetMachine &TM) { return new V8ISel(TM); } +enum TypeClass { + cByte, cShort, cInt, cFloat, cDouble +}; + +static TypeClass getClass (const Type *T) { + switch (T->getPrimitiveID ()) { + case Type::UByteTyID: case Type::SByteTyID: return cByte; + case Type::UShortTyID: case Type::ShortTyID: return cShort; + case Type::UIntTyID: case Type::IntTyID: return cInt; + case Type::FloatTyID: return cFloat; + case Type::DoubleTyID: return cDouble; + default: + assert (0 && "Type of unknown class passed to getClass?"); + return cByte; + } +} + +/// copyConstantToRegister - Output the instructions required to put the +/// specified constant into the specified register. +/// +void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB, + MachineBasicBlock::iterator IP, + Constant *C, unsigned R) { + if (C->getType()->isIntegral()) { + unsigned Class = getClass(C->getType()); + + ConstantInt *CI = cast(C); + // cByte: or %g0, , + // cShort or cInt: sethi, then or + // BuildMI(*MBB, IP, , <#regs>, R).addImm(CI->getRawValue()); + } + + assert (0 && "Can't copy constants into registers yet"); +} bool V8ISel::runOnFunction(Function &Fn) { // First pass over the function, lower any unknown intrinsic functions @@ -113,13 +213,58 @@ bool V8ISel::runOnFunction(Function &Fn) { void V8ISel::visitReturnInst(ReturnInst &I) { if (I.getNumOperands() == 0) { - // Just emit a 'ret' instruction + // Just emit a 'jmpl' instruction to return. BuildMI(BB, V8::JMPLi, 2, V8::G0).addZImm(8).addReg(V8::I7); return; } visitInstruction(I); } +void V8ISel::visitBinaryOperator (BinaryOperator &I) { + unsigned DestReg = getReg (I); + unsigned Op0Reg = getReg (I.getOperand (0)); + unsigned Op1Reg = getReg (I.getOperand (1)); + + unsigned ResultReg = makeAnotherReg (I.getType ()); + switch (I.getOpcode ()) { + case Instruction::Add: + BuildMI (BB, V8::ADDrr, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg); + break; + default: + visitInstruction (I); + return; + } + + switch (getClass (I.getType ())) { + case cByte: + if (I.getType ()->isSigned ()) { // add byte + BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff); + } else { // add ubyte + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (24); + BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (24); + } + break; + case cShort: + if (I.getType ()->isSigned ()) { // add short + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (16); + BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (16); + } else { // add ushort + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (24); + BuildMI (BB, V8::SRLri, 2, DestReg).addReg (TmpReg).addZImm (24); + } + break; + case cInt: + BuildMI (BB, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (ResultReg); + break; + default: + visitInstruction (I); + return; + } +} + /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the /// function, lowering any calls to unknown intrinsic functions into the diff --git a/lib/Target/SparcV8/InstSelectSimple.cpp b/lib/Target/SparcV8/InstSelectSimple.cpp index c195611618b..63d3dcc4904 100644 --- a/lib/Target/SparcV8/InstSelectSimple.cpp +++ b/lib/Target/SparcV8/InstSelectSimple.cpp @@ -12,11 +12,14 @@ //===----------------------------------------------------------------------===// #include "SparcV8.h" +#include "SparcV8InstrInfo.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicLowering.h" #include "llvm/Pass.h" +#include "llvm/Constants.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/SSARegMap.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/InstVisitor.h" @@ -54,6 +57,7 @@ namespace { BB = MBBMap[&LLVM_BB]; } + void visitBinaryOperator(BinaryOperator &I); void visitReturnInst(ReturnInst &RI); void visitInstruction(Instruction &I) { @@ -65,10 +69,72 @@ namespace { /// function, lowering any calls to unknown intrinsic functions into the /// equivalent LLVM code. void LowerUnknownIntrinsicFunctionCalls(Function &F); - - void visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI); + /// copyConstantToRegister - Output the instructions required to put the + /// specified constant into the specified register. + /// + void copyConstantToRegister(MachineBasicBlock *MBB, + MachineBasicBlock::iterator IP, + Constant *C, unsigned R); + + /// 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. + /// + unsigned makeAnotherReg(const Type *Ty) { + assert(dynamic_cast(TM.getRegisterInfo()) && + "Current target doesn't have SparcV8 reg info??"); + const SparcV8RegisterInfo *MRI = + static_cast(TM.getRegisterInfo()); + if (Ty == Type::LongTy || Ty == Type::ULongTy) { + const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy); + // Create the lower part + F->getSSARegMap()->createVirtualRegister(RC); + // Create the upper part. + return F->getSSARegMap()->createVirtualRegister(RC)-1; + } + + // Add the mapping of regnumber => reg class to MachineFunction + const TargetRegisterClass *RC = MRI->getRegClassForType(Ty); + return F->getSSARegMap()->createVirtualRegister(RC); + } + + unsigned getReg(Value &V) { return getReg (&V); } // allow refs. + unsigned getReg(Value *V) { + // Just append to the end of the current bb. + MachineBasicBlock::iterator It = BB->end(); + return getReg(V, BB, It); + } + unsigned getReg(Value *V, MachineBasicBlock *MBB, + MachineBasicBlock::iterator IPt) { + unsigned &Reg = RegMap[V]; + if (Reg == 0) { + Reg = makeAnotherReg(V->getType()); + RegMap[V] = Reg; + } + // If this operand is a constant, emit the code to copy the constant into + // the register here... + // + if (Constant *C = dyn_cast(V)) { + copyConstantToRegister(MBB, IPt, C, Reg); + RegMap.erase(V); // Assign a new name to this constant if ref'd again + } else if (GlobalValue *GV = dyn_cast(V)) { + // Move the address of the global into the register + // X86 does: + // BuildMI(*MBB, IPt, V8::ORrr, 2, Reg).addReg(G0).addGlobalAddress(GV); + // We need to use SETHI and OR. + assert (0 && "Can't move address of global yet"); + RegMap.erase(V); // Assign a new name to this address if ref'd again + } + + return Reg; + } + }; } @@ -76,6 +142,40 @@ FunctionPass *llvm::createSparcV8SimpleInstructionSelector(TargetMachine &TM) { return new V8ISel(TM); } +enum TypeClass { + cByte, cShort, cInt, cFloat, cDouble +}; + +static TypeClass getClass (const Type *T) { + switch (T->getPrimitiveID ()) { + case Type::UByteTyID: case Type::SByteTyID: return cByte; + case Type::UShortTyID: case Type::ShortTyID: return cShort; + case Type::UIntTyID: case Type::IntTyID: return cInt; + case Type::FloatTyID: return cFloat; + case Type::DoubleTyID: return cDouble; + default: + assert (0 && "Type of unknown class passed to getClass?"); + return cByte; + } +} + +/// copyConstantToRegister - Output the instructions required to put the +/// specified constant into the specified register. +/// +void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB, + MachineBasicBlock::iterator IP, + Constant *C, unsigned R) { + if (C->getType()->isIntegral()) { + unsigned Class = getClass(C->getType()); + + ConstantInt *CI = cast(C); + // cByte: or %g0, , + // cShort or cInt: sethi, then or + // BuildMI(*MBB, IP, , <#regs>, R).addImm(CI->getRawValue()); + } + + assert (0 && "Can't copy constants into registers yet"); +} bool V8ISel::runOnFunction(Function &Fn) { // First pass over the function, lower any unknown intrinsic functions @@ -113,13 +213,58 @@ bool V8ISel::runOnFunction(Function &Fn) { void V8ISel::visitReturnInst(ReturnInst &I) { if (I.getNumOperands() == 0) { - // Just emit a 'ret' instruction + // Just emit a 'jmpl' instruction to return. BuildMI(BB, V8::JMPLi, 2, V8::G0).addZImm(8).addReg(V8::I7); return; } visitInstruction(I); } +void V8ISel::visitBinaryOperator (BinaryOperator &I) { + unsigned DestReg = getReg (I); + unsigned Op0Reg = getReg (I.getOperand (0)); + unsigned Op1Reg = getReg (I.getOperand (1)); + + unsigned ResultReg = makeAnotherReg (I.getType ()); + switch (I.getOpcode ()) { + case Instruction::Add: + BuildMI (BB, V8::ADDrr, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg); + break; + default: + visitInstruction (I); + return; + } + + switch (getClass (I.getType ())) { + case cByte: + if (I.getType ()->isSigned ()) { // add byte + BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff); + } else { // add ubyte + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (24); + BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (24); + } + break; + case cShort: + if (I.getType ()->isSigned ()) { // add short + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (16); + BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (16); + } else { // add ushort + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (24); + BuildMI (BB, V8::SRLri, 2, DestReg).addReg (TmpReg).addZImm (24); + } + break; + case cInt: + BuildMI (BB, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (ResultReg); + break; + default: + visitInstruction (I); + return; + } +} + /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the /// function, lowering any calls to unknown intrinsic functions into the diff --git a/lib/Target/SparcV8/SparcV8ISelSimple.cpp b/lib/Target/SparcV8/SparcV8ISelSimple.cpp index c195611618b..63d3dcc4904 100644 --- a/lib/Target/SparcV8/SparcV8ISelSimple.cpp +++ b/lib/Target/SparcV8/SparcV8ISelSimple.cpp @@ -12,11 +12,14 @@ //===----------------------------------------------------------------------===// #include "SparcV8.h" +#include "SparcV8InstrInfo.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicLowering.h" #include "llvm/Pass.h" +#include "llvm/Constants.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/SSARegMap.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/InstVisitor.h" @@ -54,6 +57,7 @@ namespace { BB = MBBMap[&LLVM_BB]; } + void visitBinaryOperator(BinaryOperator &I); void visitReturnInst(ReturnInst &RI); void visitInstruction(Instruction &I) { @@ -65,10 +69,72 @@ namespace { /// function, lowering any calls to unknown intrinsic functions into the /// equivalent LLVM code. void LowerUnknownIntrinsicFunctionCalls(Function &F); - - void visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI); + /// copyConstantToRegister - Output the instructions required to put the + /// specified constant into the specified register. + /// + void copyConstantToRegister(MachineBasicBlock *MBB, + MachineBasicBlock::iterator IP, + Constant *C, unsigned R); + + /// 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. + /// + unsigned makeAnotherReg(const Type *Ty) { + assert(dynamic_cast(TM.getRegisterInfo()) && + "Current target doesn't have SparcV8 reg info??"); + const SparcV8RegisterInfo *MRI = + static_cast(TM.getRegisterInfo()); + if (Ty == Type::LongTy || Ty == Type::ULongTy) { + const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy); + // Create the lower part + F->getSSARegMap()->createVirtualRegister(RC); + // Create the upper part. + return F->getSSARegMap()->createVirtualRegister(RC)-1; + } + + // Add the mapping of regnumber => reg class to MachineFunction + const TargetRegisterClass *RC = MRI->getRegClassForType(Ty); + return F->getSSARegMap()->createVirtualRegister(RC); + } + + unsigned getReg(Value &V) { return getReg (&V); } // allow refs. + unsigned getReg(Value *V) { + // Just append to the end of the current bb. + MachineBasicBlock::iterator It = BB->end(); + return getReg(V, BB, It); + } + unsigned getReg(Value *V, MachineBasicBlock *MBB, + MachineBasicBlock::iterator IPt) { + unsigned &Reg = RegMap[V]; + if (Reg == 0) { + Reg = makeAnotherReg(V->getType()); + RegMap[V] = Reg; + } + // If this operand is a constant, emit the code to copy the constant into + // the register here... + // + if (Constant *C = dyn_cast(V)) { + copyConstantToRegister(MBB, IPt, C, Reg); + RegMap.erase(V); // Assign a new name to this constant if ref'd again + } else if (GlobalValue *GV = dyn_cast(V)) { + // Move the address of the global into the register + // X86 does: + // BuildMI(*MBB, IPt, V8::ORrr, 2, Reg).addReg(G0).addGlobalAddress(GV); + // We need to use SETHI and OR. + assert (0 && "Can't move address of global yet"); + RegMap.erase(V); // Assign a new name to this address if ref'd again + } + + return Reg; + } + }; } @@ -76,6 +142,40 @@ FunctionPass *llvm::createSparcV8SimpleInstructionSelector(TargetMachine &TM) { return new V8ISel(TM); } +enum TypeClass { + cByte, cShort, cInt, cFloat, cDouble +}; + +static TypeClass getClass (const Type *T) { + switch (T->getPrimitiveID ()) { + case Type::UByteTyID: case Type::SByteTyID: return cByte; + case Type::UShortTyID: case Type::ShortTyID: return cShort; + case Type::UIntTyID: case Type::IntTyID: return cInt; + case Type::FloatTyID: return cFloat; + case Type::DoubleTyID: return cDouble; + default: + assert (0 && "Type of unknown class passed to getClass?"); + return cByte; + } +} + +/// copyConstantToRegister - Output the instructions required to put the +/// specified constant into the specified register. +/// +void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB, + MachineBasicBlock::iterator IP, + Constant *C, unsigned R) { + if (C->getType()->isIntegral()) { + unsigned Class = getClass(C->getType()); + + ConstantInt *CI = cast(C); + // cByte: or %g0, , + // cShort or cInt: sethi, then or + // BuildMI(*MBB, IP, , <#regs>, R).addImm(CI->getRawValue()); + } + + assert (0 && "Can't copy constants into registers yet"); +} bool V8ISel::runOnFunction(Function &Fn) { // First pass over the function, lower any unknown intrinsic functions @@ -113,13 +213,58 @@ bool V8ISel::runOnFunction(Function &Fn) { void V8ISel::visitReturnInst(ReturnInst &I) { if (I.getNumOperands() == 0) { - // Just emit a 'ret' instruction + // Just emit a 'jmpl' instruction to return. BuildMI(BB, V8::JMPLi, 2, V8::G0).addZImm(8).addReg(V8::I7); return; } visitInstruction(I); } +void V8ISel::visitBinaryOperator (BinaryOperator &I) { + unsigned DestReg = getReg (I); + unsigned Op0Reg = getReg (I.getOperand (0)); + unsigned Op1Reg = getReg (I.getOperand (1)); + + unsigned ResultReg = makeAnotherReg (I.getType ()); + switch (I.getOpcode ()) { + case Instruction::Add: + BuildMI (BB, V8::ADDrr, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg); + break; + default: + visitInstruction (I); + return; + } + + switch (getClass (I.getType ())) { + case cByte: + if (I.getType ()->isSigned ()) { // add byte + BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff); + } else { // add ubyte + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (24); + BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (24); + } + break; + case cShort: + if (I.getType ()->isSigned ()) { // add short + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (16); + BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (16); + } else { // add ushort + unsigned TmpReg = makeAnotherReg (I.getType ()); + BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (24); + BuildMI (BB, V8::SRLri, 2, DestReg).addReg (TmpReg).addZImm (24); + } + break; + case cInt: + BuildMI (BB, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (ResultReg); + break; + default: + visitInstruction (I); + return; + } +} + /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the /// function, lowering any calls to unknown intrinsic functions into the diff --git a/lib/Target/SparcV8/SparcV8InstrInfo.td b/lib/Target/SparcV8/SparcV8InstrInfo.td index 1d7d973e411..96e2dd19756 100644 --- a/lib/Target/SparcV8/SparcV8InstrInfo.td +++ b/lib/Target/SparcV8/SparcV8InstrInfo.td @@ -62,7 +62,19 @@ def CALL : InstV8 { let Name = "call"; } -// Section B.25: Jump and Link - p126 +// Section B.11 - Logical Instructions, p. 106 +def ANDri : F3_2<2, 0b000001, "and">; +def ORrr : F3_1<2, 0b000010, "or">; + +// Section B.12 - Shift Instructions, p. 107 +def SLLri : F3_1<2, 0b100101, "sll">; +def SRLri : F3_1<2, 0b100110, "srl">; +def SRAri : F3_1<2, 0b100111, "sra">; + +// Section B.13 - Add Instructions, p. 108 +def ADDrr : F3_1<2, 0b000000, "add">; + +// Section B.25 - Jump and Link, p. 126 def JMPLr : F3_1<2, 0b111000, "jmpl">; // jmpl [rs1+rs2], rd def JMPLi : F3_2<2, 0b111000, "jmpl">; // jmpl [rs1+imm], rd