Index: llvm/trunk/lib/Target/AArch64/AArch64LegalizerInfo.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64LegalizerInfo.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64LegalizerInfo.cpp @@ -321,8 +321,29 @@ // Extensions getActionDefinitionsBuilder({G_ZEXT, G_SEXT, G_ANYEXT}) - .legalForCartesianProduct({s8, s16, s32, s64}, {s1, s8, s16, s32}) - .legalFor({v8s16, v8s8}); + .legalIf([=](const LegalityQuery &Query) { + unsigned DstSize = Query.Types[0].getSizeInBits(); + + // Make sure that we have something that will fit in a register, and + // make sure it's a power of 2. + if (DstSize < 8 || DstSize > 128 || !isPowerOf2_32(DstSize)) + return false; + + const LLT &SrcTy = Query.Types[1]; + + // Special case for s1. + if (SrcTy == s1) + return true; + + // Make sure we fit in a register otherwise. Don't bother checking that + // the source type is below 128 bits. We shouldn't be allowing anything + // through which is wider than the destination in the first place. + unsigned SrcSize = SrcTy.getSizeInBits(); + if (SrcSize < 8 || !isPowerOf2_32(SrcSize)) + return false; + + return true; + }); getActionDefinitionsBuilder(G_TRUNC).alwaysLegal(); Index: llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-ext.mir =================================================================== --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-ext.mir +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-ext.mir @@ -227,3 +227,140 @@ %2:_(<8 x s16>) = G_ANYEXT %1(<8 x s8>) $q0 = COPY %2(<8 x s16>) RET_ReallyLR implicit $q0 + +... +--- +name: test_zext_v4s32_from_v4s16 +alignment: 2 +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: test_zext_v4s32_from_v4s16 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $d0 + ; CHECK: [[ZEXT:%[0-9]+]]:_(<4 x s32>) = G_ZEXT [[COPY]](<4 x s16>) + ; CHECK: $q0 = COPY [[ZEXT]](<4 x s32>) + ; CHECK: RET_ReallyLR implicit $q0 + %0:_(<4 x s16>) = COPY $d0 + %1:_(<4 x s32>) = G_ZEXT %0(<4 x s16>) + $q0 = COPY %1(<4 x s32>) + RET_ReallyLR implicit $q0 + +... +--- +name: test_sext_v4s32_from_v4s16 +alignment: 2 +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: test_sext_v4s32_from_v4s16 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $d0 + ; CHECK: [[SEXT:%[0-9]+]]:_(<4 x s32>) = G_SEXT [[COPY]](<4 x s16>) + ; CHECK: $q0 = COPY [[SEXT]](<4 x s32>) + ; CHECK: RET_ReallyLR implicit $q0 + %0:_(<4 x s16>) = COPY $d0 + %1:_(<4 x s32>) = G_SEXT %0(<4 x s16>) + $q0 = COPY %1(<4 x s32>) + RET_ReallyLR implicit $q0 + +... +--- +name: test_anyext_v4s32_from_v4s16 +alignment: 2 +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: test_anyext_v4s32_from_v4s16 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $d0 + ; CHECK: [[ANYEXT:%[0-9]+]]:_(<4 x s32>) = G_ANYEXT [[COPY]](<4 x s16>) + ; CHECK: $q0 = COPY [[ANYEXT]](<4 x s32>) + ; CHECK: RET_ReallyLR implicit $q0 + %0:_(<4 x s16>) = COPY $d0 + %1:_(<4 x s32>) = G_ANYEXT %0(<4 x s16>) + $q0 = COPY %1(<4 x s32>) + RET_ReallyLR implicit $q0 + +... +--- +name: test_zext_v2s64_from_v2s32 +alignment: 2 +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: test_zext_v2s64_from_v2s32 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0 + ; CHECK: [[ZEXT:%[0-9]+]]:_(<2 x s64>) = G_ZEXT [[COPY]](<2 x s32>) + ; CHECK: $q0 = COPY [[ZEXT]](<2 x s64>) + ; CHECK: RET_ReallyLR implicit $q0 + %0:_(<2 x s32>) = COPY $d0 + %1:_(<2 x s64>) = G_ZEXT %0(<2 x s32>) + $q0 = COPY %1(<2 x s64>) + RET_ReallyLR implicit $q0 + +... +--- +name: test_sext_v2s64_from_v2s32 +alignment: 2 +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: test_sext_v2s64_from_v2s32 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0 + ; CHECK: [[SEXT:%[0-9]+]]:_(<2 x s64>) = G_SEXT [[COPY]](<2 x s32>) + ; CHECK: $q0 = COPY [[SEXT]](<2 x s64>) + ; CHECK: RET_ReallyLR implicit $q0 + %0:_(<2 x s32>) = COPY $d0 + %1:_(<2 x s64>) = G_SEXT %0(<2 x s32>) + $q0 = COPY %1(<2 x s64>) + RET_ReallyLR implicit $q0 + +... +--- +name: test_anyext_v2s64_from_v2s32 +alignment: 2 +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: test_anyext_v2s64_from_v2s32 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0 + ; CHECK: [[ANYEXT:%[0-9]+]]:_(<2 x s64>) = G_ANYEXT [[COPY]](<2 x s32>) + ; CHECK: $q0 = COPY [[ANYEXT]](<2 x s64>) + ; CHECK: RET_ReallyLR implicit $q0 + %0:_(<2 x s32>) = COPY $d0 + %1:_(<2 x s64>) = G_ANYEXT %0(<2 x s32>) + $q0 = COPY %1(<2 x s64>) + RET_ReallyLR implicit $q0 + +... Index: llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir =================================================================== --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -157,7 +157,7 @@ # DEBUG: .. type index coverage check SKIPPED: no rules defined # # DEBUG-NEXT: G_ANYEXT (opcode {{[0-9]+}}): 2 type indices -# DEBUG: .. the first uncovered type index: 2, OK +# DEBUG: .. type index coverage check SKIPPED: user-defined predicate detected # # DEBUG-NEXT: G_TRUNC (opcode {{[0-9]+}}): 2 type indices # DEBUG: .. type index coverage check SKIPPED: user-defined predicate detected @@ -175,10 +175,10 @@ # DEBUG: .. the first uncovered type index: 2, OK # # DEBUG-NEXT: G_SEXT (opcode {{[0-9]+}}): 2 type indices -# DEBUG: .. the first uncovered type index: 2, OK +# DEBUG: .. type index coverage check SKIPPED: user-defined predicate detected # # DEBUG-NEXT: G_ZEXT (opcode {{[0-9]+}}): 2 type indices -# DEBUG: .. the first uncovered type index: 2, OK +# DEBUG: .. type index coverage check SKIPPED: user-defined predicate detected # # DEBUG-NEXT: G_SHL (opcode {{[0-9]+}}): 2 type indices # DEBUG:.. type index coverage check SKIPPED: user-defined predicate detected Index: llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-int-ext.mir =================================================================== --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-int-ext.mir +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-int-ext.mir @@ -7,18 +7,24 @@ define void @anyext_s64_from_s32() { ret void } define void @anyext_s32_from_s8() { ret void } define void @anyext_v8s16_from_v8s8() { ret void } + define void @anyext_v4s32_from_v4s16() { ret void } + define void @anyext_v2s64_from_v2s32() { ret void } define void @zext_s64_from_s32() { ret void } define void @zext_s32_from_s16() { ret void } define void @zext_s32_from_s8() { ret void } define void @zext_s16_from_s8() { ret void } define void @zext_v8s16_from_v8s8() { ret void } + define void @zext_v4s32_from_v4s16() { ret void } + define void @zext_v2s64_from_v2s32() { ret void } define void @sext_s64_from_s32() { ret void } define void @sext_s32_from_s16() { ret void } define void @sext_s32_from_s8() { ret void } define void @sext_s16_from_s8() { ret void } define void @sext_v8s16_from_v8s8() { ret void } + define void @sext_v4s32_from_v4s16() { ret void } + define void @sext_v2s64_from_v2s32() { ret void } ... --- @@ -90,6 +96,60 @@ %1:fpr(<8 x s16>) = G_ANYEXT %0(<8 x s8>) $q0 = COPY %1(<8 x s16>) RET_ReallyLR implicit $q0 +... + +--- +name: anyext_v4s32_from_v4s16 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: anyext_v4s32_from_v4s16 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 + ; CHECK: [[USHLLv4i16_shift:%[0-9]+]]:fpr128 = USHLLv4i16_shift [[COPY]], 0 + ; CHECK: $q0 = COPY [[USHLLv4i16_shift]] + ; CHECK: RET_ReallyLR implicit $q0 + %0:fpr(<4 x s16>) = COPY $d0 + %1:fpr(<4 x s32>) = G_ANYEXT %0(<4 x s16>) + $q0 = COPY %1(<4 x s32>) + RET_ReallyLR implicit $q0 +... + +--- +name: anyext_v2s64_from_v2s32 +alignment: 2 +tracksRegLiveness: true +legalized: true +regBankSelected: true +tracksRegLiveness: true +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: anyext_v2s64_from_v2s32 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 + ; CHECK: [[USHLLv2i32_shift:%[0-9]+]]:fpr128 = USHLLv2i32_shift [[COPY]], 0 + ; CHECK: $q0 = COPY [[USHLLv2i32_shift]] + ; CHECK: RET_ReallyLR implicit $q0 + %0:fpr(<2 x s32>) = COPY $d0 + %1:fpr(<2 x s64>) = G_ANYEXT %0(<2 x s32>) + $q0 = COPY %1(<2 x s64>) + RET_ReallyLR implicit $q0 +... --- name: zext_s64_from_s32 @@ -213,6 +273,58 @@ ... --- +name: zext_v4s32_from_v4s16 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: zext_v4s32_from_v4s16 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 + ; CHECK: [[USHLLv4i16_shift:%[0-9]+]]:fpr128 = USHLLv4i16_shift [[COPY]], 0 + ; CHECK: $q0 = COPY [[USHLLv4i16_shift]] + ; CHECK: RET_ReallyLR implicit $q0 + %0:fpr(<4 x s16>) = COPY $d0 + %1:fpr(<4 x s32>) = G_ZEXT %0(<4 x s16>) + $q0 = COPY %1(<4 x s32>) + RET_ReallyLR implicit $q0 +... + +--- +name: zext_v2s64_from_v2s32 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: zext_v2s64_from_v2s32 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 + ; CHECK: [[USHLLv2i32_shift:%[0-9]+]]:fpr128 = USHLLv2i32_shift [[COPY]], 0 + ; CHECK: $q0 = COPY [[USHLLv2i32_shift]] + ; CHECK: RET_ReallyLR implicit $q0 + %0:fpr(<2 x s32>) = COPY $d0 + %1:fpr(<2 x s64>) = G_ZEXT %0(<2 x s32>) + $q0 = COPY %1(<2 x s64>) + RET_ReallyLR implicit $q0 +... + +--- name: sext_s64_from_s32 legalized: true regBankSelected: true @@ -332,3 +444,54 @@ RET_ReallyLR implicit $q0 ... + +--- +name: sext_v4s32_from_v4s16 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: sext_v4s32_from_v4s16 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 + ; CHECK: [[SSHLLv4i16_shift:%[0-9]+]]:fpr128 = SSHLLv4i16_shift [[COPY]], 0 + ; CHECK: $q0 = COPY [[SSHLLv4i16_shift]] + ; CHECK: RET_ReallyLR implicit $q0 + %0:fpr(<4 x s16>) = COPY $d0 + %1:fpr(<4 x s32>) = G_SEXT %0(<4 x s16>) + $q0 = COPY %1(<4 x s32>) + RET_ReallyLR implicit $q0 +... + +--- +name: sext_v2s64_from_v2s32 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } +machineFunctionInfo: {} +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: sext_v2s64_from_v2s32 + ; CHECK: liveins: $d0 + ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 + ; CHECK: [[SSHLLv2i32_shift:%[0-9]+]]:fpr128 = SSHLLv2i32_shift [[COPY]], 0 + ; CHECK: $q0 = COPY [[SSHLLv2i32_shift]] + ; CHECK: RET_ReallyLR implicit $q0 + %0:fpr(<2 x s32>) = COPY $d0 + %1:fpr(<2 x s64>) = G_SEXT %0(<2 x s32>) + $q0 = COPY %1(<2 x s64>) + RET_ReallyLR implicit $q0 Index: llvm/trunk/test/CodeGen/AArch64/arm64-subvector-extend.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/arm64-subvector-extend.ll +++ llvm/trunk/test/CodeGen/AArch64/arm64-subvector-extend.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple -asm-verbose=false | FileCheck %s +; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple -asm-verbose=false -global-isel -global-isel-abort=2 -pass-remarks-missed=gisel* 2>&1 | FileCheck %s --check-prefixes=CHECK,FALLBACK ; Test efficient codegen of vector extends up from legal type to 128 bit ; and 256 bit vector types. @@ -6,6 +7,8 @@ ;----- ; Vectors of i16. ;----- + +; FALLBACK-NOT: remark:{{.*}}(in function: func1) define <8 x i16> @func1(<8 x i8> %v0) nounwind { ; CHECK-LABEL: func1: ; CHECK-NEXT: ushll.8h v0, v0, #0 @@ -14,6 +17,7 @@ ret <8 x i16> %r } +; FALLBACK-NOT: remark:{{.*}}(in function: func2) define <8 x i16> @func2(<8 x i8> %v0) nounwind { ; CHECK-LABEL: func2: ; CHECK-NEXT: sshll.8h v0, v0, #0 @@ -44,6 +48,7 @@ ; Vectors of i32. ;----- +; FALLBACK-NOT: remark:{{.*}}(in function: afunc1) define <4 x i32> @afunc1(<4 x i16> %v0) nounwind { ; CHECK-LABEL: afunc1: ; CHECK-NEXT: ushll.4s v0, v0, #0 @@ -52,6 +57,7 @@ ret <4 x i32> %r } +; FALLBACK-NOT: remark:{{.*}}(in function: afunc2) define <4 x i32> @afunc2(<4 x i16> %v0) nounwind { ; CHECK-LABEL: afunc2: ; CHECK-NEXT: sshll.4s v0, v0, #0 Index: llvm/trunk/test/CodeGen/AArch64/arm64-vabs.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/arm64-vabs.ll +++ llvm/trunk/test/CodeGen/AArch64/arm64-vabs.ll @@ -1,13 +1,11 @@ ; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s -; RUN: llc < %s -global-isel -global-isel-abort=2 -pass-remarks-missed=gisel* -mtriple=arm64-eabi -aarch64-neon-syntax=apple 2>&1 | FileCheck %s --check-prefixes=GISEL,FALLBACK +; RUN: llc < %s -global-isel -global-isel-abort=2 -pass-remarks-missed=gisel* -mtriple=arm64-eabi -aarch64-neon-syntax=apple 2>&1 | FileCheck %s --check-prefixes=FALLBACK,CHECK -; FALLBACK-NOT: remark:{{.*}}(<8 x s16>) = G_ZEXT %4:_(<8 x s8>) +; FALLBACK-NOT: remark:{{.*}} G_ZEXT ; FALLBACK-NOT: remark:{{.*}} sabdl8h define <8 x i16> @sabdl8h(<8 x i8>* %A, <8 x i8>* %B) nounwind { ;CHECK-LABEL: sabdl8h: ;CHECK: sabdl.8h -;GISEL-LABEL: sabdl8h: -;GISEL: sabdl.8h %tmp1 = load <8 x i8>, <8 x i8>* %A %tmp2 = load <8 x i8>, <8 x i8>* %B %tmp3 = call <8 x i8> @llvm.aarch64.neon.sabd.v8i8(<8 x i8> %tmp1, <8 x i8> %tmp2) @@ -15,6 +13,7 @@ ret <8 x i16> %tmp4 } +; FALLBACK-NOT: remark:{{.*}} sabdl4s define <4 x i32> @sabdl4s(<4 x i16>* %A, <4 x i16>* %B) nounwind { ;CHECK-LABEL: sabdl4s: ;CHECK: sabdl.4s @@ -25,6 +24,7 @@ ret <4 x i32> %tmp4 } +; FALLBACK-NOT: remark:{{.*}} sabdl2d define <2 x i64> @sabdl2d(<2 x i32>* %A, <2 x i32>* %B) nounwind { ;CHECK-LABEL: sabdl2d: ;CHECK: sabdl.2d @@ -71,6 +71,7 @@ ret <2 x i64> %tmp4 } +; FALLBACK-NOT: remark:{{.*}} uabdl8h) define <8 x i16> @uabdl8h(<8 x i8>* %A, <8 x i8>* %B) nounwind { ;CHECK-LABEL: uabdl8h: ;CHECK: uabdl.8h @@ -81,6 +82,7 @@ ret <8 x i16> %tmp4 } +; FALLBACK-NOT: remark:{{.*}} uabdl4s) define <4 x i32> @uabdl4s(<4 x i16>* %A, <4 x i16>* %B) nounwind { ;CHECK-LABEL: uabdl4s: ;CHECK: uabdl.4s @@ -91,6 +93,7 @@ ret <4 x i32> %tmp4 } +; FALLBACK-NOT: remark:{{.*}} uabdl2d) define <2 x i64> @uabdl2d(<2 x i32>* %A, <2 x i32>* %B) nounwind { ;CHECK-LABEL: uabdl2d: ;CHECK: uabdl.2d @@ -560,6 +563,7 @@ declare <1 x i64> @llvm.aarch64.neon.abs.v1i64(<1 x i64>) nounwind readnone declare i64 @llvm.aarch64.neon.abs.i64(i64) nounwind readnone +; FALLBACK-NOT: remark:{{.*}} sabal8h define <8 x i16> @sabal8h(<8 x i8>* %A, <8 x i8>* %B, <8 x i16>* %C) nounwind { ;CHECK-LABEL: sabal8h: ;CHECK: sabal.8h @@ -572,6 +576,7 @@ ret <8 x i16> %tmp5 } +; FALLBACK-NOT: remark:{{.*}} sabal4s define <4 x i32> @sabal4s(<4 x i16>* %A, <4 x i16>* %B, <4 x i32>* %C) nounwind { ;CHECK-LABEL: sabal4s: ;CHECK: sabal.4s @@ -584,6 +589,7 @@ ret <4 x i32> %tmp5 } +; FALLBACK-NOT: remark:{{.*}} sabal2d define <2 x i64> @sabal2d(<2 x i32>* %A, <2 x i32>* %B, <2 x i64>* %C) nounwind { ;CHECK-LABEL: sabal2d: ;CHECK: sabal.2d @@ -639,6 +645,7 @@ ret <2 x i64> %tmp5 } +; FALLBACK-NOT: remark:{{.*}} uabal8h define <8 x i16> @uabal8h(<8 x i8>* %A, <8 x i8>* %B, <8 x i16>* %C) nounwind { ;CHECK-LABEL: uabal8h: ;CHECK: uabal.8h @@ -651,6 +658,7 @@ ret <8 x i16> %tmp5 } +; FALLBACK-NOT: remark:{{.*}} uabal8s define <4 x i32> @uabal4s(<4 x i16>* %A, <4 x i16>* %B, <4 x i32>* %C) nounwind { ;CHECK-LABEL: uabal4s: ;CHECK: uabal.4s @@ -663,6 +671,7 @@ ret <4 x i32> %tmp5 } +; FALLBACK-NOT: remark:{{.*}} uabal2d define <2 x i64> @uabal2d(<2 x i32>* %A, <2 x i32>* %B, <2 x i64>* %C) nounwind { ;CHECK-LABEL: uabal2d: ;CHECK: uabal.2d