aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/X86
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-04-11 20:26:20 +0000
committerChris Lattner <sabre@nondot.org>2004-04-11 20:26:20 +0000
commit48b0c97e20305e234b8a27cc06b936829c745efe (patch)
tree00d5d5a89e26df26dc8065068c8dbf5bce91979e /lib/Target/X86
parent490e86fed58ddf97234a3188cd4a8670251b66f7 (diff)
downloadexternal_llvm-48b0c97e20305e234b8a27cc06b936829c745efe.zip
external_llvm-48b0c97e20305e234b8a27cc06b936829c745efe.tar.gz
external_llvm-48b0c97e20305e234b8a27cc06b936829c745efe.tar.bz2
Codegen FP adds and subtracts with a constant more efficiently, generating:
fld QWORD PTR [%ESP + 4] fadd QWORD PTR [.CPItest_add_0] instead of: fld QWORD PTR [%ESP + 4] fld QWORD PTR [.CPItest_add_0] faddp %ST(1) I also intend to do this for mul & div, but it appears that I have to refactor a bit of code before I can do so. This is tested by: test/Regression/CodeGen/X86/fp_constant_op.llx git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12839 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/X86')
-rw-r--r--lib/Target/X86/InstSelectSimple.cpp97
-rw-r--r--lib/Target/X86/X86ISelSimple.cpp97
2 files changed, 138 insertions, 56 deletions
diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp
index 8dbf61e..a9a3ae1 100644
--- a/lib/Target/X86/InstSelectSimple.cpp
+++ b/lib/Target/X86/InstSelectSimple.cpp
@@ -1830,36 +1830,27 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
unsigned Class = getClassB(Op0->getType());
// sub 0, X -> neg X
- if (OperatorClass == 1)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0)) {
- if (CI->isNullValue()) {
- unsigned op1Reg = getReg(Op1, MBB, IP);
- static unsigned const NEGTab[] = {
- X86::NEG8r, X86::NEG16r, X86::NEG32r, 0, X86::NEG32r
- };
- BuildMI(*MBB, IP, NEGTab[Class], 1, DestReg).addReg(op1Reg);
-
- if (Class == cLong) {
- // We just emitted: Dl = neg Sl
- // Now emit : T = addc Sh, 0
- // : Dh = neg T
- unsigned T = makeAnotherReg(Type::IntTy);
- BuildMI(*MBB, IP, X86::ADC32ri, 2, T).addReg(op1Reg+1).addImm(0);
- BuildMI(*MBB, IP, X86::NEG32r, 1, DestReg+1).addReg(T);
- }
- return;
- }
- } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(Op0))
- if (CFP->isExactlyValue(-0.0)) {
- // -0.0 - X === -X
- unsigned op1Reg = getReg(Op1, MBB, IP);
- BuildMI(*MBB, IP, X86::FCHS, 1, DestReg).addReg(op1Reg);
- return;
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0))
+ if (OperatorClass == 1 && CI->isNullValue()) {
+ unsigned op1Reg = getReg(Op1, MBB, IP);
+ static unsigned const NEGTab[] = {
+ X86::NEG8r, X86::NEG16r, X86::NEG32r, 0, X86::NEG32r
+ };
+ BuildMI(*MBB, IP, NEGTab[Class], 1, DestReg).addReg(op1Reg);
+
+ if (Class == cLong) {
+ // We just emitted: Dl = neg Sl
+ // Now emit : T = addc Sh, 0
+ // : Dh = neg T
+ unsigned T = makeAnotherReg(Type::IntTy);
+ BuildMI(*MBB, IP, X86::ADC32ri, 2, T).addReg(op1Reg+1).addImm(0);
+ BuildMI(*MBB, IP, X86::NEG32r, 1, DestReg+1).addReg(T);
}
+ return;
+ }
- // Special case: op Reg, <const>
- if (isa<ConstantInt>(Op1)) {
- ConstantInt *Op1C = cast<ConstantInt>(Op1);
+ // Special case: op Reg, <const int>
+ if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
unsigned Op0r = getReg(Op0, MBB, IP);
// xor X, -1 -> not X
@@ -1953,6 +1944,56 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
}
}
+ // Special case: op Reg, <const fp>
+ if (ConstantFP *Op1C = dyn_cast<ConstantFP>(Op1))
+ if (!Op1C->isExactlyValue(+0.0) && !Op1C->isExactlyValue(+1.0)) {
+ assert(OperatorClass < 2 && "FP operations only support add/sub!");
+
+ // Create a constant pool entry for this constant.
+ MachineConstantPool *CP = F->getConstantPool();
+ unsigned CPI = CP->getConstantPoolIndex(Op1C);
+ const Type *Ty = Op1->getType();
+
+ static const unsigned OpcodeTab[][2] = {
+ { X86::FADD32m, X86::FSUB32m }, // Float
+ { X86::FADD64m, X86::FSUB64m }, // Double
+ };
+
+ assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
+ unsigned Opcode = OpcodeTab[Ty != Type::FloatTy][OperatorClass];
+ unsigned Op0r = getReg(Op0, MBB, IP);
+ addConstantPoolReference(BuildMI(*MBB, IP, Opcode, 5,
+ DestReg).addReg(Op0r), CPI);
+ return;
+ }
+
+ // Special case: R1 = sub <const fp>, R2
+ if (ConstantFP *CFP = dyn_cast<ConstantFP>(Op0))
+ if (OperatorClass == 1) { // sub only
+ if (CFP->isExactlyValue(-0.0)) {
+ // -0.0 - X === -X
+ unsigned op1Reg = getReg(Op1, MBB, IP);
+ BuildMI(*MBB, IP, X86::FCHS, 1, DestReg).addReg(op1Reg);
+ return;
+ } else if (!CFP->isExactlyValue(+0.0) && !CFP->isExactlyValue(+1.0)) {
+ // R1 = sub CST, R2 --> R1 = subr R2, CST
+
+ // Create a constant pool entry for this constant.
+ MachineConstantPool *CP = F->getConstantPool();
+ unsigned CPI = CP->getConstantPoolIndex(CFP);
+ const Type *Ty = CFP->getType();
+
+ static const unsigned OpcodeTab[2] = { X86::FSUBR32m, X86::FSUBR64m };
+
+ assert(Ty == Type::FloatTy||Ty == Type::DoubleTy && "Unknown FP type!");
+ unsigned Opcode = OpcodeTab[Ty != Type::FloatTy];
+ unsigned Op1r = getReg(Op1, MBB, IP);
+ addConstantPoolReference(BuildMI(*MBB, IP, Opcode, 5,
+ DestReg).addReg(Op1r), CPI);
+ return;
+ }
+ }
+
// Finally, handle the general case now.
static const unsigned OpcodeTab[][5] = {
// Arithmetic operators
diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp
index 8dbf61e..a9a3ae1 100644
--- a/lib/Target/X86/X86ISelSimple.cpp
+++ b/lib/Target/X86/X86ISelSimple.cpp
@@ -1830,36 +1830,27 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
unsigned Class = getClassB(Op0->getType());
// sub 0, X -> neg X
- if (OperatorClass == 1)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0)) {
- if (CI->isNullValue()) {
- unsigned op1Reg = getReg(Op1, MBB, IP);
- static unsigned const NEGTab[] = {
- X86::NEG8r, X86::NEG16r, X86::NEG32r, 0, X86::NEG32r
- };
- BuildMI(*MBB, IP, NEGTab[Class], 1, DestReg).addReg(op1Reg);
-
- if (Class == cLong) {
- // We just emitted: Dl = neg Sl
- // Now emit : T = addc Sh, 0
- // : Dh = neg T
- unsigned T = makeAnotherReg(Type::IntTy);
- BuildMI(*MBB, IP, X86::ADC32ri, 2, T).addReg(op1Reg+1).addImm(0);
- BuildMI(*MBB, IP, X86::NEG32r, 1, DestReg+1).addReg(T);
- }
- return;
- }
- } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(Op0))
- if (CFP->isExactlyValue(-0.0)) {
- // -0.0 - X === -X
- unsigned op1Reg = getReg(Op1, MBB, IP);
- BuildMI(*MBB, IP, X86::FCHS, 1, DestReg).addReg(op1Reg);
- return;
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0))
+ if (OperatorClass == 1 && CI->isNullValue()) {
+ unsigned op1Reg = getReg(Op1, MBB, IP);
+ static unsigned const NEGTab[] = {
+ X86::NEG8r, X86::NEG16r, X86::NEG32r, 0, X86::NEG32r
+ };
+ BuildMI(*MBB, IP, NEGTab[Class], 1, DestReg).addReg(op1Reg);
+
+ if (Class == cLong) {
+ // We just emitted: Dl = neg Sl
+ // Now emit : T = addc Sh, 0
+ // : Dh = neg T
+ unsigned T = makeAnotherReg(Type::IntTy);
+ BuildMI(*MBB, IP, X86::ADC32ri, 2, T).addReg(op1Reg+1).addImm(0);
+ BuildMI(*MBB, IP, X86::NEG32r, 1, DestReg+1).addReg(T);
}
+ return;
+ }
- // Special case: op Reg, <const>
- if (isa<ConstantInt>(Op1)) {
- ConstantInt *Op1C = cast<ConstantInt>(Op1);
+ // Special case: op Reg, <const int>
+ if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
unsigned Op0r = getReg(Op0, MBB, IP);
// xor X, -1 -> not X
@@ -1953,6 +1944,56 @@ void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
}
}
+ // Special case: op Reg, <const fp>
+ if (ConstantFP *Op1C = dyn_cast<ConstantFP>(Op1))
+ if (!Op1C->isExactlyValue(+0.0) && !Op1C->isExactlyValue(+1.0)) {
+ assert(OperatorClass < 2 && "FP operations only support add/sub!");
+
+ // Create a constant pool entry for this constant.
+ MachineConstantPool *CP = F->getConstantPool();
+ unsigned CPI = CP->getConstantPoolIndex(Op1C);
+ const Type *Ty = Op1->getType();
+
+ static const unsigned OpcodeTab[][2] = {
+ { X86::FADD32m, X86::FSUB32m }, // Float
+ { X86::FADD64m, X86::FSUB64m }, // Double
+ };
+
+ assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
+ unsigned Opcode = OpcodeTab[Ty != Type::FloatTy][OperatorClass];
+ unsigned Op0r = getReg(Op0, MBB, IP);
+ addConstantPoolReference(BuildMI(*MBB, IP, Opcode, 5,
+ DestReg).addReg(Op0r), CPI);
+ return;
+ }
+
+ // Special case: R1 = sub <const fp>, R2
+ if (ConstantFP *CFP = dyn_cast<ConstantFP>(Op0))
+ if (OperatorClass == 1) { // sub only
+ if (CFP->isExactlyValue(-0.0)) {
+ // -0.0 - X === -X
+ unsigned op1Reg = getReg(Op1, MBB, IP);
+ BuildMI(*MBB, IP, X86::FCHS, 1, DestReg).addReg(op1Reg);
+ return;
+ } else if (!CFP->isExactlyValue(+0.0) && !CFP->isExactlyValue(+1.0)) {
+ // R1 = sub CST, R2 --> R1 = subr R2, CST
+
+ // Create a constant pool entry for this constant.
+ MachineConstantPool *CP = F->getConstantPool();
+ unsigned CPI = CP->getConstantPoolIndex(CFP);
+ const Type *Ty = CFP->getType();
+
+ static const unsigned OpcodeTab[2] = { X86::FSUBR32m, X86::FSUBR64m };
+
+ assert(Ty == Type::FloatTy||Ty == Type::DoubleTy && "Unknown FP type!");
+ unsigned Opcode = OpcodeTab[Ty != Type::FloatTy];
+ unsigned Op1r = getReg(Op1, MBB, IP);
+ addConstantPoolReference(BuildMI(*MBB, IP, Opcode, 5,
+ DestReg).addReg(Op1r), CPI);
+ return;
+ }
+ }
+
// Finally, handle the general case now.
static const unsigned OpcodeTab[][5] = {
// Arithmetic operators