[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