[llvm] r214345 - [FastISel][AArch64] Add support for shift-immediate.

Juergen Ributzka juergen at apple.com
Wed Jul 30 15:04:23 PDT 2014


Author: ributzka
Date: Wed Jul 30 17:04:22 2014
New Revision: 214345

URL: http://llvm.org/viewvc/llvm-project?rev=214345&view=rev
Log:
[FastISel][AArch64] Add support for shift-immediate.

Currently the shift-immediate versions are not supported by tblgen and
hopefully this can be later removed, once the required support has been
added to tblgen.

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

Modified: llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp?rev=214345&r1=214344&r2=214345&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp Wed Jul 30 17:04:22 2014
@@ -109,6 +109,7 @@ private:
   bool SelectTrunc(const Instruction *I);
   bool SelectIntExt(const Instruction *I);
   bool SelectMul(const Instruction *I);
+  bool SelectShift(const Instruction *I, bool IsLeftShift, bool IsArithmetic);
 
   // Utility helper routines.
   bool isTypeLegal(Type *Ty, MVT &VT);
@@ -129,6 +130,9 @@ private:
                  bool UseUnscaled = false);
   unsigned EmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt);
   unsigned Emiti1Ext(unsigned SrcReg, MVT DestVT, bool isZExt);
+  unsigned Emit_LSL_ri(MVT RetVT, unsigned Op0, bool Op0IsKill, uint64_t Imm);
+  unsigned Emit_LSR_ri(MVT RetVT, unsigned Op0, bool Op0IsKill, uint64_t Imm);
+  unsigned Emit_ASR_ri(MVT RetVT, unsigned Op0, bool Op0IsKill, uint64_t Imm);
 
   unsigned AArch64MaterializeFP(const ConstantFP *CFP, MVT VT);
   unsigned AArch64MaterializeGV(const GlobalValue *GV);
@@ -1722,6 +1726,60 @@ unsigned AArch64FastISel::Emiti1Ext(unsi
   }
 }
 
