[llvm] r221923 - [FastISel][AArch64] Don't bail during simple GEP instruction selection.

Juergen Ributzka juergen at apple.com
Thu Nov 13 12:50:44 PST 2014


Author: ributzka
Date: Thu Nov 13 14:50:44 2014
New Revision: 221923

URL: http://llvm.org/viewvc/llvm-project?rev=221923&view=rev
Log:
[FastISel][AArch64] Don't bail during simple GEP instruction selection.

The generic FastISel code would bail, because it can't emit a sign-extend for
AArch64. This copies the code over and uses AArch64 specific emit functions.

This is not ideal and 'computeAddress' should handles this, so it can fold the
address computation into the memory operation.

I plan to clean up 'computeAddress' anyways, so I will add that in a future
commit.

Related to rdar://problem/18962471.

Modified:
    llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp
    llvm/trunk/test/CodeGen/AArch64/fast-isel-gep.ll

Modified: llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp?rev=221923&r1=221922&r2=221923&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp Thu Nov 13 14:50:44 2014
@@ -151,6 +151,7 @@ private:
                          const Value *Cond);
   bool optimizeIntExtLoad(const Instruction *I, MVT RetVT, MVT SrcVT);
   bool optimizeSelect(const SelectInst *SI);
+  std::pair<unsigned, bool> getRegForGEPIndex(const Value *Idx);
 
   // Emit helper routines.
   unsigned emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
@@ -4725,6 +4726,28 @@ bool AArch64FastISel::selectSDiv(const 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<unsigned, bool> AArch64FastISel::getRegForGEPIndex(const Value *Idx) {
+  unsigned IdxN = getRegForValue(Idx);
+  if (IdxN == 0)
+    // Unhandled operand. Halt "fast" selection and bail.
+    return std::pair<unsigned, bool>(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<unsigned, bool>(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

Modified: 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=221923&r1=221922&r2=221923&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/fast-isel-gep.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/fast-isel-gep.ll Thu Nov 13 14:50:44 2014
@@ -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
+}





More information about the llvm-commits mailing list