[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 dont 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