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

Chad Rosier mcrosier at codeaurora.org
Mon Aug 4 15:17:34 PDT 2014


Thanks, Juergen.

> Thanks Chad,
>
> this should be fixed in r214788. I tweaked the parameters to UBFM/SBFM to
> get the zero-/sign-extension for free.

Cool!

> This way we don’t need to emit a instruction afterwards to mask out the
> upper bits.
>
> Cheers,
> Juergen
>
> On Aug 2, 2014, at 8:39 PM, Chad Rosier <mcrosier at codeaurora.org> wrote:
>
>> Hi Juergen,
>> A shift with a non-legal value type (i.e., i8/i16) requires special
>> handling.  Consider the following testcase:
>>
>> target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
>> target triple = "aarch64--linux-gnu"
>>
>> @C = constant i8 65, align 4
>>
>> define i32 @main(i32 %argc, i8** %argv) {
>> entry:
>>  %load = load i8* @C, align 1
>>  %shl = shl i8 %load, 4
>>  %ashr = ashr i8 %shl, 4
>>  %cast = sext i8 %ashr to i32
>>  ret i32 %cast
>> }
>>
>> Fast-isel produces 65, but the correct value is 1.  The first solution
>> that comes to mind would be to emit an ANDri with the appropriate mask
>> after a left-shift.
>>
>> When you have a moment, please take a look..
>>
>> Regards,
>>  Chad
>>
>>> 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
>>> +}
>>> +
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>
>>
>>
>> --
>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
>> hosted by The Linux Foundation
>>
>
>


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation




More information about the llvm-commits mailing list