[llvm] r219726 - [FastISel][AArch64] Add custom lowering for GEPs.

Juergen Ributzka juergen at apple.com
Tue Oct 14 22:26:12 PDT 2014


Hi Eric,

I reverted this commit in r219776 for other reasons (broke our internal build bots) and I will add the comments when I recommit.

Cheers,
Juergen

> On Oct 14, 2014, at 4:27 PM, Eric Christopher <echristo at gmail.com> wrote:
> 
> Could you document that you're largely copying it out and the changes
> you've made as either a block comment or block comment with some
> inline comments of "here we bail out"?
> 
> Thanks!
> 
> -eric
> 
> On Tue, Oct 14, 2014 at 2:41 PM, Juergen Ributzka <juergen at apple.com> wrote:
>> Author: ributzka
>> Date: Tue Oct 14 16:41:23 2014
>> New Revision: 219726
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=219726&view=rev
>> Log:
>> [FastISel][AArch64] Add custom lowering for GEPs.
>> 
>> This is mostly a copy of the existing FastISel GEP code, but on AArch64 we bail
>> out even for simple cases, because the standard fastEmit functions don't cover
>> MUL and ADD is lowered inefficientily.
>> 
>> Added:
>>    llvm/trunk/test/CodeGen/AArch64/fast-isel-gep.ll
>> Modified:
>>    llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp
>>    llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-alloca.ll
>> 
>> Modified: llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp?rev=219726&r1=219725&r2=219726&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp (original)
>> +++ llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp Tue Oct 14 16:41:23 2014
>> @@ -134,6 +134,7 @@ private:
>>   bool selectBitCast(const Instruction *I);
>>   bool selectFRem(const Instruction *I);
>>   bool selectSDiv(const Instruction *I);
>> +  bool selectGetElementPtr(const Instruction *I);
>> 
>>   // Utility helper routines.
>>   bool isTypeLegal(Type *Ty, MVT &VT);
>> @@ -4541,6 +4542,88 @@ bool AArch64FastISel::selectSDiv(const I
>>   return true;
>> }
>> 
>> +bool AArch64FastISel::selectGetElementPtr(const Instruction *I) {
>> +  unsigned N = getRegForValue(I->getOperand(0));
>> +  if (!N)
>> +    return false;
>> +  bool NIsKill = hasTrivialKill(I->getOperand(0));
>> +
>> +  // Keep a running tab of the total offset to coalesce multiple N = N + Offset
>> +  // into a single N = N + TotalOffset.
>> +  uint64_t TotalOffs = 0;
>> +  Type *Ty = I->getOperand(0)->getType();
>> +  MVT VT = TLI.getPointerTy();
>> +  for (auto OI = std::next(I->op_begin()), E = I->op_end(); OI != E; ++OI) {
>> +    const Value *Idx = *OI;
>> +    if (auto *StTy = dyn_cast<StructType>(Ty)) {
>> +      unsigned Field = cast<ConstantInt>(Idx)->getZExtValue();
>> +      // N = N + Offset
>> +      if (Field)
>> +        TotalOffs += DL.getStructLayout(StTy)->getElementOffset(Field);
>> +      Ty = StTy->getElementType(Field);
>> +    } else {
>> +      Ty = cast<SequentialType>(Ty)->getElementType();
>> +      // If this is a constant subscript, handle it quickly.
>> +      if (const auto *CI = dyn_cast<ConstantInt>(Idx)) {
>> +        if (CI->isZero())
>> +          continue;
>> +        // N = N + Offset
>> +        TotalOffs +=
>> +            DL.getTypeAllocSize(Ty) * cast<ConstantInt>(CI)->getSExtValue();
>> +        continue;
>> +      }
>> +      if (TotalOffs) {
>> +        N = emitAddSub_ri(/*UseAdd=*/true, VT, N, NIsKill, TotalOffs);
>> +        if (!N) {
>> +          unsigned C = fastEmit_i(VT, VT, ISD::Constant, TotalOffs);
>> +          if (!C)
>> +            return false;
>> +          N = emitAddSub_rr(/*UseAdd=*/true, VT, N, NIsKill, C, true);
>> +          if (!N)
>> +            return false;
>> +        }
>> +        NIsKill = true;
>> +        TotalOffs = 0;
>> +      }
>> +
>> +      // N = N + Idx * ElementSize;
>> +      uint64_t ElementSize = DL.getTypeAllocSize(Ty);
>> +      std::pair<unsigned, bool> Pair = getRegForGEPIndex(Idx);
>> +      unsigned IdxN = Pair.first;
>> +      bool IdxNIsKill = Pair.second;
>> +      if (!IdxN)
>> +        return false;
>> +
>> +      if (ElementSize != 1) {
>> +        unsigned C = fastEmit_i(VT, VT, ISD::Constant, ElementSize);
>> +        if (!C)
>> +          return false;
>> +        IdxN = emitMul_rr(VT, IdxN, IdxNIsKill, C, true);
>> +        if (!IdxN)
>> +          return false;
>> +        IdxNIsKill = true;
>> +      }
>> +      N = fastEmit_rr(VT, VT, ISD::ADD, N, NIsKill, IdxN, IdxNIsKill);
>> +      if (!N)
>> +        return false;
>> +    }
>> +  }
>> +  if (TotalOffs) {
>> +    N = emitAddSub_ri(/*UseAdd=*/true, VT, N, NIsKill, TotalOffs);
>> +    if (!N) {
>> +      unsigned C = fastEmit_i(VT, VT, ISD::Constant, TotalOffs);
>> +      if (!C)
>> +        return false;
>> +      N = emitAddSub_rr(/*UseAdd=*/true, VT, N, NIsKill, C, true);
>> +      if (!N)
>> +        return false;
>> +    }
>> +  }
>> +
>> +  updateValueMap(I, N);
>> +  return true;
>> +}
>> +
>> bool AArch64FastISel::fastSelectInstruction(const Instruction *I) {
>>   switch (I->getOpcode()) {
>>   default:
>> @@ -4612,6 +4695,8 @@ bool AArch64FastISel::fastSelectInstruct
>>     return selectRet(I);
>>   case Instruction::FRem:
>>     return selectFRem(I);
>> +  case Instruction::GetElementPtr:
>> +    return selectGetElementPtr(I);
>>   }
>> 
>>   // fall-back to target-independent instruction selection.
>> 
>> Modified: llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-alloca.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-alloca.ll?rev=219726&r1=219725&r2=219726&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-alloca.ll (original)
>> +++ llvm/trunk/test/CodeGen/AArch64/arm64-fast-isel-alloca.ll Tue Oct 14 16:41:23 2014
>> @@ -15,9 +15,8 @@ define void @main() nounwind {
>> entry:
>> ; CHECK: main
>> ; CHECK: mov x29, sp
>> -; CHECK: mov x[[REG:[0-9]+]], sp
>> -; CHECK-NEXT: orr x[[REG1:[0-9]+]], xzr, #0x8
>> -; CHECK-NEXT: add x0, x[[REG]], x[[REG1]]
>> +; CHECK: mov [[REG:x[0-9]+]], sp
>> +; CHECK-NEXT: add x0, [[REG]], #8
>>   %E = alloca %struct.S2Ty, align 4
>>   %B = getelementptr inbounds %struct.S2Ty* %E, i32 0, i32 1
>>   call void @takeS1(%struct.S1Ty* %B)
>> 
>> Added: llvm/trunk/test/CodeGen/AArch64/fast-isel-gep.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/fast-isel-gep.ll?rev=219726&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/AArch64/fast-isel-gep.ll (added)
>> +++ llvm/trunk/test/CodeGen/AArch64/fast-isel-gep.ll Tue Oct 14 16:41:23 2014
>> @@ -0,0 +1,18 @@
>> +; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort -verify-machineinstrs < %s | FileCheck %s
>> +
>> +%struct.foo = type { i32, i64, float, double }
>> +
>> +define double* @test_struct(%struct.foo* %f) {
>> +; CHECK-LABEL: test_struct
>> +; CHECK:       add x0, x0, #24
>> +  %1 = getelementptr inbounds %struct.foo* %f, i64 0, i32 3
>> +  ret double* %1
>> +}
>> +
>> +define i32* @test_array(i32* %a, i64 %i) {
>> +; CHECK-LABEL: test_array
>> +; CHECK:       orr [[REG:x[0-9]+]], xzr, #0x4
>> +; CHECK-NEXT:  madd  x0, x1, [[REG]], x0
>> +  %1 = getelementptr inbounds i32* %a, i64 %i
>> +  ret i32* %1
>> +}
>> 
>> 
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits





More information about the llvm-commits mailing list