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

Eric Christopher echristo at gmail.com
Tue Oct 14 16:27:22 PDT 2014


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