+unsigned AArch64FastISel::Emit_LSL_ri(MVT RetVT, unsigned Op0, bool Op0IsKill,
+                                      uint64_t Shift) {
+  unsigned Opc, ImmR, ImmS;
+  switch (RetVT.SimpleTy) {
+  default: return 0;
+  case MVT::i8:
+  case MVT::i16:
+  case MVT::i32:
+    RetVT = MVT::i32;
+    Opc = AArch64::UBFMWri; ImmR = -Shift % 32; ImmS = 31 - Shift; break;
+  case MVT::i64:
+    Opc = AArch64::UBFMXri; ImmR = -Shift % 64; ImmS = 63 - Shift; break;
+  }
+
+  return FastEmitInst_rii(Opc, TLI.getRegClassFor(RetVT), Op0, Op0IsKill, ImmR,
+                          ImmS);
+}
+
+unsigned AArch64FastISel::Emit_LSR_ri(MVT RetVT, unsigned Op0, bool Op0IsKill,
+                                      uint64_t Shift) {
+  unsigned Opc, ImmS;
+  switch (RetVT.SimpleTy) {
+  default: return 0;
+  case MVT::i8:
+  case MVT::i16:
+  case MVT::i32:
+    RetVT = MVT::i32;
+    Opc = AArch64::UBFMWri; ImmS = 31; break;
+  case MVT::i64:
+    Opc = AArch64::UBFMXri; ImmS = 63; break;
+  }
+
+  return FastEmitInst_rii(Opc, TLI.getRegClassFor(RetVT), Op0, Op0IsKill, Shift,
+                          ImmS);
+}
+
+unsigned AArch64FastISel::Emit_ASR_ri(MVT RetVT, unsigned Op0, bool Op0IsKill,
+                                      uint64_t Shift) {
+  unsigned Opc, ImmS;
+  switch (RetVT.SimpleTy) {
+  default: return 0;
+  case MVT::i8:
+  case MVT::i16:
+  case MVT::i32:
+    RetVT = MVT::i32;
+    Opc = AArch64::SBFMWri; ImmS = 31; break;
+  case MVT::i64:
+    Opc = AArch64::SBFMXri; ImmS = 63; break;
+  }
+
+  return FastEmitInst_rii(Opc, TLI.getRegClassFor(RetVT), Op0, Op0IsKill, Shift,
+                          ImmS);
+}
+
 unsigned AArch64FastISel::EmitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT,
                                      bool isZExt) {
   assert(DestVT != MVT::i1 && "ZeroExt/SignExt an i1?");
@@ -1908,6 +1966,40 @@ bool AArch64FastISel::SelectMul(const In
   return true;
 }
 
+bool AArch64FastISel::SelectShift(const Instruction *I, bool IsLeftShift,
+                                  bool IsArithmetic) {
+  EVT RetEVT = TLI.getValueType(I->getType(), true);
+  if (!RetEVT.isSimple())
+    return false;
+  MVT RetVT = RetEVT.getSimpleVT();
+
+  if (!isa<ConstantInt>(I->getOperand(1)))
+    return false;
+
+  unsigned Op0Reg = getRegForValue(I->getOperand(0));
+  if (!Op0Reg)
+    return false;
+  bool Op0IsKill = hasTrivialKill(I->getOperand(0));
+
+  uint64_t ShiftVal = cast<ConstantInt>(I->getOperand(1))->getZExtValue();
+
+  unsigned ResultReg;
+  if (IsLeftShift)
+    ResultReg = Emit_LSL_ri(RetVT, Op0Reg, Op0IsKill, ShiftVal);
+  else {
+    if (IsArithmetic)
+      ResultReg = Emit_ASR_ri(RetVT, Op0Reg, Op0IsKill, ShiftVal);
+    else
+      ResultReg = Emit_LSR_ri(RetVT, Op0Reg, Op0IsKill, ShiftVal);
+  }
+
+  if (!ResultReg)
+    return false;
+
+  UpdateValueMap(I, ResultReg);
+  return true;
+}
+
 bool AArch64FastISel::TargetSelectInstruction(const Instruction *I) {
   switch (I->getOpcode()) {
   default:
@@ -1948,9 +2040,17 @@ bool AArch64FastISel::TargetSelectInstru
   case Instruction::ZExt:
   case Instruction::SExt:
     return SelectIntExt(I);
+
+  // FIXME: All of these should really be handled by the target-independent
+  // selector -> improve FastISel tblgen.
   case Instruction::Mul:
-    // FIXME: This really should be handled by the target-independent selector.
     return SelectMul(I);
+  case Instruction::Shl:
+      return SelectShift(I, /*IsLeftShift=*/true, /*IsArithmetic=*/false);
+  case Instruction::LShr:
+    return SelectShift(I, /*IsLeftShift=*/false, /*IsArithmetic=*/false);
+  case Instruction::AShr:
+    return SelectShift(I, /*IsLeftShift=*/false, /*IsArithmetic=*/true);
   }
   return false;
   // Silence warnings.

Added: llvm/trunk/test/CodeGen/AArch64/fast-isel-shift.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/fast-isel-shift.ll?rev=214345&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/fast-isel-shift.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/fast-isel-shift.ll Wed Jul 30 17:04:22 2014
@@ -0,0 +1,89 @@
+; RUN: llc -fast-isel -fast-isel-abort -mtriple=arm64-apple-darwin < %s | FileCheck %s
+
+; CHECK-LABEL: lsl_i8
+; CHECK: lsl {{w[0-9]*}}, {{w[0-9]*}}, #4
+define zeroext i8 @lsl_i8(i8 %a) {
+  %1 = shl i8 %a, 4
+  ret i8 %1
+}
+
+; CHECK-LABEL: lsl_i16
+; CHECK: lsl {{w[0-9]*}}, {{w[0-9]*}}, #8
+define zeroext i16 @lsl_i16(i16 %a) {
+  %1 = shl i16 %a, 8
+  ret i16 %1
+}
+
+; CHECK-LABEL: lsl_i32
+; CHECK: lsl {{w[0-9]*}}, {{w[0-9]*}}, #16
+define zeroext i32 @lsl_i32(i32 %a) {
+  %1 = shl i32 %a, 16
+  ret i32 %1
+}
+
+; FIXME: This shouldn't use the variable shift version.
+; CHECK-LABEL: lsl_i64
+; CHECK: lsl {{x[0-9]*}}, {{x[0-9]*}}, {{x[0-9]*}}
+define i64 @lsl_i64(i64 %a) {
+  %1 = shl i64 %a, 32
+  ret i64 %1
+}
+
+; CHECK-LABEL: lsr_i8
+; CHECK: lsr {{w[0-9]*}}, {{w[0-9]*}}, #4
+define zeroext i8 @lsr_i8(i8 %a) {
+  %1 = lshr i8 %a, 4
+  ret i8 %1
+}
+
+; CHECK-LABEL: lsr_i16
+; CHECK: lsr {{w[0-9]*}}, {{w[0-9]*}}, #8
+define zeroext i16 @lsr_i16(i16 %a) {
+  %1 = lshr i16 %a, 8
+  ret i16 %1
+}
+
+; CHECK-LABEL: lsr_i32
+; CHECK: lsr {{w[0-9]*}}, {{w[0-9]*}}, #16
+define zeroext i32 @lsr_i32(i32 %a) {
+  %1 = lshr i32 %a, 16
+  ret i32 %1
+}
+
+; FIXME: This shouldn't use the variable shift version.
+; CHECK-LABEL: lsr_i64
+; CHECK: lsr {{x[0-9]*}}, {{x[0-9]*}}, {{x[0-9]*}}
+define i64 @lsr_i64(i64 %a) {
+  %1 = lshr i64 %a, 32
+  ret i64 %1
+}
+
+; CHECK-LABEL: asr_i8
+; CHECK: asr {{w[0-9]*}}, {{w[0-9]*}}, #4
+define zeroext i8 @asr_i8(i8 %a) {
+  %1 = ashr i8 %a, 4
+  ret i8 %1
+}
+
+; CHECK-LABEL: asr_i16
+; CHECK: asr {{w[0-9]*}}, {{w[0-9]*}}, #8
+define zeroext i16 @asr_i16(i16 %a) {
+  %1 = ashr i16 %a, 8
+  ret i16 %1
+}
+
+; CHECK-LABEL: asr_i32
+; CHECK: asr {{w[0-9]*}}, {{w[0-9]*}}, #16
+define zeroext i32 @asr_i32(i32 %a) {
+  %1 = ashr i32 %a, 16
+  ret i32 %1
+}
+
+; FIXME: This shouldn't use the variable shift version.
+; CHECK-LABEL: asr_i64
+; CHECK: asr {{x[0-9]*}}, {{x[0-9]*}}, {{x[0-9]*}}
+define i64 @asr_i64(i64 %a) {
+  %1 = ashr i64 %a, 32
+  ret i64 %1
+}
+





More information about the llvm-commits mailing list