aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/SparcV8
diff options
context:
space:
mode:
authorBrian Gaeke <gaeke@uiuc.edu>2004-12-11 05:19:02 +0000
committerBrian Gaeke <gaeke@uiuc.edu>2004-12-11 05:19:02 +0000
commit4f70b63ebcae70c8b875244f8976baa2097adcc2 (patch)
treeda9a1f5a85c6e5fae9c93aee44759b1b75a8169e /lib/Target/SparcV8
parent9d6ffb47b4f4c8a51ed100a90af9488ce6cc0778 (diff)
downloadexternal_llvm-4f70b63ebcae70c8b875244f8976baa2097adcc2.zip
external_llvm-4f70b63ebcae70c8b875244f8976baa2097adcc2.tar.gz
external_llvm-4f70b63ebcae70c8b875244f8976baa2097adcc2.tar.bz2
Make GEPs not suck so much:
* Don't emit the Index * ElementSize multiply if Index is a constant. * Use a shift, not a multiply, if ElementSize is 1/2/4/8. * If ElementSize fits in the immediate field of SMUL, then put it there. Fix a bug where struct offsets might be truncated (ConstantSInt::get is now used instead of ConstantInt::get). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@18792 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/SparcV8')
-rw-r--r--lib/Target/SparcV8/SparcV8ISelSimple.cpp82
1 files changed, 67 insertions, 15 deletions
diff --git a/lib/Target/SparcV8/SparcV8ISelSimple.cpp b/lib/Target/SparcV8/SparcV8ISelSimple.cpp
index 60c9585..5959c47 100644
--- a/lib/Target/SparcV8/SparcV8ISelSimple.cpp
+++ b/lib/Target/SparcV8/SparcV8ISelSimple.cpp
@@ -1059,15 +1059,15 @@ void V8ISel::emitGEPOperation (MachineBasicBlock *MBB,
unsigned memberOffset =
TD.getStructLayout (StTy)->MemberOffsets[fieldIndex];
// Emit an ADD to add memberOffset to the basePtr.
- // We might have to copy memberOffset into a register first, if it's
- // big.
+ // We might have to copy memberOffset into a register first, if
+ // it's big.
if (memberOffset + 4096 < 8191) {
BuildMI (*MBB, IP, V8::ADDri, 2,
nextBasePtrReg).addReg (basePtrReg).addSImm (memberOffset);
} else {
unsigned offsetReg = makeAnotherReg (Type::IntTy);
copyConstantToRegister (MBB, IP,
- ConstantInt::get(Type::IntTy, memberOffset), offsetReg);
+ ConstantSInt::get(Type::IntTy, memberOffset), offsetReg);
BuildMI (*MBB, IP, V8::ADDrr, 2,
nextBasePtrReg).addReg (basePtrReg).addReg (offsetReg);
}
@@ -1081,18 +1081,70 @@ void V8ISel::emitGEPOperation (MachineBasicBlock *MBB,
// type is the type of the elements in the array).
Ty = SqTy->getElementType ();
unsigned elementSize = TD.getTypeSize (Ty);
- unsigned idxReg = getReg (idx, MBB, IP);
- unsigned OffsetReg = makeAnotherReg (Type::IntTy);
- unsigned elementSizeReg = makeAnotherReg (Type::UIntTy);
- copyConstantToRegister (MBB, IP,
- ConstantUInt::get(Type::UIntTy, elementSize), elementSizeReg);
- // Emit a SMUL to multiply the register holding the index by
- // elementSize, putting the result in OffsetReg.
- BuildMI (*MBB, IP, V8::SMULrr, 2,
- OffsetReg).addReg (elementSizeReg).addReg (idxReg);
- // Emit an ADD to add OffsetReg to the basePtr.
- BuildMI (*MBB, IP, V8::ADDrr, 2,
- nextBasePtrReg).addReg (basePtrReg).addReg (OffsetReg);
+ unsigned OffsetReg = ~0U;
+ int64_t Offset = -1;
+ bool addImmed = false;
+ if (isa<ConstantIntegral> (idx)) {
+ // If idx is a constant, we don't have to emit the multiply.
+ int64_t Val = cast<ConstantIntegral> (idx)->getRawValue ();
+ if ((Val * elementSize) + 4096 < 8191) {
+ // (Val * elementSize) is constant and fits in an immediate field.
+ // emit: nextBasePtrReg = ADDri basePtrReg, (Val * elementSize)
+ addImmed = true;
+ Offset = Val * elementSize;
+ } else {
+ // (Val * elementSize) is constant, but doesn't fit in an immediate
+ // field. emit: OffsetReg = (Val * elementSize)
+ // nextBasePtrReg = ADDrr OffsetReg, basePtrReg
+ OffsetReg = makeAnotherReg (Type::IntTy);
+ copyConstantToRegister (MBB, IP,
+ ConstantSInt::get(Type::IntTy, Val * elementSize), OffsetReg);
+ }
+ } else {
+ // idx is not constant, we have to shift or multiply.
+ OffsetReg = makeAnotherReg (Type::IntTy);
+ unsigned idxReg = getReg (idx, MBB, IP);
+ switch (elementSize) {
+ case 1:
+ BuildMI (*MBB, IP, V8::ORrr, 2, OffsetReg).addReg (V8::G0).addReg (idxReg);
+ break;
+ case 2:
+ BuildMI (*MBB, IP, V8::SLLri, 2, OffsetReg).addReg (idxReg).addZImm (1);
+ break;
+ case 4:
+ BuildMI (*MBB, IP, V8::SLLri, 2, OffsetReg).addReg (idxReg).addZImm (2);
+ break;
+ case 8:
+ BuildMI (*MBB, IP, V8::SLLri, 2, OffsetReg).addReg (idxReg).addZImm (3);
+ break;
+ default: {
+ if (elementSize + 4096 < 8191) {
+ // Emit a SMUL to multiply the register holding the index by
+ // elementSize, putting the result in OffsetReg.
+ BuildMI (*MBB, IP, V8::SMULri, 2,
+ OffsetReg).addReg (idxReg).addSImm (elementSize);
+ } else {
+ unsigned elementSizeReg = makeAnotherReg (Type::UIntTy);
+ copyConstantToRegister (MBB, IP,
+ ConstantUInt::get(Type::UIntTy, elementSize), elementSizeReg);
+ // Emit a SMUL to multiply the register holding the index by
+ // the register w/ elementSize, putting the result in OffsetReg.
+ BuildMI (*MBB, IP, V8::SMULrr, 2,
+ OffsetReg).addReg (idxReg).addReg (elementSizeReg);
+ }
+ break;
+ }
+ }
+ }
+ if (addImmed) {
+ // Emit an ADD to add the constant immediate Offset to the basePtr.
+ BuildMI (*MBB, IP, V8::ADDri, 2,
+ nextBasePtrReg).addReg (basePtrReg).addSImm (Offset);
+ } else {
+ // Emit an ADD to add OffsetReg to the basePtr.
+ BuildMI (*MBB, IP, V8::ADDrr, 2,
+ nextBasePtrReg).addReg (basePtrReg).addReg (OffsetReg);
+ }
}
basePtrReg = nextBasePtrReg;
}