From e2954c84e91570064af78a1c6e29646b75131056 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 2 Nov 2002 20:04:26 +0000 Subject: [PATCH] shuffle code around a bit, implement and, or, xor git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4502 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/InstSelectSimple.cpp | 100 +++++++++++++++++++--------- lib/Target/X86/X86ISelSimple.cpp | 100 +++++++++++++++++++--------- lib/Target/X86/X86InstrInfo.def | 13 +++- 3 files changed, 148 insertions(+), 65 deletions(-) diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp index 106d99b19dc..425ff9ed81c 100644 --- a/lib/Target/X86/InstSelectSimple.cpp +++ b/lib/Target/X86/InstSelectSimple.cpp @@ -55,11 +55,23 @@ namespace { // Visitation methods for various instructions. These methods simply emit // fixed X86 code for each instruction. // - void visitPHINode(PHINode &I); void visitReturnInst(ReturnInst &RI); void visitBranchInst(BranchInst &BI); + + // Arithmetic operators void visitAdd(BinaryOperator &B); + + // Bitwise operators + void visitAnd(BinaryOperator &B) { visitBitwise(B, 0); } + void visitOr (BinaryOperator &B) { visitBitwise(B, 1); } + void visitXor(BinaryOperator &B) { visitBitwise(B, 2); } + void visitBitwise(BinaryOperator &B, unsigned OpcodeClass); + + // Binary comparison operators + + // Other operators void visitShiftInst(ShiftInst &I); + void visitPHINode(PHINode &I); void visitInstruction(Instruction &I) { std::cerr << "Cannot instruction select: " << I; @@ -142,19 +154,6 @@ void ISel::copyConstantToRegister(Constant *C, unsigned R) { } } -/// visitPHINode - Turn an LLVM PHI node into an X86 PHI node... -/// -void ISel::visitPHINode(PHINode &PN) { - MachineInstr *MI = BuildMI(BB, X86::PHI, PN.getNumOperands(), getReg(PN)); - - for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { - // FIXME: This will put constants after the PHI nodes in the block, which - // is invalid. They should be put inline into the PHI node eventually. - // - MI->addRegOperand(getReg(PN.getIncomingValue(i))); - MI->addPCDispOperand(PN.getIncomingBlock(i)); - } -} /// 'ret' instruction - Here we are interested in meeting the x86 ABI. As such, @@ -192,6 +191,50 @@ void ISel::visitBranchInst(BranchInst &BI) { } + +/// 'add' instruction - Simply turn this into an x86 reg,reg add instruction. +void ISel::visitAdd(BinaryOperator &B) { + unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1)); + unsigned DestReg = getReg(B); + unsigned Class = getClass(B.getType()); + + static const unsigned Opcodes[] = { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32 }; + + if (Class >= sizeof(Opcodes)/sizeof(Opcodes[0])) + visitInstruction(B); // Not handled class yet... + + BuildMI(BB, Opcodes[Class], 2, DestReg).addReg(Op0r).addReg(Op1r); + + // For Longs: Here we have a pair of operands each occupying a pair of + // registers. We need to do an ADDrr32 of the least-significant pair + // immediately followed by an ADCrr32 (Add with Carry) of the most-significant + // pair. I don't know how we are representing these multi-register arguments. +} + +/// visitBitwise - Implement the three bitwise operators for integral types... +/// OperatorClass is one of: 0 for And, 1 for Or, 2 for Xor. +void ISel::visitBitwise(BinaryOperator &B, unsigned OperatorClass) { + if (B.getType() == Type::BoolTy) // FIXME: Handle bools + visitInstruction(B); + + unsigned Class = getClass(B.getType()); + if (Class > 2) // FIXME: Handle longs + visitInstruction(B); + + static const unsigned OpcodeTab[][4] = { + { X86::ANDrr8, X86::ANDrr16, X86::ANDrr32, 0 }, // AND + { X86:: ORrr8, X86:: ORrr16, X86:: ORrr32, 0 }, // OR + { X86::XORrr8, X86::XORrr16, X86::XORrr32, 0 }, // XOR + }; + + unsigned Opcode = OpcodeTab[OperatorClass][Class]; + unsigned Op0r = getReg(B.getOperand(0)); + unsigned Op1r = getReg(B.getOperand(1)); + BuildMI(BB, Opcode, 2, getReg(B)).addReg(Op0r).addReg(Op1r); +} + + + /// 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, @@ -255,28 +298,21 @@ ISel::visitShiftInst (ShiftInst & I) } } +/// visitPHINode - Turn an LLVM PHI node into an X86 PHI node... +/// +void ISel::visitPHINode(PHINode &PN) { + MachineInstr *MI = BuildMI(BB, X86::PHI, PN.getNumOperands(), getReg(PN)); -/// 'add' instruction - Simply turn this into an x86 reg,reg add instruction. -void ISel::visitAdd(BinaryOperator &B) { - unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1)); - unsigned DestReg = getReg(B); - unsigned Class = getClass(B.getType()); - - static const unsigned Opcodes[] = { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32 }; - - if (Class >= sizeof(Opcodes)/sizeof(Opcodes[0])) - visitInstruction(B); // Not handled class yet... - - BuildMI(BB, Opcodes[Class], 2, DestReg).addReg(Op0r).addReg(Op1r); - - // For Longs: Here we have a pair of operands each occupying a pair of - // registers. We need to do an ADDrr32 of the least-significant pair - // immediately followed by an ADCrr32 (Add with Carry) of the most-significant - // pair. I don't know how we are representing these multi-register arguments. + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { + // FIXME: This will put constants after the PHI nodes in the block, which + // is invalid. They should be put inline into the PHI node eventually. + // + MI->addRegOperand(getReg(PN.getIncomingValue(i))); + MI->addPCDispOperand(PN.getIncomingBlock(i)); + } } - /// createSimpleX86InstructionSelector - This pass converts an LLVM function /// into a machine code representation is a very simple peep-hole fashion. The /// generated code sucks but the implementation is nice and simple. diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp index 106d99b19dc..425ff9ed81c 100644 --- a/lib/Target/X86/X86ISelSimple.cpp +++ b/lib/Target/X86/X86ISelSimple.cpp @@ -55,11 +55,23 @@ namespace { // Visitation methods for various instructions. These methods simply emit // fixed X86 code for each instruction. // - void visitPHINode(PHINode &I); void visitReturnInst(ReturnInst &RI); void visitBranchInst(BranchInst &BI); + + // Arithmetic operators void visitAdd(BinaryOperator &B); + + // Bitwise operators + void visitAnd(BinaryOperator &B) { visitBitwise(B, 0); } + void visitOr (BinaryOperator &B) { visitBitwise(B, 1); } + void visitXor(BinaryOperator &B) { visitBitwise(B, 2); } + void visitBitwise(BinaryOperator &B, unsigned OpcodeClass); + + // Binary comparison operators + + // Other operators void visitShiftInst(ShiftInst &I); + void visitPHINode(PHINode &I); void visitInstruction(Instruction &I) { std::cerr << "Cannot instruction select: " << I; @@ -142,19 +154,6 @@ void ISel::copyConstantToRegister(Constant *C, unsigned R) { } } -/// visitPHINode - Turn an LLVM PHI node into an X86 PHI node... -/// -void ISel::visitPHINode(PHINode &PN) { - MachineInstr *MI = BuildMI(BB, X86::PHI, PN.getNumOperands(), getReg(PN)); - - for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { - // FIXME: This will put constants after the PHI nodes in the block, which - // is invalid. They should be put inline into the PHI node eventually. - // - MI->addRegOperand(getReg(PN.getIncomingValue(i))); - MI->addPCDispOperand(PN.getIncomingBlock(i)); - } -} /// 'ret' instruction - Here we are interested in meeting the x86 ABI. As such, @@ -192,6 +191,50 @@ void ISel::visitBranchInst(BranchInst &BI) { } + +/// 'add' instruction - Simply turn this into an x86 reg,reg add instruction. +void ISel::visitAdd(BinaryOperator &B) { + unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1)); + unsigned DestReg = getReg(B); + unsigned Class = getClass(B.getType()); + + static const unsigned Opcodes[] = { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32 }; + + if (Class >= sizeof(Opcodes)/sizeof(Opcodes[0])) + visitInstruction(B); // Not handled class yet... + + BuildMI(BB, Opcodes[Class], 2, DestReg).addReg(Op0r).addReg(Op1r); + + // For Longs: Here we have a pair of operands each occupying a pair of + // registers. We need to do an ADDrr32 of the least-significant pair + // immediately followed by an ADCrr32 (Add with Carry) of the most-significant + // pair. I don't know how we are representing these multi-register arguments. +} + +/// visitBitwise - Implement the three bitwise operators for integral types... +/// OperatorClass is one of: 0 for And, 1 for Or, 2 for Xor. +void ISel::visitBitwise(BinaryOperator &B, unsigned OperatorClass) { + if (B.getType() == Type::BoolTy) // FIXME: Handle bools + visitInstruction(B); + + unsigned Class = getClass(B.getType()); + if (Class > 2) // FIXME: Handle longs + visitInstruction(B); + + static const unsigned OpcodeTab[][4] = { + { X86::ANDrr8, X86::ANDrr16, X86::ANDrr32, 0 }, // AND + { X86:: ORrr8, X86:: ORrr16, X86:: ORrr32, 0 }, // OR + { X86::XORrr8, X86::XORrr16, X86::XORrr32, 0 }, // XOR + }; + + unsigned Opcode = OpcodeTab[OperatorClass][Class]; + unsigned Op0r = getReg(B.getOperand(0)); + unsigned Op1r = getReg(B.getOperand(1)); + BuildMI(BB, Opcode, 2, getReg(B)).addReg(Op0r).addReg(Op1r); +} + + + /// 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, @@ -255,28 +298,21 @@ ISel::visitShiftInst (ShiftInst & I) } } +/// visitPHINode - Turn an LLVM PHI node into an X86 PHI node... +/// +void ISel::visitPHINode(PHINode &PN) { + MachineInstr *MI = BuildMI(BB, X86::PHI, PN.getNumOperands(), getReg(PN)); -/// 'add' instruction - Simply turn this into an x86 reg,reg add instruction. -void ISel::visitAdd(BinaryOperator &B) { - unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1)); - unsigned DestReg = getReg(B); - unsigned Class = getClass(B.getType()); - - static const unsigned Opcodes[] = { X86::ADDrr8, X86::ADDrr16, X86::ADDrr32 }; - - if (Class >= sizeof(Opcodes)/sizeof(Opcodes[0])) - visitInstruction(B); // Not handled class yet... - - BuildMI(BB, Opcodes[Class], 2, DestReg).addReg(Op0r).addReg(Op1r); - - // For Longs: Here we have a pair of operands each occupying a pair of - // registers. We need to do an ADDrr32 of the least-significant pair - // immediately followed by an ADCrr32 (Add with Carry) of the most-significant - // pair. I don't know how we are representing these multi-register arguments. + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { + // FIXME: This will put constants after the PHI nodes in the block, which + // is invalid. They should be put inline into the PHI node eventually. + // + MI->addRegOperand(getReg(PN.getIncomingValue(i))); + MI->addPCDispOperand(PN.getIncomingBlock(i)); + } } - /// createSimpleX86InstructionSelector - This pass converts an LLVM function /// into a machine code representation is a very simple peep-hole fashion. The /// generated code sucks but the implementation is nice and simple. diff --git a/lib/Target/X86/X86InstrInfo.def b/lib/Target/X86/X86InstrInfo.def index 327c4e64f68..2bddb4ccc5d 100644 --- a/lib/Target/X86/X86InstrInfo.def +++ b/lib/Target/X86/X86InstrInfo.def @@ -48,7 +48,18 @@ I(MOVir32 , "movl", 0, 0) // R32 = imm32 B8+ rd // Arithmetic instructions I(ADDrr8 , "addb", 0, 0) // R8 += R8 00/r I(ADDrr16 , "addw", 0, 0) // R16 += R16 01/r -I(ADDrr32 , "addl", 0, 0) // R32 += R32 02/r +I(ADDrr32 , "addl", 0, 0) // R32 += R32 01/r + +// Logical operators +I(ANDrr8 , "andb", 0, 0) // R8 &= R8 20/r +I(ANDrr16 , "andw", 0, 0) // R16 &= R16 21/r +I(ANDrr32 , "andl", 0, 0) // R32 &= R32 21/r +I(ORrr8 , "orb", 0, 0) // R8 |= R8 08/r +I(ORrr16 , "orw", 0, 0) // R16 |= R16 09/r +I(ORrr32 , "orl", 0, 0) // R32 |= R32 09/r +I(XORrr8 , "xorb", 0, 0) // R8 ^= R8 30/r +I(XORrr16 , "xorw", 0, 0) // R16 ^= R16 31/r +I(XORrr32 , "xorl", 0, 0) // R32 ^= R32 31/r // Shift instructions I(SHLrr8 , "shlb", 0, 0) // R8 <<= cl D2/4