diff --git a/lib/Target/AArch64/AArch64FastISel.cpp b/lib/Target/AArch64/AArch64FastISel.cpp index 1b1aaf214fb..4d18a4e0b0f 100644 --- a/lib/Target/AArch64/AArch64FastISel.cpp +++ b/lib/Target/AArch64/AArch64FastISel.cpp @@ -151,6 +151,7 @@ private: const Value *Cond); bool optimizeIntExtLoad(const Instruction *I, MVT RetVT, MVT SrcVT); bool optimizeSelect(const SelectInst *SI); + std::pair getRegForGEPIndex(const Value *Idx); // Emit helper routines. unsigned emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS, @@ -4725,6 +4726,28 @@ bool AArch64FastISel::selectSDiv(const Instruction *I) { return true; } +/// This is mostly a copy of the existing FastISel getRegForGEPIndex code. We +/// have to duplicate it for AArch64, because otherwise we would fail during the +/// sign-extend emission. +std::pair AArch64FastISel::getRegForGEPIndex(const Value *Idx) { + unsigned IdxN = getRegForValue(Idx); + if (IdxN == 0) + // Unhandled operand. Halt "fast" selection and bail. + return std::pair(0, false); + + bool IdxNIsKill = hasTrivialKill(Idx); + + // If the index is smaller or larger than intptr_t, truncate or extend it. + MVT PtrVT = TLI.getPointerTy(); + EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false); + if (IdxVT.bitsLT(PtrVT)) { + IdxN = emitIntExt(IdxVT.getSimpleVT(), IdxN, PtrVT, /*IsZExt=*/false); + IdxNIsKill = true; + } else if (IdxVT.bitsGT(PtrVT)) + llvm_unreachable("AArch64 FastISel doesn't support types larger than i64"); + return std::pair(IdxN, IdxNIsKill); +} + /// This is mostly a copy of the existing FastISel GEP code, but we have to /// duplicate it for AArch64, because otherwise we would bail out even for /// simple cases. This is because the standard fastEmit functions don't cover diff --git a/test/CodeGen/AArch64/fast-isel-gep.ll b/test/CodeGen/AArch64/fast-isel-gep.ll index 465f595245c..4dc0a05894f 100644 --- a/test/CodeGen/AArch64/fast-isel-gep.ll +++ b/test/CodeGen/AArch64/fast-isel-gep.ll @@ -39,3 +39,11 @@ define i32* @test_array4(i32* %a) { ret i32* %1 } +define i32* @test_array5(i32* %a, i32 %i) { +; CHECK-LABEL: test_array5 +; CHECK: sxtw [[REG1:x[0-9]+]], w1 +; CHECK-NEXT: orr [[REG2:x[0-9]+]], xzr, #0x4 +; CHECK-NEXT: madd {{x[0-9]+}}, [[REG1]], [[REG2]], x0 + %1 = getelementptr inbounds i32* %a, i32 %i + ret i32* %1 +}