diff options
author | Brian Gaeke <gaeke@uiuc.edu> | 2004-12-11 05:19:02 +0000 |
---|---|---|
committer | Brian Gaeke <gaeke@uiuc.edu> | 2004-12-11 05:19:02 +0000 |
commit | 4f70b63ebcae70c8b875244f8976baa2097adcc2 (patch) | |
tree | da9a1f5a85c6e5fae9c93aee44759b1b75a8169e /lib/Target/SparcV8 | |
parent | 9d6ffb47b4f4c8a51ed100a90af9488ce6cc0778 (diff) | |
download | external_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.cpp | 82 |
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; } |