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

Juergen Ributzka juergen at apple.com
Mon Aug 4 15:07:32 PDT 2014


Thanks Chad,

this should be fixed in r214788. I tweaked the parameters to UBFM/SBFM to get the zero-/sign-extension for free.
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
> 





More information about the llvm-commits mailing list