diff options
Diffstat (limited to 'test/CodeGen/AArch64')
145 files changed, 9783 insertions, 3550 deletions
diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-callingconv-ios.ll b/test/CodeGen/AArch64/GlobalISel/arm64-callingconv-ios.ll new file mode 100644 index 0000000000000..a70cee0efcb6c --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/arm64-callingconv-ios.ll @@ -0,0 +1,28 @@ +; RUN: llc -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s + +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-apple-ios9.0" + +; CHECK-LABEL: name: test_varargs +; CHECK: [[ANSWER:%[0-9]+]](s32) = G_CONSTANT i32 42 +; CHECK: [[D_ONE:%[0-9]+]](s64) = G_FCONSTANT double 1.000000e+00 +; CHECK: [[TWELVE:%[0-9]+]](s64) = G_CONSTANT i64 12 +; CHECK: [[THREE:%[0-9]+]](s8) = G_CONSTANT i8 3 +; CHECK: [[ONE:%[0-9]+]](s16) = G_CONSTANT i16 1 +; CHECK: [[FOUR:%[0-9]+]](s32) = G_CONSTANT i32 4 +; CHECK: [[F_ONE:%[0-9]+]](s32) = G_FCONSTANT float 1.000000e+00 +; CHECK: [[TWO:%[0-9]+]](s64) = G_FCONSTANT double 2.000000e+00 + +; CHECK: %w0 = COPY [[ANSWER]] +; CHECK: %d0 = COPY [[D_ONE]] +; CHECK: %x1 = COPY [[TWELVE]] +; CHECK: G_STORE [[THREE]](s8), {{%[0-9]+}}(p0) :: (store 1 into stack, align 0) +; CHECK: G_STORE [[ONE]](s16), {{%[0-9]+}}(p0) :: (store 2 into stack + 8, align 0) +; CHECK: G_STORE [[FOUR]](s32), {{%[0-9]+}}(p0) :: (store 4 into stack + 16, align 0) +; CHECK: G_STORE [[F_ONE]](s32), {{%[0-9]+}}(p0) :: (store 4 into stack + 24, align 0) +; CHECK: G_STORE [[TWO]](s64), {{%[0-9]+}}(p0) :: (store 8 into stack + 32, align 0) +declare void @varargs(i32, double, i64, ...) +define void @test_varargs() { + call void(i32, double, i64, ...) @varargs(i32 42, double 1.0, i64 12, i8 3, i16 1, i32 4, float 1.0, double 2.0) + ret void +} diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-callingconv.ll b/test/CodeGen/AArch64/GlobalISel/arm64-callingconv.ll index 95b2ea2b4ffc1..59b9bb49f0ee0 100644 --- a/test/CodeGen/AArch64/GlobalISel/arm64-callingconv.ll +++ b/test/CodeGen/AArch64/GlobalISel/arm64-callingconv.ll @@ -56,3 +56,41 @@ define i8* @args_ptrs(i8* %x0, i16* %x1, <2 x i8>* %x2, {i8, i16, i32}* %x3, define [1 x double] @args_arr([1 x double] %d0) { ret [1 x double] %d0 } + +; CHECK-LABEL: name: test_varargs +; CHECK: [[ANSWER:%[0-9]+]](s32) = G_CONSTANT i32 42 +; CHECK: [[D_ONE:%[0-9]+]](s64) = G_FCONSTANT double 1.000000e+00 +; CHECK: [[TWELVE:%[0-9]+]](s64) = G_CONSTANT i64 12 +; CHECK: [[THREE:%[0-9]+]](s8) = G_CONSTANT i8 3 +; CHECK: [[ONE:%[0-9]+]](s16) = G_CONSTANT i16 1 +; CHECK: [[FOUR:%[0-9]+]](s32) = G_CONSTANT i32 4 +; CHECK: [[F_ONE:%[0-9]+]](s32) = G_FCONSTANT float 1.000000e+00 +; CHECK: [[TWO:%[0-9]+]](s64) = G_FCONSTANT double 2.000000e+00 + +; CHECK: %w0 = COPY [[ANSWER]] +; CHECK: %d0 = COPY [[D_ONE]] +; CHECK: %x1 = COPY [[TWELVE]] +; CHECK: %w2 = COPY [[THREE]](s8) +; CHECK: %w3 = COPY [[ONE]](s16) +; CHECK: %w4 = COPY [[FOUR]](s32) +; CHECK: %s1 = COPY [[F_ONE]](s32) +; CHECK: %d2 = COPY [[TWO]](s64) +declare void @varargs(i32, double, i64, ...) +define void @test_varargs() { + call void(i32, double, i64, ...) @varargs(i32 42, double 1.0, i64 12, i8 3, i16 1, i32 4, float 1.0, double 2.0) + ret void +} + +; signext/zeroext parameters on the stack: not part of any real ABI as far as I +; know, but ELF currently allocates 8 bytes for a signext parameter on the +; stack. The ADJCALLSTACK ops should reflect this, even if the difference is +; theoretical. +declare void @stack_ext_needed([8 x i64], i8 signext %in) +; CHECK-LABEL: name: test_stack_ext_needed +; CHECK: ADJCALLSTACKDOWN 8 +; CHECK: BL @stack_ext_needed +; CHECK: ADJCALLSTACKUP 8 +define void @test_stack_ext_needed() { + call void @stack_ext_needed([8 x i64] undef, i8 signext 42) + ret void +} diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll b/test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll index 8d1dbc246e6ad..e40199d82c9dd 100644 --- a/test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll +++ b/test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll @@ -1,6 +1,6 @@ ; RUN: not llc -O0 -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefix=ERROR ; RUN: llc -O0 -global-isel -global-isel-abort=0 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefix=FALLBACK -; RUN: llc -O0 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o %t.out 2> %t.err +; RUN: llc -O0 -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' -verify-machineinstrs %s -o %t.out 2> %t.err ; RUN: FileCheck %s --check-prefix=FALLBACK-WITH-REPORT-OUT < %t.out ; RUN: FileCheck %s --check-prefix=FALLBACK-WITH-REPORT-ERR < %t.err ; This file checks that the fallback path to selection dag works. @@ -14,10 +14,11 @@ target triple = "aarch64--" ; We use __fixunstfti as the common denominator for __fixunstfti on Linux and ; ___fixunstfti on iOS -; ERROR: Unable to lower arguments +; ERROR: unable to lower arguments: i128 (i128)* (in function: ABIi128) ; FALLBACK: ldr q0, ; FALLBACK-NEXT: bl __fixunstfti ; +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to lower arguments: i128 (i128)* (in function: ABIi128) ; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for ABIi128 ; FALLBACK-WITH-REPORT-OUT-LABEL: ABIi128: ; FALLBACK-WITH-REPORT-OUT: ldr q0, @@ -31,6 +32,7 @@ define i128 @ABIi128(i128 %arg1) { ; It happens that we don't handle ConstantArray instances yet during ; translation. Any other constant would be fine too. +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to translate constant: [1 x double] (in function: constant) ; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for constant ; FALLBACK-WITH-REPORT-OUT-LABEL: constant: ; FALLBACK-WITH-REPORT-OUT: fmov d0, #1.0 @@ -41,6 +43,7 @@ define [1 x double] @constant() { ; The key problem here is that we may fail to create an MBB referenced by a ; PHI. If so, we cannot complete the G_PHI and mustn't try or bad things ; happen. +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: cannot select: G_STORE %vreg4, %vreg2; mem:ST4[%addr] GPR:%vreg4,%vreg2 (in function: pending_phis) ; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for pending_phis ; FALLBACK-WITH-REPORT-OUT-LABEL: pending_phis: define i32 @pending_phis(i1 %tst, i32 %val, i32* %addr) { @@ -60,6 +63,7 @@ false: } ; General legalizer inability to handle types whose size wasn't a power of 2. +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %vreg1<def>(s42) = G_LOAD %vreg0; mem:LD6[%addr](align=8) (in function: odd_type) ; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for odd_type ; FALLBACK-WITH-REPORT-OUT-LABEL: odd_type: define void @odd_type(i42* %addr) { @@ -67,8 +71,17 @@ define void @odd_type(i42* %addr) { ret void } +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %vreg1<def>(<7 x s32>) = G_LOAD %vreg0; mem:LD28[%addr](align=32) (in function: odd_vector) +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for odd_vector +; FALLBACK-WITH-REPORT-OUT-LABEL: odd_vector: +define void @odd_vector(<7 x i32>* %addr) { + %vec = load <7 x i32>, <7 x i32>* %addr + ret void +} + ; RegBankSelect crashed when given invalid mappings, and AArch64's ; implementation produce valid-but-nonsense mappings for G_SEQUENCE. +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to map instruction ; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for sequence_mapping ; FALLBACK-WITH-REPORT-OUT-LABEL: sequence_mapping: define void @sequence_mapping([2 x i64] %in) { @@ -76,42 +89,68 @@ define void @sequence_mapping([2 x i64] %in) { } ; Legalizer was asserting when it enountered an unexpected default action. +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to map instruction ; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for legal_default ; FALLBACK-WITH-REPORT-LABEL: legal_default: -define void @legal_default(i64 %in) { - insertvalue [2 x i64] undef, i64 %in, 0 +define void @legal_default([8 x i8] %in) { + insertvalue { [4 x i8], [8 x i8], [4 x i8] } undef, [8 x i8] %in, 1 ret void } -; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for debug_insts -; FALLBACK-WITH-REPORT-LABEL: debug_insts: -define void @debug_insts(i32 %in) #0 !dbg !7 { -entry: - %in.addr = alloca i32, align 4 - store i32 %in, i32* %in.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %in.addr, metadata !11, metadata !12), !dbg !13 - ret void, !dbg !14 + ; AArch64 was asserting instead of returning an invalid mapping for unknown + ; sizes. +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to translate instruction: ret: ' ret i128 undef' (in function: sequence_sizes) +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for sequence_sizes +; FALLBACK-WITH-REPORT-LABEL: sequence_sizes: +define i128 @sequence_sizes([8 x i8] %in) { + ret i128 undef +} + +; Just to make sure we don't accidentally emit a normal load/store. +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: cannot select: %vreg2<def>(s64) = G_LOAD %vreg0; mem:LD8[%addr] GPR:%vreg2,%vreg0 (in function: atomic_ops) +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for atomic_ops +; FALLBACK-WITH-REPORT-LABEL: atomic_ops: +define i64 @atomic_ops(i64* %addr) { + store atomic i64 0, i64* %addr unordered, align 8 + %res = load atomic i64, i64* %addr seq_cst, align 8 + ret i64 %res +} + +; Make sure we don't mess up metadata arguments. +declare void @llvm.write_register.i64(metadata, i64) + +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' call void @llvm.write_register.i64(metadata !0, i64 0)' (in function: test_write_register_intrin) +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for test_write_register_intrin +; FALLBACK-WITH-REPORT-LABEL: test_write_register_intrin: +define void @test_write_register_intrin() { + call void @llvm.write_register.i64(metadata !{!"sp"}, i64 0) + ret void } -; Function Attrs: nounwind readnone -declare void @llvm.dbg.declare(metadata, metadata, metadata) - -!llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!3, !4, !5} -!llvm.ident = !{!6} - -!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 289075) (llvm/trunk 289080)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) -!1 = !DIFile(filename: "tmp.c", directory: "/Users/tim/llvm/build") -!2 = !{} -!3 = !{i32 2, !"Dwarf Version", i32 4} -!4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = !{i32 1, !"PIC Level", i32 2} -!6 = !{!"clang version 4.0.0 (trunk 289075) (llvm/trunk 289080)"} -!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) -!8 = !DISubroutineType(types: !9) -!9 = !{null, !10} -!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!11 = !DILocalVariable(name: "in", arg: 1, scope: !7, file: !1, line: 1, type: !10) -!12 = !DIExpression() -!13 = !DILocation(line: 1, column: 14, scope: !7) -!14 = !DILocation(line: 2, column: 1, scope: !7) +@_ZTIi = external global i8* +declare i32 @__gxx_personality_v0(...) + +; Check that we fallback on invoke translation failures. +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to translate instruction: invoke: ' invoke void %callee(i128 0) +; FALLBACK-WITH-REPORT-NEXT: to label %continue unwind label %broken' (in function: invoke_weird_type) +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for invoke_weird_type +; FALLBACK-WITH-REPORT-OUT-LABEL: invoke_weird_type: +define void @invoke_weird_type(void(i128)* %callee) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { + invoke void %callee(i128 0) + to label %continue unwind label %broken + +broken: + landingpad { i8*, i32 } catch i8* bitcast(i8** @_ZTIi to i8*) + ret void + +continue: + ret void +} + +; Check that we fallback on invoke translation failures. +; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %vreg0<def>(s128) = G_FCONSTANT quad 2 +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for test_quad_dump +; FALLBACK-WITH-REPORT-OUT-LABEL: test_quad_dump: +define fp128 @test_quad_dump() { + ret fp128 0xL00000000000000004000000000000000 +} diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir b/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir deleted file mode 100644 index ece5a858b49c7..0000000000000 --- a/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir +++ /dev/null @@ -1,2979 +0,0 @@ -# RUN: llc -O0 -mtriple=aarch64-apple-ios -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=IOS -# RUN: llc -O0 -mtriple=aarch64-linux-gnu -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=LINUX-DEFAULT -# RUN: llc -O0 -mtriple=aarch64-linux-gnu -relocation-model=pic -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=LINUX-PIC - -# Test the instruction selector. -# As we support more instructions, we need to split this up. - ---- | - target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" - - define void @add_s8_gpr() { ret void } - define void @add_s16_gpr() { ret void } - define void @add_s32_gpr() { ret void } - define void @add_s64_gpr() { ret void } - - define void @sub_s8_gpr() { ret void } - define void @sub_s16_gpr() { ret void } - define void @sub_s32_gpr() { ret void } - define void @sub_s64_gpr() { ret void } - - define void @or_s1_gpr() { ret void } - define void @or_s16_gpr() { ret void } - define void @or_s32_gpr() { ret void } - define void @or_s64_gpr() { ret void } - define void @or_v2s32_fpr() { ret void } - - define void @xor_s8_gpr() { ret void } - define void @xor_s16_gpr() { ret void } - define void @xor_s32_gpr() { ret void } - define void @xor_s64_gpr() { ret void } - - define void @and_s8_gpr() { ret void } - define void @and_s16_gpr() { ret void } - define void @and_s32_gpr() { ret void } - define void @and_s64_gpr() { ret void } - - define void @shl_s8_gpr() { ret void } - define void @shl_s16_gpr() { ret void } - define void @shl_s32_gpr() { ret void } - define void @shl_s64_gpr() { ret void } - - define void @lshr_s32_gpr() { ret void } - define void @lshr_s64_gpr() { ret void } - - define void @ashr_s32_gpr() { ret void } - define void @ashr_s64_gpr() { ret void } - - define void @mul_s8_gpr() { ret void } - define void @mul_s16_gpr() { ret void } - define void @mul_s32_gpr() { ret void } - define void @mul_s64_gpr() { ret void } - - define void @sdiv_s32_gpr() { ret void } - define void @sdiv_s64_gpr() { ret void } - - define void @udiv_s32_gpr() { ret void } - define void @udiv_s64_gpr() { ret void } - - define void @fadd_s32_gpr() { ret void } - define void @fadd_s64_gpr() { ret void } - - define void @fsub_s32_gpr() { ret void } - define void @fsub_s64_gpr() { ret void } - - define void @fmul_s32_gpr() { ret void } - define void @fmul_s64_gpr() { ret void } - - define void @fdiv_s32_gpr() { ret void } - define void @fdiv_s64_gpr() { ret void } - - define void @sitofp_s32_s32_fpr() { ret void } - define void @sitofp_s32_s64_fpr() { ret void } - define void @sitofp_s64_s32_fpr() { ret void } - define void @sitofp_s64_s64_fpr() { ret void } - - define void @uitofp_s32_s32_fpr() { ret void } - define void @uitofp_s32_s64_fpr() { ret void } - define void @uitofp_s64_s32_fpr() { ret void } - define void @uitofp_s64_s64_fpr() { ret void } - - define void @fptosi_s32_s32_gpr() { ret void } - define void @fptosi_s32_s64_gpr() { ret void } - define void @fptosi_s64_s32_gpr() { ret void } - define void @fptosi_s64_s64_gpr() { ret void } - - define void @fptoui_s32_s32_gpr() { ret void } - define void @fptoui_s32_s64_gpr() { ret void } - define void @fptoui_s64_s32_gpr() { ret void } - define void @fptoui_s64_s64_gpr() { ret void } - - define void @fptrunc() { ret void } - define void @fpext() { ret void } - - define void @unconditional_br() { ret void } - define void @conditional_br() { ret void } - - define void @load_s64_gpr(i64* %addr) { ret void } - define void @load_s32_gpr(i32* %addr) { ret void } - define void @load_s16_gpr(i16* %addr) { ret void } - define void @load_s8_gpr(i8* %addr) { ret void } - define void @load_s64_fpr(i64* %addr) { ret void } - define void @load_s32_fpr(i32* %addr) { ret void } - define void @load_s16_fpr(i16* %addr) { ret void } - define void @load_s8_fpr(i8* %addr) { ret void } - - define void @store_s64_gpr(i64* %addr) { ret void } - define void @store_s32_gpr(i32* %addr) { ret void } - define void @store_s16_gpr(i16* %addr) { ret void } - define void @store_s8_gpr(i8* %addr) { ret void } - define void @store_s64_fpr(i64* %addr) { ret void } - define void @store_s32_fpr(i32* %addr) { ret void } - - define void @frame_index() { - %ptr0 = alloca i64 - ret void - } - - define void @selected_property() { ret void } - - define i32 @const_s32() { ret i32 42 } - define i64 @const_s64() { ret i64 1234567890123 } - - define i32 @fconst_s32() { ret i32 42 } - define i64 @fconst_s64() { ret i64 1234567890123 } - - define i8* @gep(i8* %in) { ret i8* undef } - - @var_local = global i8 0 - define i8* @global_local() { ret i8* undef } - - @var_got = external global i8 - define i8* @global_got() { ret i8* undef } - - define void @trunc() { ret void } - - define void @anyext_gpr() { ret void } - define void @zext_gpr() { ret void } - define void @sext_gpr() { ret void } - - define void @casts() { ret void } - - define void @bitcast_s32_gpr() { ret void } - define void @bitcast_s32_fpr() { ret void } - define void @bitcast_s32_gpr_fpr() { ret void } - define void @bitcast_s32_fpr_gpr() { ret void } - define void @bitcast_s64_gpr() { ret void } - define void @bitcast_s64_fpr() { ret void } - define void @bitcast_s64_gpr_fpr() { ret void } - define void @bitcast_s64_fpr_gpr() { ret void } - - define void @icmp() { ret void } - define void @fcmp() { ret void } - - define void @phi() { ret void } - - define void @select() { ret void } -... - ---- -# CHECK-LABEL: name: add_s8_gpr -name: add_s8_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = ADDWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s8) = COPY %w0 - %1(s8) = COPY %w1 - %2(s8) = G_ADD %0, %1 -... - ---- -# CHECK-LABEL: name: add_s16_gpr -name: add_s16_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = ADDWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s16) = COPY %w0 - %1(s16) = COPY %w1 - %2(s16) = G_ADD %0, %1 -... - ---- -# Check that we select a 32-bit GPR G_ADD into ADDWrr on GPR32. -# Also check that we constrain the register class of the COPY to GPR32. -# CHECK-LABEL: name: add_s32_gpr -name: add_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = ADDWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_ADD %0, %1 -... - ---- -# Same as add_s32_gpr, for 64-bit operations. -# CHECK-LABEL: name: add_s64_gpr -name: add_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = ADDXrr %0, %1 -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_ADD %0, %1 -... - ---- -# CHECK-LABEL: name: sub_s8_gpr -name: sub_s8_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = SUBWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s8) = COPY %w0 - %1(s8) = COPY %w1 - %2(s8) = G_SUB %0, %1 -... - ---- -# CHECK-LABEL: name: sub_s16_gpr -name: sub_s16_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = SUBWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s16) = COPY %w0 - %1(s16) = COPY %w1 - %2(s16) = G_SUB %0, %1 -... - ---- -# Same as add_s32_gpr, for G_SUB operations. -# CHECK-LABEL: name: sub_s32_gpr -name: sub_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = SUBWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_SUB %0, %1 -... - ---- -# Same as add_s64_gpr, for G_SUB operations. -# CHECK-LABEL: name: sub_s64_gpr -name: sub_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = SUBXrr %0, %1 -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_SUB %0, %1 -... - ---- -# CHECK-LABEL: name: or_s1_gpr -name: or_s1_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = ORRWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s1) = COPY %w0 - %1(s1) = COPY %w1 - %2(s1) = G_OR %0, %1 -... - ---- -# CHECK-LABEL: name: or_s16_gpr -name: or_s16_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = ORRWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s16) = COPY %w0 - %1(s16) = COPY %w1 - %2(s16) = G_OR %0, %1 -... - ---- -# Same as add_s32_gpr, for G_OR operations. -# CHECK-LABEL: name: or_s32_gpr -name: or_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = ORRWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_OR %0, %1 -... - ---- -# Same as add_s64_gpr, for G_OR operations. -# CHECK-LABEL: name: or_s64_gpr -name: or_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = ORRXrr %0, %1 -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_OR %0, %1 -... - ---- -# 64-bit G_OR on vector registers. -# CHECK-LABEL: name: or_v2s32_fpr -name: or_v2s32_fpr -legalized: true -regBankSelected: true -# -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr64 } -# CHECK-NEXT: - { id: 1, class: fpr64 } -# CHECK-NEXT: - { id: 2, class: fpr64 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = COPY %d1 -# The actual OR does not matter as long as it is operating -# on 64-bit width vector. -# CHECK: %2 = ORRv8i8 %0, %1 -body: | - bb.0: - liveins: %d0, %d1 - - %0(<2 x s32>) = COPY %d0 - %1(<2 x s32>) = COPY %d1 - %2(<2 x s32>) = G_OR %0, %1 -... - ---- -# CHECK-LABEL: name: xor_s8_gpr -name: xor_s8_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = EORWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s8) = COPY %w0 - %1(s8) = COPY %w1 - %2(s8) = G_XOR %0, %1 -... - ---- -# CHECK-LABEL: name: xor_s16_gpr -name: xor_s16_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = EORWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s16) = COPY %w0 - %1(s16) = COPY %w1 - %2(s16) = G_XOR %0, %1 -... - ---- -# Same as add_s32_gpr, for G_XOR operations. -# CHECK-LABEL: name: xor_s32_gpr -name: xor_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = EORWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_XOR %0, %1 -... - ---- -# Same as add_s64_gpr, for G_XOR operations. -# CHECK-LABEL: name: xor_s64_gpr -name: xor_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = EORXrr %0, %1 -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_XOR %0, %1 -... - ---- -# CHECK-LABEL: name: and_s8_gpr -name: and_s8_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = ANDWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s8) = COPY %w0 - %1(s8) = COPY %w1 - %2(s8) = G_AND %0, %1 -... - ---- -# CHECK-LABEL: name: and_s16_gpr -name: and_s16_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = ANDWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s16) = COPY %w0 - %1(s16) = COPY %w1 - %2(s16) = G_AND %0, %1 -... - ---- -# Same as add_s32_gpr, for G_AND operations. -# CHECK-LABEL: name: and_s32_gpr -name: and_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = ANDWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_AND %0, %1 -... - ---- -# Same as add_s64_gpr, for G_AND operations. -# CHECK-LABEL: name: and_s64_gpr -name: and_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = ANDXrr %0, %1 -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_AND %0, %1 -... - ---- -# CHECK-LABEL: name: shl_s8_gpr -name: shl_s8_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = LSLVWr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s8) = COPY %w0 - %1(s8) = COPY %w1 - %2(s8) = G_SHL %0, %1 -... - ---- -# CHECK-LABEL: name: shl_s16_gpr -name: shl_s16_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = LSLVWr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s16) = COPY %w0 - %1(s16) = COPY %w1 - %2(s16) = G_SHL %0, %1 -... - ---- -# Same as add_s32_gpr, for G_SHL operations. -# CHECK-LABEL: name: shl_s32_gpr -name: shl_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = LSLVWr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_SHL %0, %1 -... - ---- -# Same as add_s64_gpr, for G_SHL operations. -# CHECK-LABEL: name: shl_s64_gpr -name: shl_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = LSLVXr %0, %1 -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_SHL %0, %1 -... - ---- -# Same as add_s32_gpr, for G_LSHR operations. -# CHECK-LABEL: name: lshr_s32_gpr -name: lshr_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = LSRVWr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_LSHR %0, %1 -... - ---- -# Same as add_s64_gpr, for G_LSHR operations. -# CHECK-LABEL: name: lshr_s64_gpr -name: lshr_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = LSRVXr %0, %1 -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_LSHR %0, %1 -... - ---- -# Same as add_s32_gpr, for G_ASHR operations. -# CHECK-LABEL: name: ashr_s32_gpr -name: ashr_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = ASRVWr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_ASHR %0, %1 -... - ---- -# Same as add_s64_gpr, for G_ASHR operations. -# CHECK-LABEL: name: ashr_s64_gpr -name: ashr_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = ASRVXr %0, %1 -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_ASHR %0, %1 -... - ---- -# CHECK-LABEL: name: mul_s8_gpr -name: mul_s8_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = MADDWrrr %0, %1, %wzr -body: | - bb.0: - liveins: %w0, %w1 - - %0(s8) = COPY %w0 - %1(s8) = COPY %w1 - %2(s8) = G_MUL %0, %1 -... - ---- -# CHECK-LABEL: name: mul_s16_gpr -name: mul_s16_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = MADDWrrr %0, %1, %wzr -body: | - bb.0: - liveins: %w0, %w1 - - %0(s16) = COPY %w0 - %1(s16) = COPY %w1 - %2(s16) = G_MUL %0, %1 -... - ---- -# Check that we select s32 GPR G_MUL. This is trickier than other binops because -# there is only MADDWrrr, and we have to use the WZR physreg. -# CHECK-LABEL: name: mul_s32_gpr -name: mul_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = MADDWrrr %0, %1, %wzr -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_MUL %0, %1 -... - ---- -# Same as mul_s32_gpr for the s64 type. -# CHECK-LABEL: name: mul_s64_gpr -name: mul_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = MADDXrrr %0, %1, %xzr -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_MUL %0, %1 -... - ---- -# Same as add_s32_gpr, for G_SDIV operations. -# CHECK-LABEL: name: sdiv_s32_gpr -name: sdiv_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = SDIVWr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_SDIV %0, %1 -... - ---- -# Same as add_s64_gpr, for G_SDIV operations. -# CHECK-LABEL: name: sdiv_s64_gpr -name: sdiv_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = SDIVXr %0, %1 -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_SDIV %0, %1 -... - ---- -# Same as add_s32_gpr, for G_UDIV operations. -# CHECK-LABEL: name: udiv_s32_gpr -name: udiv_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = UDIVWr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_UDIV %0, %1 -... - ---- -# Same as add_s64_gpr, for G_UDIV operations. -# CHECK-LABEL: name: udiv_s64_gpr -name: udiv_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = UDIVXr %0, %1 -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_UDIV %0, %1 -... - ---- -# Check that we select a s32 FPR G_FADD into FADDSrr. -# CHECK-LABEL: name: fadd_s32_gpr -name: fadd_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: fpr32 } -# CHECK-NEXT: - { id: 2, class: fpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %s0 -# CHECK: %1 = COPY %s1 -# CHECK: %2 = FADDSrr %0, %1 -body: | - bb.0: - liveins: %s0, %s1 - - %0(s32) = COPY %s0 - %1(s32) = COPY %s1 - %2(s32) = G_FADD %0, %1 -... - ---- -# CHECK-LABEL: name: fadd_s64_gpr -name: fadd_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr64 } -# CHECK-NEXT: - { id: 1, class: fpr64 } -# CHECK-NEXT: - { id: 2, class: fpr64 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = COPY %d1 -# CHECK: %2 = FADDDrr %0, %1 -body: | - bb.0: - liveins: %d0, %d1 - - %0(s64) = COPY %d0 - %1(s64) = COPY %d1 - %2(s64) = G_FADD %0, %1 -... - ---- -# CHECK-LABEL: name: fsub_s32_gpr -name: fsub_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: fpr32 } -# CHECK-NEXT: - { id: 2, class: fpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %s0 -# CHECK: %1 = COPY %s1 -# CHECK: %2 = FSUBSrr %0, %1 -body: | - bb.0: - liveins: %s0, %s1 - - %0(s32) = COPY %s0 - %1(s32) = COPY %s1 - %2(s32) = G_FSUB %0, %1 -... - ---- -# CHECK-LABEL: name: fsub_s64_gpr -name: fsub_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr64 } -# CHECK-NEXT: - { id: 1, class: fpr64 } -# CHECK-NEXT: - { id: 2, class: fpr64 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = COPY %d1 -# CHECK: %2 = FSUBDrr %0, %1 -body: | - bb.0: - liveins: %d0, %d1 - - %0(s64) = COPY %d0 - %1(s64) = COPY %d1 - %2(s64) = G_FSUB %0, %1 -... - ---- -# CHECK-LABEL: name: fmul_s32_gpr -name: fmul_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: fpr32 } -# CHECK-NEXT: - { id: 2, class: fpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %s0 -# CHECK: %1 = COPY %s1 -# CHECK: %2 = FMULSrr %0, %1 -body: | - bb.0: - liveins: %s0, %s1 - - %0(s32) = COPY %s0 - %1(s32) = COPY %s1 - %2(s32) = G_FMUL %0, %1 -... - ---- -# CHECK-LABEL: name: fmul_s64_gpr -name: fmul_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr64 } -# CHECK-NEXT: - { id: 1, class: fpr64 } -# CHECK-NEXT: - { id: 2, class: fpr64 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = COPY %d1 -# CHECK: %2 = FMULDrr %0, %1 -body: | - bb.0: - liveins: %d0, %d1 - - %0(s64) = COPY %d0 - %1(s64) = COPY %d1 - %2(s64) = G_FMUL %0, %1 -... - ---- -# CHECK-LABEL: name: fdiv_s32_gpr -name: fdiv_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: fpr32 } -# CHECK-NEXT: - { id: 2, class: fpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %s0 -# CHECK: %1 = COPY %s1 -# CHECK: %2 = FDIVSrr %0, %1 -body: | - bb.0: - liveins: %s0, %s1 - - %0(s32) = COPY %s0 - %1(s32) = COPY %s1 - %2(s32) = G_FDIV %0, %1 -... - ---- -# CHECK-LABEL: name: fdiv_s64_gpr -name: fdiv_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr64 } -# CHECK-NEXT: - { id: 1, class: fpr64 } -# CHECK-NEXT: - { id: 2, class: fpr64 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - - { id: 2, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = COPY %d1 -# CHECK: %2 = FDIVDrr %0, %1 -body: | - bb.0: - liveins: %d0, %d1 - - %0(s64) = COPY %d0 - %1(s64) = COPY %d1 - %2(s64) = G_FDIV %0, %1 -... - ---- -# CHECK-LABEL: name: sitofp_s32_s32_fpr -name: sitofp_s32_s32_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: fpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = SCVTFUWSri %0 -body: | - bb.0: - liveins: %w0 - - %0(s32) = COPY %w0 - %1(s32) = G_SITOFP %0 -... - ---- -# CHECK-LABEL: name: sitofp_s32_s64_fpr -name: sitofp_s32_s64_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: fpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = SCVTFUXSri %0 -body: | - bb.0: - liveins: %x0 - - %0(s64) = COPY %x0 - %1(s32) = G_SITOFP %0 -... - ---- -# CHECK-LABEL: name: sitofp_s64_s32_fpr -name: sitofp_s64_s32_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: fpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = SCVTFUWDri %0 -body: | - bb.0: - liveins: %w0 - - %0(s32) = COPY %w0 - %1(s64) = G_SITOFP %0 -... - ---- -# CHECK-LABEL: name: sitofp_s64_s64_fpr -name: sitofp_s64_s64_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: fpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = SCVTFUXDri %0 -body: | - bb.0: - liveins: %x0 - - %0(s64) = COPY %x0 - %1(s64) = G_SITOFP %0 -... - ---- -# CHECK-LABEL: name: uitofp_s32_s32_fpr -name: uitofp_s32_s32_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: fpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = UCVTFUWSri %0 -body: | - bb.0: - liveins: %w0 - - %0(s32) = COPY %w0 - %1(s32) = G_UITOFP %0 -... - ---- -# CHECK-LABEL: name: uitofp_s32_s64_fpr -name: uitofp_s32_s64_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: fpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = UCVTFUXSri %0 -body: | - bb.0: - liveins: %x0 - - %0(s64) = COPY %x0 - %1(s32) = G_UITOFP %0 -... - ---- -# CHECK-LABEL: name: uitofp_s64_s32_fpr -name: uitofp_s64_s32_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: fpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = UCVTFUWDri %0 -body: | - bb.0: - liveins: %w0 - - %0(s32) = COPY %w0 - %1(s64) = G_UITOFP %0 -... - ---- -# CHECK-LABEL: name: uitofp_s64_s64_fpr -name: uitofp_s64_s64_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: fpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = UCVTFUXDri %0 -body: | - bb.0: - liveins: %x0 - - %0(s64) = COPY %x0 - %1(s64) = G_UITOFP %0 -... - ---- -# CHECK-LABEL: name: fptosi_s32_s32_gpr -name: fptosi_s32_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %s0 -# CHECK: %1 = FCVTZSUWSr %0 -body: | - bb.0: - liveins: %s0 - - %0(s32) = COPY %s0 - %1(s32) = G_FPTOSI %0 -... - ---- -# CHECK-LABEL: name: fptosi_s32_s64_gpr -name: fptosi_s32_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr64 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = FCVTZSUWDr %0 -body: | - bb.0: - liveins: %d0 - - %0(s64) = COPY %d0 - %1(s32) = G_FPTOSI %0 -... - ---- -# CHECK-LABEL: name: fptosi_s64_s32_gpr -name: fptosi_s64_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %s0 -# CHECK: %1 = FCVTZSUXSr %0 -body: | - bb.0: - liveins: %s0 - - %0(s32) = COPY %s0 - %1(s64) = G_FPTOSI %0 -... - ---- -# CHECK-LABEL: name: fptosi_s64_s64_gpr -name: fptosi_s64_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = FCVTZSUXDr %0 -body: | - bb.0: - liveins: %d0 - - %0(s64) = COPY %d0 - %1(s64) = G_FPTOSI %0 -... - ---- -# CHECK-LABEL: name: fptoui_s32_s32_gpr -name: fptoui_s32_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %s0 -# CHECK: %1 = FCVTZUUWSr %0 -body: | - bb.0: - liveins: %s0 - - %0(s32) = COPY %s0 - %1(s32) = G_FPTOUI %0 -... - ---- -# CHECK-LABEL: name: fptoui_s32_s64_gpr -name: fptoui_s32_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr64 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = FCVTZUUWDr %0 -body: | - bb.0: - liveins: %d0 - - %0(s64) = COPY %d0 - %1(s32) = G_FPTOUI %0 -... - ---- -# CHECK-LABEL: name: fptoui_s64_s32_gpr -name: fptoui_s64_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %s0 -# CHECK: %1 = FCVTZUUXSr %0 -body: | - bb.0: - liveins: %s0 - - %0(s32) = COPY %s0 - %1(s64) = G_FPTOUI %0 -... - ---- -# CHECK-LABEL: name: fptoui_s64_s64_gpr -name: fptoui_s64_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = FCVTZUUXDr %0 -body: | - bb.0: - liveins: %d0 - - %0(s64) = COPY %d0 - %1(s64) = G_FPTOUI %0 -... - ---- -# CHECK-LABEL: name: fptrunc -name: fptrunc -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK: - { id: 0, class: fpr64 } -# CHECK: - { id: 1, class: fpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = FCVTSDr %0 -body: | - bb.0: - liveins: %d0 - - %0(s64) = COPY %d0 - %1(s32) = G_FPTRUNC %0 -... - ---- -# CHECK-LABEL: name: fpext -name: fpext -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK: - { id: 0, class: fpr32 } -# CHECK: - { id: 1, class: fpr64 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %s0 -# CHECK: %1 = FCVTDSr %0 -body: | - bb.0: - liveins: %d0 - - %0(s32) = COPY %s0 - %1(s64) = G_FPEXT %0 -... - ---- -# CHECK-LABEL: name: unconditional_br -name: unconditional_br -legalized: true -regBankSelected: true - -# CHECK: body: -# CHECK: bb.0: -# CHECK: successors: %bb.0 -# CHECK: B %bb.0 -body: | - bb.0: - successors: %bb.0 - - G_BR %bb.0 -... - ---- -# CHECK-LABEL: name: conditional_br -name: conditional_br -legalized: true -regBankSelected: true - -registers: - - { id: 0, class: gpr } - -# CHECK: body: -# CHECK: bb.0: -# CHECK: TBNZW %0, 0, %bb.1 -# CHECK: B %bb.0 -body: | - bb.0: - successors: %bb.0, %bb.1 - %0(s1) = COPY %w0 - G_BRCOND %0(s1), %bb.1 - G_BR %bb.0 - - bb.1: -... - ---- -# CHECK-LABEL: name: load_s64_gpr -name: load_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = LDRXui %0, 0 :: (load 8 from %ir.addr) -body: | - bb.0: - liveins: %x0 - - %0(p0) = COPY %x0 - %1(s64) = G_LOAD %0 :: (load 8 from %ir.addr) - -... - ---- -# CHECK-LABEL: name: load_s32_gpr -name: load_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = LDRWui %0, 0 :: (load 4 from %ir.addr) -body: | - bb.0: - liveins: %x0 - - %0(p0) = COPY %x0 - %1(s32) = G_LOAD %0 :: (load 4 from %ir.addr) - -... - ---- -# CHECK-LABEL: name: load_s16_gpr -name: load_s16_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = LDRHHui %0, 0 :: (load 2 from %ir.addr) -body: | - bb.0: - liveins: %x0 - - %0(p0) = COPY %x0 - %1(s16) = G_LOAD %0 :: (load 2 from %ir.addr) - -... - ---- -# CHECK-LABEL: name: load_s8_gpr -name: load_s8_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = LDRBBui %0, 0 :: (load 1 from %ir.addr) -body: | - bb.0: - liveins: %x0 - - %0(p0) = COPY %x0 - %1(s8) = G_LOAD %0 :: (load 1 from %ir.addr) - -... - ---- -# CHECK-LABEL: name: load_s64_fpr -name: load_s64_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: fpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = LDRDui %0, 0 :: (load 8 from %ir.addr) -body: | - bb.0: - liveins: %x0 - - %0(p0) = COPY %x0 - %1(s64) = G_LOAD %0 :: (load 8 from %ir.addr) - -... - ---- -# CHECK-LABEL: name: load_s32_fpr -name: load_s32_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: fpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = LDRSui %0, 0 :: (load 4 from %ir.addr) -body: | - bb.0: - liveins: %x0 - - %0(p0) = COPY %x0 - %1(s32) = G_LOAD %0 :: (load 4 from %ir.addr) - -... - ---- -# CHECK-LABEL: name: load_s16_fpr -name: load_s16_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: fpr16 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = LDRHui %0, 0 :: (load 2 from %ir.addr) -body: | - bb.0: - liveins: %x0 - - %0(p0) = COPY %x0 - %1(s16) = G_LOAD %0 :: (load 2 from %ir.addr) - -... - ---- -# CHECK-LABEL: name: load_s8_fpr -name: load_s8_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: fpr8 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = LDRBui %0, 0 :: (load 1 from %ir.addr) -body: | - bb.0: - liveins: %x0 - - %0(p0) = COPY %x0 - %1(s8) = G_LOAD %0 :: (load 1 from %ir.addr) - -... - ---- -# CHECK-LABEL: name: store_s64_gpr -name: store_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: STRXui %1, %0, 0 :: (store 8 into %ir.addr) -body: | - bb.0: - liveins: %x0, %x1 - - %0(p0) = COPY %x0 - %1(s64) = COPY %x1 - G_STORE %1, %0 :: (store 8 into %ir.addr) - -... - ---- -# CHECK-LABEL: name: store_s32_gpr -name: store_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %w1 -# CHECK: STRWui %1, %0, 0 :: (store 4 into %ir.addr) -body: | - bb.0: - liveins: %x0, %w1 - - %0(p0) = COPY %x0 - %1(s32) = COPY %w1 - G_STORE %1, %0 :: (store 4 into %ir.addr) - -... - ---- -# CHECK-LABEL: name: store_s16_gpr -name: store_s16_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %w1 -# CHECK: STRHHui %1, %0, 0 :: (store 2 into %ir.addr) -body: | - bb.0: - liveins: %x0, %w1 - - %0(p0) = COPY %x0 - %1(s16) = COPY %w1 - G_STORE %1, %0 :: (store 2 into %ir.addr) - -... - ---- -# CHECK-LABEL: name: store_s8_gpr -name: store_s8_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %w1 -# CHECK: STRBBui %1, %0, 0 :: (store 1 into %ir.addr) -body: | - bb.0: - liveins: %x0, %w1 - - %0(p0) = COPY %x0 - %1(s8) = COPY %w1 - G_STORE %1, %0 :: (store 1 into %ir.addr) - -... - ---- -# CHECK-LABEL: name: store_s64_fpr -name: store_s64_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: fpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %d1 -# CHECK: STRDui %1, %0, 0 :: (store 8 into %ir.addr) -body: | - bb.0: - liveins: %x0, %d1 - - %0(p0) = COPY %x0 - %1(s64) = COPY %d1 - G_STORE %1, %0 :: (store 8 into %ir.addr) - -... - ---- -# CHECK-LABEL: name: store_s32_fpr -name: store_s32_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -# CHECK-NEXT: - { id: 1, class: fpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %s1 -# CHECK: STRSui %1, %0, 0 :: (store 4 into %ir.addr) -body: | - bb.0: - liveins: %x0, %s1 - - %0(p0) = COPY %x0 - %1(s32) = COPY %s1 - G_STORE %1, %0 :: (store 4 into %ir.addr) - -... - ---- -# CHECK-LABEL: name: frame_index -name: frame_index -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp } -registers: - - { id: 0, class: gpr } - -stack: - - { id: 0, name: ptr0, offset: 0, size: 8, alignment: 8 } - -# CHECK: body: -# CHECK: %0 = ADDXri %stack.0.ptr0, 0, 0 -body: | - bb.0: - %0(p0) = G_FRAME_INDEX %stack.0.ptr0 -... - ---- -# Check that we set the "selected" property. -# CHECK-LABEL: name: selected_property -# CHECK: legalized: true -# CHECK-NEXT: regBankSelected: true -# CHECK-NEXT: selected: true -name: selected_property -legalized: true -regBankSelected: true -selected: false -body: | - bb.0: -... - ---- -# CHECK-LABEL: name: const_s32 -name: const_s32 -legalized: true -regBankSelected: true -registers: - - { id: 0, class: gpr } - -# CHECK: body: -# CHECK: %0 = MOVi32imm 42 -body: | - bb.0: - %0(s32) = G_CONSTANT i32 42 -... - ---- -# CHECK-LABEL: name: const_s64 -name: const_s64 -legalized: true -regBankSelected: true -registers: - - { id: 0, class: gpr } - -# CHECK: body: -# CHECK: %0 = MOVi64imm 1234567890123 -body: | - bb.0: - %0(s64) = G_CONSTANT i64 1234567890123 -... - ---- -# CHECK-LABEL: name: fconst_s32 -name: fconst_s32 -legalized: true -regBankSelected: true -registers: - - { id: 0, class: fpr } - -# CHECK: body: -# CHECK: [[TMP:%[0-9]+]] = MOVi32imm 1080033280 -# CHECK: %0 = COPY [[TMP]] -body: | - bb.0: - %0(s32) = G_FCONSTANT float 3.5 -... - ---- -# CHECK-LABEL: name: fconst_s64 -name: fconst_s64 -legalized: true -regBankSelected: true -registers: - - { id: 0, class: fpr } - -# CHECK: body: -# CHECK: [[TMP:%[0-9]+]] = MOVi64imm 4607182418800017408 -# CHECK: %0 = COPY [[TMP]] -body: | - bb.0: - %0(s64) = G_FCONSTANT double 1.0 -... - ---- -# CHECK-LABEL: name: gep -name: gep -legalized: true -regBankSelected: true -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %1 = MOVi64imm 42 -# CHECK: %2 = ADDXrr %0, %1 -body: | - bb.0: - liveins: %x0 - %0(p0) = COPY %x0 - %1(s64) = G_CONSTANT i64 42 - %2(p0) = G_GEP %0, %1(s64) -... - ---- -# Global defined in the same linkage unit so no GOT is needed -# CHECK-LABEL: name: global_local -name: global_local -legalized: true -regBankSelected: true -registers: - - { id: 0, class: gpr } - -# CHECK: body: -# IOS: %0 = MOVaddr target-flags(aarch64-page) @var_local, target-flags(aarch64-pageoff, aarch64-nc) @var_local -# LINUX-DEFAULT: %0 = MOVaddr target-flags(aarch64-page) @var_local, target-flags(aarch64-pageoff, aarch64-nc) @var_local -# LINUX-PIC: %0 = LOADgot target-flags(aarch64-got) @var_local -body: | - bb.0: - %0(p0) = G_GLOBAL_VALUE @var_local -... - ---- -# CHECK-LABEL: name: global_got -name: global_got -legalized: true -regBankSelected: true -registers: - - { id: 0, class: gpr } - -# CHECK: body: -# IOS: %0 = LOADgot target-flags(aarch64-got) @var_got -# LINUX-DEFAULT: %0 = MOVaddr target-flags(aarch64-page) @var_got, target-flags(aarch64-pageoff, aarch64-nc) @var_got -# LINUX-PIC: %0 = LOADgot target-flags(aarch64-got) @var_got -body: | - bb.0: - %0(p0) = G_GLOBAL_VALUE @var_got -... - ---- -# CHECK-LABEL: name: trunc -name: trunc -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -# CHECK-NEXT: - { id: 3, class: gpr32 } -# CHECK-NEXT: - { id: 4, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - - { id: 3, class: gpr } - - { id: 4, class: gpr } - -# CHECK: body: -# CHECK: %1 = COPY %0 -# CHECK: %3 = COPY %2.sub_32 -# CHECK: %4 = COPY %2.sub_32 -body: | - bb.0: - liveins: %w0, %x0 - - %0(s32) = COPY %w0 - %1(s1) = G_TRUNC %0 - - %2(s64) = COPY %x0 - %3(s32) = G_TRUNC %2 - %4(s8) = G_TRUNC %2 -... - ---- -# CHECK-LABEL: name: anyext_gpr -name: anyext_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32all } -# CHECK-NEXT: - { id: 1, class: gpr64all } -# CHECK-NEXT: - { id: 2, class: gpr32all } -# CHECK-NEXT: - { id: 3, class: gpr32all } -# CHECK-NEXT: - { id: 4, class: gpr64all } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - - { id: 3, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %4 = SUBREG_TO_REG 0, %0, 15 -# CHECK: %1 = COPY %4 -# CHECK: %2 = COPY %w0 -# CHECK: %3 = COPY %2 -body: | - bb.0: - liveins: %w0 - - %0(s32) = COPY %w0 - %1(s64) = G_ANYEXT %0 - %2(s8) = COPY %w0 - %3(s32) = G_ANYEXT %2 -... - ---- -# CHECK-LABEL: name: zext_gpr -name: zext_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -# CHECK-NEXT: - { id: 3, class: gpr32 } -# CHECK-NEXT: - { id: 4, class: gpr32 } -# CHECK-NEXT: - { id: 5, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - - { id: 3, class: gpr } - - { id: 4, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %5 = SUBREG_TO_REG 0, %0, 15 -# CHECK: %1 = UBFMXri %5, 0, 31 -# CHECK: %2 = COPY %w0 -# CHECK: %3 = UBFMWri %2, 0, 7 -# CHECK: %4 = UBFMWri %2, 0, 7 -body: | - bb.0: - liveins: %w0 - - %0(s32) = COPY %w0 - %1(s64) = G_ZEXT %0 - %2(s8) = COPY %w0 - %3(s32) = G_ZEXT %2 - %4(s16)= G_ZEXT %2 -... - ---- -# CHECK-LABEL: name: sext_gpr -name: sext_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -# CHECK-NEXT: - { id: 3, class: gpr32 } -# CHECK-NEXT: - { id: 4, class: gpr32 } -# CHECK-NEXT: - { id: 5, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - - { id: 3, class: gpr } - - { id: 4, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %5 = SUBREG_TO_REG 0, %0, 15 -# CHECK: %1 = SBFMXri %5, 0, 31 -# CHECK: %2 = COPY %w0 -# CHECK: %3 = SBFMWri %2, 0, 7 -# CHECK: %4 = SBFMWri %2, 0, 7 -body: | - bb.0: - liveins: %w0 - - %0(s32) = COPY %w0 - %1(s64) = G_SEXT %0 - %2(s8) = COPY %w0 - %3(s32) = G_SEXT %2 - %4(s16) = G_SEXT %2 -... - ---- -# CHECK-LABEL: name: casts -name: casts -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64all } -# CHECK-NEXT: - { id: 1, class: fpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -# CHECK-NEXT: - { id: 3, class: gpr64 } -# CHECK-NEXT: - { id: 4, class: gpr32 } -# CHECK-NEXT: - { id: 5, class: gpr32 } -# CHECK-NEXT: - { id: 6, class: gpr32 } -# CHECK-NEXT: - { id: 7, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - - { id: 2, class: gpr } - - { id: 3, class: gpr } - - { id: 4, class: gpr } - - { id: 5, class: gpr } - - { id: 6, class: gpr } - - { id: 7, class: gpr } -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %0 -# CHECK: %2 = COPY %0 -# CHECK: %3 = COPY %2 -# CHECK: %4 = COPY %2.sub_32 -# CHECK: %5 = COPY %2.sub_32 -# CHECK: %6 = COPY %2.sub_32 -# CHECK: %7 = COPY %2.sub_32 -body: | - bb.0: - liveins: %x0 - %0(s64) = COPY %x0 - %1(<8 x s8>) = G_BITCAST %0(s64) - %2(p0) = G_INTTOPTR %0 - - %3(s64) = G_PTRTOINT %2 - %4(s32) = G_PTRTOINT %2 - %5(s16) = G_PTRTOINT %2 - %6(s8) = G_PTRTOINT %2 - %7(s1) = G_PTRTOINT %2 -... - ---- -# CHECK-LABEL: name: bitcast_s32_gpr -name: bitcast_s32_gpr -legalized: true -regBankSelected: true -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32all } -# CHECK-NEXT: - { id: 1, class: gpr32all } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %0 -body: | - bb.0: - liveins: %w0 - - %0(s32) = COPY %w0 - %1(s32) = G_BITCAST %0 -... - ---- -# CHECK-LABEL: name: bitcast_s32_fpr -name: bitcast_s32_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: fpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %s0 -# CHECK: %1 = COPY %0 -body: | - bb.0: - liveins: %s0 - - %0(s32) = COPY %s0 - %1(s32) = G_BITCAST %0 -... - ---- -# CHECK-LABEL: name: bitcast_s32_gpr_fpr -name: bitcast_s32_gpr_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32all } -# CHECK-NEXT: - { id: 1, class: fpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %0 -body: | - bb.0: - liveins: %w0 - - %0(s32) = COPY %w0 - %1(s32) = G_BITCAST %0 -... - ---- -# CHECK-LABEL: name: bitcast_s32_fpr_gpr -name: bitcast_s32_fpr_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32all } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %s0 -# CHECK: %1 = COPY %0 -body: | - bb.0: - liveins: %s0 - - %0(s32) = COPY %s0 - %1(s32) = G_BITCAST %0 -... - ---- -# CHECK-LABEL: name: bitcast_s64_gpr -name: bitcast_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64all } -# CHECK-NEXT: - { id: 1, class: gpr64all } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %0 -body: | - bb.0: - liveins: %x0 - - %0(s64) = COPY %x0 - %1(s64) = G_BITCAST %0 -... - ---- -# CHECK-LABEL: name: bitcast_s64_fpr -name: bitcast_s64_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr64 } -# CHECK-NEXT: - { id: 1, class: fpr64 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: fpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = COPY %0 -body: | - bb.0: - liveins: %d0 - - %0(s64) = COPY %d0 - %1(s64) = G_BITCAST %0 -... - ---- -# CHECK-LABEL: name: bitcast_s64_gpr_fpr -name: bitcast_s64_gpr_fpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64all } -# CHECK-NEXT: - { id: 1, class: fpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: fpr } -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %0 -body: | - bb.0: - liveins: %x0 - - %0(s64) = COPY %x0 - %1(s64) = G_BITCAST %0 -... - ---- -# CHECK-LABEL: name: bitcast_s64_fpr_gpr -name: bitcast_s64_fpr_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64all } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %d0 -# CHECK: %1 = COPY %0 -body: | - bb.0: - liveins: %d0 - - %0(s64) = COPY %d0 - %1(s64) = G_BITCAST %0 -... - ---- -# CHECK-LABEL: name: icmp -name: icmp -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -# CHECK-NEXT: - { id: 3, class: gpr32 } -# CHECK-NEXT: - { id: 4, class: gpr64 } -# CHECK-NEXT: - { id: 5, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - - { id: 3, class: gpr } - - { id: 4, class: gpr } - - { id: 5, class: gpr } - -# CHECK: body: -# CHECK: %wzr = SUBSWrr %0, %0, implicit-def %nzcv -# CHECK: %1 = CSINCWr %wzr, %wzr, 1, implicit %nzcv - -# CHECK: %xzr = SUBSXrr %2, %2, implicit-def %nzcv -# CHECK: %3 = CSINCWr %wzr, %wzr, 3, implicit %nzcv - -# CHECK: %xzr = SUBSXrr %4, %4, implicit-def %nzcv -# CHECK: %5 = CSINCWr %wzr, %wzr, 0, implicit %nzcv - -body: | - bb.0: - liveins: %w0, %x0 - - %0(s32) = COPY %w0 - %1(s1) = G_ICMP intpred(eq), %0, %0 - - %2(s64) = COPY %x0 - %3(s1) = G_ICMP intpred(uge), %2, %2 - - %4(p0) = COPY %x0 - %5(s1) = G_ICMP intpred(ne), %4, %4 -... - ---- -# CHECK-LABEL: name: fcmp -name: fcmp -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: fpr64 } -# CHECK-NEXT: - { id: 3, class: gpr32 } -# CHECK-NEXT: - { id: 4, class: gpr32 } -# CHECK-NEXT: - { id: 5, class: gpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - - { id: 2, class: fpr } - - { id: 3, class: gpr } - -# CHECK: body: -# CHECK: FCMPSrr %0, %0, implicit-def %nzcv -# CHECK: [[TST_MI:%[0-9]+]] = CSINCWr %wzr, %wzr, 4, implicit %nzcv -# CHECK: [[TST_GT:%[0-9]+]] = CSINCWr %wzr, %wzr, 12, implicit %nzcv -# CHECK: %1 = ORRWrr [[TST_MI]], [[TST_GT]] - -# CHECK: FCMPDrr %2, %2, implicit-def %nzcv -# CHECK: %3 = CSINCWr %wzr, %wzr, 5, implicit %nzcv - -body: | - bb.0: - liveins: %w0, %x0 - - %0(s32) = COPY %s0 - %1(s1) = G_FCMP floatpred(one), %0, %0 - - %2(s64) = COPY %d0 - %3(s1) = G_FCMP floatpred(uge), %2, %2 - -... - ---- -# CHECK-LABEL: name: phi -name: phi -legalized: true -regBankSelected: true -tracksRegLiveness: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: fpr32 } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - - { id: 2, class: fpr } - -# CHECK: body: -# CHECK: bb.1: -# CHECK: %2 = PHI %0, %bb.0, %2, %bb.1 - -body: | - bb.0: - liveins: %s0, %w0 - successors: %bb.1 - %0(s32) = COPY %s0 - %1(s1) = COPY %w0 - - bb.1: - successors: %bb.1, %bb.2 - %2(s32) = PHI %0, %bb.0, %2, %bb.1 - G_BRCOND %1, %bb.1 - - bb.2: - %s0 = COPY %2 - RET_ReallyLR implicit %s0 -... - ---- -# CHECK-LABEL: name: select -name: select -legalized: true -regBankSelected: true -tracksRegLiveness: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -# CHECK-NEXT: - { id: 3, class: gpr32 } -# CHECK-NEXT: - { id: 4, class: gpr64 } -# CHECK-NEXT: - { id: 5, class: gpr64 } -# CHECK-NEXT: - { id: 6, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - - { id: 3, class: gpr } - - { id: 4, class: gpr } - - { id: 5, class: gpr } - - { id: 6, class: gpr } - -# CHECK: body: -# CHECK: %wzr = ANDSWri %0, 0, implicit-def %nzcv -# CHECK: %3 = CSELWr %1, %2, 1, implicit %nzcv -# CHECK: %wzr = ANDSWri %0, 0, implicit-def %nzcv -# CHECK: %6 = CSELXr %4, %5, 1, implicit %nzcv -body: | - bb.0: - liveins: %w0, %w1, %w2 - %0(s1) = COPY %w0 - - %1(s32) = COPY %w1 - %2(s32) = COPY %w2 - %3(s32) = G_SELECT %0, %1, %2 - - %4(s64) = COPY %x0 - %5(s64) = COPY %x1 - %6(s64) = G_SELECT %0, %4, %5 -... diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator-stackprotect.ll b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator-stackprotect.ll index 579ef777223c3..0063086411843 100644 --- a/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator-stackprotect.ll +++ b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator-stackprotect.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=aarch64-apple-ios %s -stop-after=irtranslator -o - -global-isel | FileCheck %s +; RUN: llc -verify-machineinstrs -mtriple=aarch64-apple-ios %s -stop-after=irtranslator -o - -global-isel | FileCheck %s ; CHECK: name: test_stack_guard diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll index 15b4012f383d8..02848021dbc09 100644 --- a/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -52,18 +52,40 @@ define void @allocai64() { ; CHECK: body: ; ; ABI/constant lowering and IR-level entry basic block. -; CHECK: {{bb.[0-9]+}} (%ir-block.{{[0-9]+}}): +; CHECK: {{bb.[0-9]+}}.entry: ; ; Make sure we have one successor and only one. -; CHECK-NEXT: successors: %[[END:bb.[0-9]+.end]](0x80000000) +; CHECK-NEXT: successors: %[[BB2:bb.[0-9]+.bb2]](0x80000000) ; ; Check that we emit the correct branch. -; CHECK: G_BR %[[END]] +; CHECK: G_BR %[[BB2]] ; ; Check that end contains the return instruction. -; CHECK: [[END]]: +; CHECK: [[END:bb.[0-9]+.end]]: ; CHECK-NEXT: RET_ReallyLR +; +; CHECK: {{bb.[0-9]+}}.bb2: +; CHECK-NEXT: successors: %[[END]](0x80000000) +; CHECK: G_BR %[[END]] define void @uncondbr() { +entry: + br label %bb2 +end: + ret void +bb2: + br label %end +} + +; CHECK-LABEL: name: uncondbr_fallthrough +; CHECK: body: +; CHECK: {{bb.[0-9]+}}.entry: +; CHECK-NEXT: successors: %[[END:bb.[0-9]+.end]](0x80000000) +; We don't emit a branch here, as we can fallthrough to the successor. +; CHECK-NOT: G_BR +; CHECK: [[END]]: +; CHECK-NEXT: RET_ReallyLR +define void @uncondbr_fallthrough() { +entry: br label %end end: ret void @@ -117,33 +139,35 @@ false: ; CHECK: G_BRCOND %[[regicmp100]](s1), %[[BB_CASE100]] ; CHECK: G_BR %[[BB_NOTCASE100_CHECKNEXT]] ; -; CHECK: [[BB_CASE100]]: -; CHECK-NEXT: successors: %[[BB_RET:bb.[0-9]+.return]](0x80000000) -; CHECK: %[[regretc100:[0-9]+]](s32) = G_ADD %0, %[[reg1]] -; CHECK: G_BR %[[BB_RET]] ; CHECK: [[BB_NOTCASE100_CHECKNEXT]]: ; CHECK-NEXT: successors: %[[BB_CASE200:bb.[0-9]+.case200]](0x40000000), %[[BB_NOTCASE200_CHECKNEXT:bb.[0-9]+.entry]](0x40000000) ; CHECK: %[[regicmp200:[0-9]+]](s1) = G_ICMP intpred(eq), %[[reg200]](s32), %0 ; CHECK: G_BRCOND %[[regicmp200]](s1), %[[BB_CASE200]] ; CHECK: G_BR %[[BB_NOTCASE200_CHECKNEXT]] ; -; CHECK: [[BB_CASE200]]: -; CHECK-NEXT: successors: %[[BB_RET:bb.[0-9]+.return]](0x80000000) -; CHECK: %[[regretc200:[0-9]+]](s32) = G_ADD %0, %[[reg2]] -; CHECK: G_BR %[[BB_RET]] ; CHECK: [[BB_NOTCASE200_CHECKNEXT]]: ; CHECK-NEXT: successors: %[[BB_DEFAULT:bb.[0-9]+.default]](0x80000000) ; CHECK: G_BR %[[BB_DEFAULT]] ; ; CHECK: [[BB_DEFAULT]]: -; CHECK-NEXT: successors: %[[BB_RET]](0x80000000) +; CHECK-NEXT: successors: %[[BB_RET:bb.[0-9]+.return]](0x80000000) ; CHECK: %[[regretdefault:[0-9]+]](s32) = G_ADD %0, %[[reg0]] ; CHECK: G_BR %[[BB_RET]] ; +; CHECK: [[BB_CASE100]]: +; CHECK-NEXT: successors: %[[BB_RET:bb.[0-9]+.return]](0x80000000) +; CHECK: %[[regretc100:[0-9]+]](s32) = G_ADD %0, %[[reg1]] +; CHECK: G_BR %[[BB_RET]] +; +; CHECK: [[BB_CASE200]]: +; CHECK-NEXT: successors: %[[BB_RET]](0x80000000) +; CHECK: %[[regretc200:[0-9]+]](s32) = G_ADD %0, %[[reg2]] +; ; CHECK: [[BB_RET]]: ; CHECK-NEXT: %[[regret:[0-9]+]](s32) = PHI %[[regretdefault]](s32), %[[BB_DEFAULT]], %[[regretc100]](s32), %[[BB_CASE100]] ; CHECK: %w0 = COPY %[[regret]](s32) ; CHECK: RET_ReallyLR implicit %w0 +; define i32 @switch(i32 %argc) { entry: switch i32 %argc, label %default [ @@ -168,6 +192,95 @@ return: ret i32 %res } + ; The switch lowering code changes the CFG, which means that the original + ; %entry block is no longer a predecessor for the phi instruction. We need to + ; use the correct lowered MachineBasicBlock instead. +; CHECK-LABEL: name: test_cfg_remap +; CHECK: {{bb.[0-9]+.entry}}: +; CHECK-NEXT: successors: %{{bb.[0-9]+.next}}(0x40000000), %[[NOTCASE1_BLOCK:bb.[0-9]+.entry]](0x40000000) +; CHECK: [[NOTCASE1_BLOCK]]: +; CHECK-NEXT: successors: %{{bb.[0-9]+.other}}(0x40000000), %[[NOTCASE57_BLOCK:bb.[0-9]+.entry]](0x40000000) +; CHECK: [[NOTCASE57_BLOCK]]: +; CHECK-NEXT: successors: %[[PHI_BLOCK:bb.[0-9]+.phi.block]](0x80000000) +; CHECK: G_BR %[[PHI_BLOCK]] +; +; CHECK: [[PHI_BLOCK]]: +; CHECK-NEXT: PHI %{{.*}}(s32), %[[NOTCASE57_BLOCK:bb.[0-9]+.entry]], %{{.*}}(s32), +; +define i32 @test_cfg_remap(i32 %in) { +entry: + switch i32 %in, label %phi.block [i32 1, label %next + i32 57, label %other] + +next: + br label %phi.block + +other: + ret i32 undef + +phi.block: + %res = phi i32 [1, %entry], [42, %next] + ret i32 %res +} + +; CHECK-LABEL: name: test_cfg_remap_multiple_preds +; CHECK: PHI [[ENTRY:%.*]](s32), %bb.{{[0-9]+}}.entry, [[ENTRY]](s32), %bb.{{[0-9]+}}.entry +define i32 @test_cfg_remap_multiple_preds(i32 %in) { +entry: + switch i32 %in, label %odd [i32 1, label %next + i32 57, label %other + i32 128, label %phi.block + i32 256, label %phi.block] +odd: + unreachable + +next: + br label %phi.block + +other: + ret i32 undef + +phi.block: + %res = phi i32 [1, %entry], [1, %entry], [42, %next] + ret i32 12 +} + +; Tests for indirect br. +; CHECK-LABEL: name: indirectbr +; CHECK: body: +; +; ABI/constant lowering and IR-level entry basic block. +; CHECK: {{bb.[0-9]+.entry}}: +; Make sure we have one successor +; CHECK-NEXT: successors: %[[BB_L1:bb.[0-9]+.L1]](0x80000000) +; CHECK-NOT: G_BR +; +; Check basic block L1 has 2 successors: BBL1 and BBL2 +; CHECK: [[BB_L1]] (address-taken): +; CHECK-NEXT: successors: %[[BB_L1]](0x40000000), +; CHECK: %[[BB_L2:bb.[0-9]+.L2]](0x40000000) +; CHECK: G_BRINDIRECT %{{[0-9]+}}(p0) +; +; Check basic block L2 is the return basic block +; CHECK: [[BB_L2]] (address-taken): +; CHECK-NEXT: RET_ReallyLR + +@indirectbr.L = internal unnamed_addr constant [3 x i8*] [i8* blockaddress(@indirectbr, %L1), i8* blockaddress(@indirectbr, %L2), i8* null], align 8 + +define void @indirectbr() { +entry: + br label %L1 +L1: ; preds = %entry, %L1 + %i = phi i32 [ 0, %entry ], [ %inc, %L1 ] + %inc = add i32 %i, 1 + %idxprom = zext i32 %i to i64 + %arrayidx = getelementptr inbounds [3 x i8*], [3 x i8*]* @indirectbr.L, i64 0, i64 %idxprom + %brtarget = load i8*, i8** %arrayidx, align 8 + indirectbr i8* %brtarget, [label %L1, label %L2] +L2: ; preds = %L1 + ret void +} + ; Tests for or. ; CHECK-LABEL: name: ori64 ; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0 @@ -293,11 +406,11 @@ define i64* @trivial_bitcast(i8* %a) { ; CHECK: [[A:%[0-9]+]](p0) = COPY %x0 ; CHECK: G_BR %[[CAST:bb\.[0-9]+.cast]] +; CHECK: [[END:bb\.[0-9]+.end]]: + ; CHECK: [[CAST]]: ; CHECK: {{%[0-9]+}}(p0) = COPY [[A]] -; CHECK: G_BR %[[END:bb\.[0-9]+.end]] - -; CHECK: [[END]]: +; CHECK: G_BR %[[END]] define i64* @trivial_bitcast_with_copy(i8* %a) { br label %cast @@ -375,7 +488,8 @@ define void @store(i64* %addr, i64 addrspace(42)* %addr42, i64 %val1, i64 %val2) ; CHECK-LABEL: name: intrinsics ; CHECK: [[CUR:%[0-9]+]](s32) = COPY %w0 ; CHECK: [[BITS:%[0-9]+]](s32) = COPY %w1 -; CHECK: [[PTR:%[0-9]+]](p0) = G_INTRINSIC intrinsic(@llvm.returnaddress), 0 +; CHECK: [[CREG:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[PTR:%[0-9]+]](p0) = G_INTRINSIC intrinsic(@llvm.returnaddress), [[CREG]] ; CHECK: [[PTR_VEC:%[0-9]+]](p0) = G_FRAME_INDEX %stack.0.ptr.vec ; CHECK: [[VEC:%[0-9]+]](<8 x s8>) = G_LOAD [[PTR_VEC]] ; CHECK: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.neon.st2), [[VEC]](<8 x s8>), [[VEC]](<8 x s8>), [[PTR]](p0) @@ -433,8 +547,8 @@ define void @unreachable(i32 %a) { ; CHECK-LABEL: name: constant_int ; CHECK: [[IN:%[0-9]+]](s32) = COPY %w0 ; CHECK: [[ONE:%[0-9]+]](s32) = G_CONSTANT i32 1 -; CHECK: G_BR +; CHECK: {{bb.[0-9]+}}.next: ; CHECK: [[SUM1:%[0-9]+]](s32) = G_ADD [[IN]], [[ONE]] ; CHECK: [[SUM2:%[0-9]+]](s32) = G_ADD [[IN]], [[ONE]] ; CHECK: [[RES:%[0-9]+]](s32) = G_ADD [[SUM1]], [[SUM2]] @@ -796,7 +910,7 @@ define void @test_extractvalue_agg(%struct.nested* %addr, {i8, i32}* %addr2) { ; CHECK-LABEL: name: test_insertvalue ; CHECK: [[VAL:%[0-9]+]](s32) = COPY %w1 ; CHECK: [[STRUCT:%[0-9]+]](s128) = G_LOAD -; CHECK: [[NEWSTRUCT:%[0-9]+]](s128) = G_INSERT [[STRUCT]](s128), [[VAL]](s32), 64 +; CHECK: [[NEWSTRUCT:%[0-9]+]](s128) = G_INSERT [[STRUCT]], [[VAL]](s32), 64 ; CHECK: G_STORE [[NEWSTRUCT]](s128), define void @test_insertvalue(%struct.nested* %addr, i32 %val) { %struct = load %struct.nested, %struct.nested* %addr @@ -805,10 +919,30 @@ define void @test_insertvalue(%struct.nested* %addr, i32 %val) { ret void } +define [1 x i64] @test_trivial_insert([1 x i64] %s, i64 %val) { +; CHECK-LABEL: name: test_trivial_insert +; CHECK: [[STRUCT:%[0-9]+]](s64) = COPY %x0 +; CHECK: [[VAL:%[0-9]+]](s64) = COPY %x1 +; CHECK: [[RES:%[0-9]+]](s64) = COPY [[VAL]](s64) +; CHECK: %x0 = COPY [[RES]] + %res = insertvalue [1 x i64] %s, i64 %val, 0 + ret [1 x i64] %res +} + +define [1 x i8*] @test_trivial_insert_ptr([1 x i8*] %s, i8* %val) { +; CHECK-LABEL: name: test_trivial_insert_ptr +; CHECK: [[STRUCT:%[0-9]+]](s64) = COPY %x0 +; CHECK: [[VAL:%[0-9]+]](p0) = COPY %x1 +; CHECK: [[RES:%[0-9]+]](s64) = G_PTRTOINT [[VAL]](p0) +; CHECK: %x0 = COPY [[RES]] + %res = insertvalue [1 x i8*] %s, i8* %val, 0 + ret [1 x i8*] %res +} + ; CHECK-LABEL: name: test_insertvalue_agg ; CHECK: [[SMALLSTRUCT:%[0-9]+]](s64) = G_LOAD ; CHECK: [[STRUCT:%[0-9]+]](s128) = G_LOAD -; CHECK: [[RES:%[0-9]+]](s128) = G_INSERT [[STRUCT]](s128), [[SMALLSTRUCT]](s64), 32 +; CHECK: [[RES:%[0-9]+]](s128) = G_INSERT [[STRUCT]], [[SMALLSTRUCT]](s64), 32 ; CHECK: G_STORE [[RES]](s128) define void @test_insertvalue_agg(%struct.nested* %addr, {i8, i32}* %addr2) { %smallstruct = load {i8, i32}, {i8, i32}* %addr2 @@ -840,6 +974,30 @@ define i8* @test_select_ptr(i1 %tst, i8* %lhs, i8* %rhs) { ret i8* %res } +; CHECK-LABEL: name: test_select_vec +; CHECK: [[TST:%[0-9]+]](s1) = COPY %w0 +; CHECK: [[LHS:%[0-9]+]](<4 x s32>) = COPY %q0 +; CHECK: [[RHS:%[0-9]+]](<4 x s32>) = COPY %q1 +; CHECK: [[RES:%[0-9]+]](<4 x s32>) = G_SELECT [[TST]](s1), [[LHS]], [[RHS]] +; CHECK: %q0 = COPY [[RES]] +define <4 x i32> @test_select_vec(i1 %tst, <4 x i32> %lhs, <4 x i32> %rhs) { + %res = select i1 %tst, <4 x i32> %lhs, <4 x i32> %rhs + ret <4 x i32> %res +} + +; CHECK-LABEL: name: test_vselect_vec +; CHECK: [[TST32:%[0-9]+]](<4 x s32>) = COPY %q0 +; CHECK: [[LHS:%[0-9]+]](<4 x s32>) = COPY %q1 +; CHECK: [[RHS:%[0-9]+]](<4 x s32>) = COPY %q2 +; CHECK: [[TST:%[0-9]+]](<4 x s1>) = G_TRUNC [[TST32]](<4 x s32>) +; CHECK: [[RES:%[0-9]+]](<4 x s32>) = G_SELECT [[TST]](<4 x s1>), [[LHS]], [[RHS]] +; CHECK: %q0 = COPY [[RES]] +define <4 x i32> @test_vselect_vec(<4 x i32> %tst32, <4 x i32> %lhs, <4 x i32> %rhs) { + %tst = trunc <4 x i32> %tst32 to <4 x i1> + %res = select <4 x i1> %tst, <4 x i32> %lhs, <4 x i32> %rhs + ret <4 x i32> %res +} + ; CHECK-LABEL: name: test_fptosi ; CHECK: [[FPADDR:%[0-9]+]](p0) = COPY %x0 ; CHECK: [[FP:%[0-9]+]](s32) = G_LOAD [[FPADDR]](p0) @@ -927,6 +1085,19 @@ define void @float_comparison(float* %a.addr, float* %b.addr, i1* %bool.addr) { ret void } +; CHECK-LABEL: name: trivial_float_comparison +; CHECK: [[ENTRY_R1:%[0-9]+]](s1) = G_CONSTANT i1 false +; CHECK: [[ENTRY_R2:%[0-9]+]](s1) = G_CONSTANT i1 true +; CHECK: [[R1:%[0-9]+]](s1) = COPY [[ENTRY_R1]](s1) +; CHECK: [[R2:%[0-9]+]](s1) = COPY [[ENTRY_R2]](s1) +; CHECK: G_ADD [[R1]], [[R2]] +define i1 @trivial_float_comparison(double %a, double %b) { + %r1 = fcmp false double %a, %b + %r2 = fcmp true double %a, %b + %sum = add i1 %r1, %r2 + ret i1 %sum +} + @var = global i32 0 define i32* @test_global() { @@ -969,6 +1140,34 @@ define void @test_memcpy(i8* %dst, i8* %src, i64 %size) { ret void } +declare void @llvm.memmove.p0i8.p0i8.i64(i8*, i8*, i64, i32 %align, i1 %volatile) +define void @test_memmove(i8* %dst, i8* %src, i64 %size) { +; CHECK-LABEL: name: test_memmove +; CHECK: [[DST:%[0-9]+]](p0) = COPY %x0 +; CHECK: [[SRC:%[0-9]+]](p0) = COPY %x1 +; CHECK: [[SIZE:%[0-9]+]](s64) = COPY %x2 +; CHECK: %x0 = COPY [[DST]] +; CHECK: %x1 = COPY [[SRC]] +; CHECK: %x2 = COPY [[SIZE]] +; CHECK: BL $memmove, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %x0, implicit %x1, implicit %x2 + call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %size, i32 1, i1 0) + ret void +} + +declare void @llvm.memset.p0i8.i64(i8*, i8, i64, i32 %align, i1 %volatile) +define void @test_memset(i8* %dst, i8 %val, i64 %size) { +; CHECK-LABEL: name: test_memset +; CHECK: [[DST:%[0-9]+]](p0) = COPY %x0 +; CHECK: [[SRC:%[0-9]+]](s8) = COPY %w1 +; CHECK: [[SIZE:%[0-9]+]](s64) = COPY %x2 +; CHECK: %x0 = COPY [[DST]] +; CHECK: %w1 = COPY [[SRC]] +; CHECK: %x2 = COPY [[SIZE]] +; CHECK: BL $memset, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %x0, implicit %w1, implicit %x2 + call void @llvm.memset.p0i8.i64(i8* %dst, i8 %val, i64 %size, i32 1, i1 0) + ret void +} + declare i64 @llvm.objectsize.i64(i8*, i1) declare i32 @llvm.objectsize.i32(i8*, i1) define void @test_objectsize(i8* %addr0, i8* %addr1) { @@ -1004,9 +1203,341 @@ define i8* @test_const_placement() { ; CHECK: bb.{{[0-9]+}} (%ir-block.{{[0-9]+}}): ; CHECK: [[VAL_INT:%[0-9]+]](s32) = G_CONSTANT i32 42 ; CHECK: [[VAL:%[0-9]+]](p0) = G_INTTOPTR [[VAL_INT]](s32) -; CHECK: G_BR +; CHECK: {{bb.[0-9]+}}.next: br label %next next: ret i8* inttoptr(i32 42 to i8*) } + +declare void @llvm.va_end(i8*) +define void @test_va_end(i8* %list) { +; CHECK-LABEL: name: test_va_end +; CHECK-NOT: va_end +; CHECK-NOT: INTRINSIC +; CHECK: RET_ReallyLR + call void @llvm.va_end(i8* %list) + ret void +} + +define void @test_va_arg(i8* %list) { +; CHECK-LABEL: test_va_arg +; CHECK: [[LIST:%[0-9]+]](p0) = COPY %x0 +; CHECK: G_VAARG [[LIST]](p0), 8 +; CHECK: G_VAARG [[LIST]](p0), 1 +; CHECK: G_VAARG [[LIST]](p0), 16 + + %v0 = va_arg i8* %list, i64 + %v1 = va_arg i8* %list, i8 + %v2 = va_arg i8* %list, i128 + ret void +} + +declare float @llvm.pow.f32(float, float) +define float @test_pow_intrin(float %l, float %r) { +; CHECK-LABEL: name: test_pow_intrin +; CHECK: [[LHS:%[0-9]+]](s32) = COPY %s0 +; CHECK: [[RHS:%[0-9]+]](s32) = COPY %s1 +; CHECK: [[RES:%[0-9]+]](s32) = G_FPOW [[LHS]], [[RHS]] +; CHECK: %s0 = COPY [[RES]] + %res = call float @llvm.pow.f32(float %l, float %r) + ret float %res +} + +declare void @llvm.lifetime.start.p0i8(i64, i8*) +declare void @llvm.lifetime.end.p0i8(i64, i8*) +define void @test_lifetime_intrin() { +; CHECK-LABEL: name: test_lifetime_intrin +; CHECK: RET_ReallyLR + %slot = alloca i8, i32 4 + call void @llvm.lifetime.start.p0i8(i64 0, i8* %slot) + call void @llvm.lifetime.end.p0i8(i64 0, i8* %slot) + ret void +} + +define void @test_load_store_atomics(i8* %addr) { +; CHECK-LABEL: name: test_load_store_atomics +; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x0 +; CHECK: [[V0:%[0-9]+]](s8) = G_LOAD [[ADDR]](p0) :: (load unordered 1 from %ir.addr) +; CHECK: G_STORE [[V0]](s8), [[ADDR]](p0) :: (store monotonic 1 into %ir.addr) +; CHECK: [[V1:%[0-9]+]](s8) = G_LOAD [[ADDR]](p0) :: (load acquire 1 from %ir.addr) +; CHECK: G_STORE [[V1]](s8), [[ADDR]](p0) :: (store release 1 into %ir.addr) +; CHECK: [[V2:%[0-9]+]](s8) = G_LOAD [[ADDR]](p0) :: (load singlethread seq_cst 1 from %ir.addr) +; CHECK: G_STORE [[V2]](s8), [[ADDR]](p0) :: (store singlethread monotonic 1 into %ir.addr) + %v0 = load atomic i8, i8* %addr unordered, align 1 + store atomic i8 %v0, i8* %addr monotonic, align 1 + + %v1 = load atomic i8, i8* %addr acquire, align 1 + store atomic i8 %v1, i8* %addr release, align 1 + + %v2 = load atomic i8, i8* %addr singlethread seq_cst, align 1 + store atomic i8 %v2, i8* %addr singlethread monotonic, align 1 + + ret void +} + +define float @test_fneg_f32(float %x) { +; CHECK-LABEL: name: test_fneg_f32 +; CHECK: [[ARG:%[0-9]+]](s32) = COPY %s0 +; CHECK: [[RES:%[0-9]+]](s32) = G_FNEG [[ARG]] +; CHECK: %s0 = COPY [[RES]](s32) + %neg = fsub float -0.000000e+00, %x + ret float %neg +} + +define double @test_fneg_f64(double %x) { +; CHECK-LABEL: name: test_fneg_f64 +; CHECK: [[ARG:%[0-9]+]](s64) = COPY %d0 +; CHECK: [[RES:%[0-9]+]](s64) = G_FNEG [[ARG]] +; CHECK: %d0 = COPY [[RES]](s64) + %neg = fsub double -0.000000e+00, %x + ret double %neg +} + +define void @test_trivial_inlineasm() { +; CHECK-LABEL: name: test_trivial_inlineasm +; CHECK: INLINEASM $wibble, 1 +; CHECK: INLINEASM $wibble, 0 + call void asm sideeffect "wibble", ""() + call void asm "wibble", ""() + ret void +} + +define <2 x i32> @test_insertelement(<2 x i32> %vec, i32 %elt, i32 %idx){ +; CHECK-LABEL: name: test_insertelement +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK: [[ELT:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[IDX:%[0-9]+]](s32) = COPY %w1 +; CHECK: [[RES:%[0-9]+]](<2 x s32>) = G_INSERT_VECTOR_ELT [[VEC]], [[ELT]](s32), [[IDX]](s32) +; CHECK: %d0 = COPY [[RES]](<2 x s32>) + %res = insertelement <2 x i32> %vec, i32 %elt, i32 %idx + ret <2 x i32> %res +} + +define i32 @test_extractelement(<2 x i32> %vec, i32 %idx) { +; CHECK-LABEL: name: test_extractelement +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK: [[IDX:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[RES:%[0-9]+]](s32) = G_EXTRACT_VECTOR_ELT [[VEC]](<2 x s32>), [[IDX]](s32) +; CHECK: %w0 = COPY [[RES]](s32) + %res = extractelement <2 x i32> %vec, i32 %idx + ret i32 %res +} + +define i32 @test_singleelementvector(i32 %elt){ +; CHECK-LABEL: name: test_singleelementvector +; CHECK: [[ELT:%[0-9]+]](s32) = COPY %w0 +; CHECK-NOT: G_INSERT_VECTOR_ELT +; CHECK-NOT: G_EXTRACT_VECTOR_ELT +; CHECK: %w0 = COPY [[ELT]](s32) + %vec = insertelement <1 x i32> undef, i32 %elt, i32 0 + %res = extractelement <1 x i32> %vec, i32 0 + ret i32 %res +} + +define <2 x i32> @test_constantaggzerovector_v2i32() { +; CHECK-LABEL: name: test_constantaggzerovector_v2i32 +; CHECK: [[ZERO:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[ZERO]](s32), [[ZERO]](s32) +; CHECK: %d0 = COPY [[VEC]](<2 x s32>) + ret <2 x i32> zeroinitializer +} + +define <2 x float> @test_constantaggzerovector_v2f32() { +; CHECK-LABEL: name: test_constantaggzerovector_v2f32 +; CHECK: [[ZERO:%[0-9]+]](s32) = G_FCONSTANT float 0.000000e+00 +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[ZERO]](s32), [[ZERO]](s32) +; CHECK: %d0 = COPY [[VEC]](<2 x s32>) + ret <2 x float> zeroinitializer +} + +define i32 @test_constantaggzerovector_v3i32() { +; CHECK-LABEL: name: test_constantaggzerovector_v3i32 +; CHECK: [[ZERO:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[VEC:%[0-9]+]](<3 x s32>) = G_MERGE_VALUES [[ZERO]](s32), [[ZERO]](s32), [[ZERO]](s32) +; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<3 x s32>) + %elt = extractelement <3 x i32> zeroinitializer, i32 1 + ret i32 %elt +} + +define <2 x i32> @test_constantdatavector_v2i32() { +; CHECK-LABEL: name: test_constantdatavector_v2i32 +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[C2:%[0-9]+]](s32) = G_CONSTANT i32 2 +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C2]](s32) +; CHECK: %d0 = COPY [[VEC]](<2 x s32>) + ret <2 x i32> <i32 1, i32 2> +} + +define i32 @test_constantdatavector_v3i32() { +; CHECK-LABEL: name: test_constantdatavector_v3i32 +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[C2:%[0-9]+]](s32) = G_CONSTANT i32 2 +; CHECK: [[C3:%[0-9]+]](s32) = G_CONSTANT i32 3 +; CHECK: [[VEC:%[0-9]+]](<3 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C2]](s32), [[C3]](s32) +; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<3 x s32>) + %elt = extractelement <3 x i32> <i32 1, i32 2, i32 3>, i32 1 + ret i32 %elt +} + +define <4 x i32> @test_constantdatavector_v4i32() { +; CHECK-LABEL: name: test_constantdatavector_v4i32 +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[C2:%[0-9]+]](s32) = G_CONSTANT i32 2 +; CHECK: [[C3:%[0-9]+]](s32) = G_CONSTANT i32 3 +; CHECK: [[C4:%[0-9]+]](s32) = G_CONSTANT i32 4 +; CHECK: [[VEC:%[0-9]+]](<4 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C2]](s32), [[C3]](s32), [[C4]](s32) +; CHECK: %q0 = COPY [[VEC]](<4 x s32>) + ret <4 x i32> <i32 1, i32 2, i32 3, i32 4> +} + +define <2 x double> @test_constantdatavector_v2f64() { +; CHECK-LABEL: name: test_constantdatavector_v2f64 +; CHECK: [[FC1:%[0-9]+]](s64) = G_FCONSTANT double 1.000000e+00 +; CHECK: [[FC2:%[0-9]+]](s64) = G_FCONSTANT double 2.000000e+00 +; CHECK: [[VEC:%[0-9]+]](<2 x s64>) = G_MERGE_VALUES [[FC1]](s64), [[FC2]](s64) +; CHECK: %q0 = COPY [[VEC]](<2 x s64>) + ret <2 x double> <double 1.0, double 2.0> +} + +define i32 @test_constantaggzerovector_v1s32(i32 %arg){ +; CHECK-LABEL: name: test_constantaggzerovector_v1s32 +; CHECK: [[ARG:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK-NOT: G_MERGE_VALUES +; CHECK: G_ADD [[ARG]], [[C0]] + %vec = insertelement <1 x i32> undef, i32 %arg, i32 0 + %add = add <1 x i32> %vec, zeroinitializer + %res = extractelement <1 x i32> %add, i32 0 + ret i32 %res +} + +define i32 @test_constantdatavector_v1s32(i32 %arg){ +; CHECK-LABEL: name: test_constantdatavector_v1s32 +; CHECK: [[ARG:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK-NOT: G_MERGE_VALUES +; CHECK: G_ADD [[ARG]], [[C1]] + %vec = insertelement <1 x i32> undef, i32 %arg, i32 0 + %add = add <1 x i32> %vec, <i32 1> + %res = extractelement <1 x i32> %add, i32 0 + ret i32 %res +} + +declare ghccc float @different_call_conv_target(float %x) +define float @test_different_call_conv_target(float %x) { +; CHECK-LABEL: name: test_different_call_conv +; CHECK: [[X:%[0-9]+]](s32) = COPY %s0 +; CHECK: %s8 = COPY [[X]] +; CHECK: BL @different_call_conv_target, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %s8, implicit-def %s0 + %res = call ghccc float @different_call_conv_target(float %x) + ret float %res +} + +define <2 x i32> @test_shufflevector_s32_v2s32(i32 %arg) { +; CHECK-LABEL: name: test_shufflevector_s32_v2s32 +; CHECK: [[ARG:%[0-9]+]](s32) = COPY %w0 +; CHECK-DAG: [[UNDEF:%[0-9]+]](s32) = IMPLICIT_DEF +; CHECK-DAG: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK-DAG: [[MASK:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[C0]](s32), [[C0]](s32) +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](s32), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: %d0 = COPY [[VEC]](<2 x s32>) + %vec = insertelement <1 x i32> undef, i32 %arg, i32 0 + %res = shufflevector <1 x i32> %vec, <1 x i32> undef, <2 x i32> zeroinitializer + ret <2 x i32> %res +} + +define i32 @test_shufflevector_v2s32_s32(<2 x i32> %arg) { +; CHECK-LABEL: name: test_shufflevector_v2s32_s32 +; CHECK: [[ARG:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK-DAG: [[UNDEF:%[0-9]+]](<2 x s32>) = IMPLICIT_DEF +; CHECK-DAG: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[RES:%[0-9]+]](s32) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], [[C1]](s32) +; CHECK: %w0 = COPY [[RES]](s32) + %vec = shufflevector <2 x i32> %arg, <2 x i32> undef, <1 x i32> <i32 1> + %res = extractelement <1 x i32> %vec, i32 0 + ret i32 %res +} + +define <2 x i32> @test_shufflevector_v2s32_v2s32(<2 x i32> %arg) { +; CHECK-LABEL: name: test_shufflevector_v2s32_v2s32 +; CHECK: [[ARG:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK-DAG: [[UNDEF:%[0-9]+]](<2 x s32>) = IMPLICIT_DEF +; CHECK-DAG: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK-DAG: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK-DAG: [[MASK:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C0]](s32) +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: %d0 = COPY [[VEC]](<2 x s32>) + %res = shufflevector <2 x i32> %arg, <2 x i32> undef, <2 x i32> <i32 1, i32 0> + ret <2 x i32> %res +} + +define i32 @test_shufflevector_v2s32_v3s32(<2 x i32> %arg) { +; CHECK-LABEL: name: test_shufflevector_v2s32_v3s32 +; CHECK: [[ARG:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK-DAG: [[UNDEF:%[0-9]+]](<2 x s32>) = IMPLICIT_DEF +; CHECK-DAG: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK-DAG: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK-DAG: [[MASK:%[0-9]+]](<3 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C0]](s32), [[C1]](s32) +; CHECK: [[VEC:%[0-9]+]](<3 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<2 x s32>), [[UNDEF]], [[MASK]](<3 x s32>) +; CHECK: G_EXTRACT_VECTOR_ELT [[VEC]](<3 x s32>) + %vec = shufflevector <2 x i32> %arg, <2 x i32> undef, <3 x i32> <i32 1, i32 0, i32 1> + %res = extractelement <3 x i32> %vec, i32 0 + ret i32 %res +} + +define <4 x i32> @test_shufflevector_v2s32_v4s32(<2 x i32> %arg1, <2 x i32> %arg2) { +; CHECK-LABEL: name: test_shufflevector_v2s32_v4s32 +; CHECK: [[ARG1:%[0-9]+]](<2 x s32>) = COPY %d0 +; CHECK: [[ARG2:%[0-9]+]](<2 x s32>) = COPY %d1 +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[C2:%[0-9]+]](s32) = G_CONSTANT i32 2 +; CHECK: [[C3:%[0-9]+]](s32) = G_CONSTANT i32 3 +; CHECK: [[MASK:%[0-9]+]](<4 x s32>) = G_MERGE_VALUES [[C0]](s32), [[C1]](s32), [[C2]](s32), [[C3]](s32) +; CHECK: [[VEC:%[0-9]+]](<4 x s32>) = G_SHUFFLE_VECTOR [[ARG1]](<2 x s32>), [[ARG2]], [[MASK]](<4 x s32>) +; CHECK: %q0 = COPY [[VEC]](<4 x s32>) + %res = shufflevector <2 x i32> %arg1, <2 x i32> %arg2, <4 x i32> <i32 0, i32 1, i32 2, i32 3> + ret <4 x i32> %res +} + +define <2 x i32> @test_shufflevector_v4s32_v2s32(<4 x i32> %arg) { +; CHECK-LABEL: name: test_shufflevector_v4s32_v2s32 +; CHECK: [[ARG:%[0-9]+]](<4 x s32>) = COPY %q0 +; CHECK-DAG: [[UNDEF:%[0-9]+]](<4 x s32>) = IMPLICIT_DEF +; CHECK-DAG: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK-DAG: [[C3:%[0-9]+]](s32) = G_CONSTANT i32 3 +; CHECK-DAG: [[MASK:%[0-9]+]](<2 x s32>) = G_MERGE_VALUES [[C1]](s32), [[C3]](s32) +; CHECK: [[VEC:%[0-9]+]](<2 x s32>) = G_SHUFFLE_VECTOR [[ARG]](<4 x s32>), [[UNDEF]], [[MASK]](<2 x s32>) +; CHECK: %d0 = COPY [[VEC]](<2 x s32>) + %res = shufflevector <4 x i32> %arg, <4 x i32> undef, <2 x i32> <i32 1, i32 3> + ret <2 x i32> %res +} + + +define <16 x i8> @test_shufflevector_v8s8_v16s8(<8 x i8> %arg1, <8 x i8> %arg2) { +; CHECK-LABEL: name: test_shufflevector_v8s8_v16s8 +; CHECK: [[ARG1:%[0-9]+]](<8 x s8>) = COPY %d0 +; CHECK: [[ARG2:%[0-9]+]](<8 x s8>) = COPY %d1 +; CHECK: [[C0:%[0-9]+]](s32) = G_CONSTANT i32 0 +; CHECK: [[C8:%[0-9]+]](s32) = G_CONSTANT i32 8 +; CHECK: [[C1:%[0-9]+]](s32) = G_CONSTANT i32 1 +; CHECK: [[C9:%[0-9]+]](s32) = G_CONSTANT i32 9 +; CHECK: [[C2:%[0-9]+]](s32) = G_CONSTANT i32 2 +; CHECK: [[C10:%[0-9]+]](s32) = G_CONSTANT i32 10 +; CHECK: [[C3:%[0-9]+]](s32) = G_CONSTANT i32 3 +; CHECK: [[C11:%[0-9]+]](s32) = G_CONSTANT i32 11 +; CHECK: [[C4:%[0-9]+]](s32) = G_CONSTANT i32 4 +; CHECK: [[C12:%[0-9]+]](s32) = G_CONSTANT i32 12 +; CHECK: [[C5:%[0-9]+]](s32) = G_CONSTANT i32 5 +; CHECK: [[C13:%[0-9]+]](s32) = G_CONSTANT i32 13 +; CHECK: [[C6:%[0-9]+]](s32) = G_CONSTANT i32 6 +; CHECK: [[C14:%[0-9]+]](s32) = G_CONSTANT i32 14 +; CHECK: [[C7:%[0-9]+]](s32) = G_CONSTANT i32 7 +; CHECK: [[C15:%[0-9]+]](s32) = G_CONSTANT i32 15 +; CHECK: [[MASK:%[0-9]+]](<16 x s32>) = G_MERGE_VALUES [[C0]](s32), [[C8]](s32), [[C1]](s32), [[C9]](s32), [[C2]](s32), [[C10]](s32), [[C3]](s32), [[C11]](s32), [[C4]](s32), [[C12]](s32), [[C5]](s32), [[C13]](s32), [[C6]](s32), [[C14]](s32), [[C7]](s32), [[C15]](s32) +; CHECK: [[VEC:%[0-9]+]](<16 x s8>) = G_SHUFFLE_VECTOR [[ARG1]](<8 x s8>), [[ARG2]], [[MASK]](<16 x s32>) +; CHECK: %q0 = COPY [[VEC]](<16 x s8>) + %res = shufflevector <8 x i8> %arg1, <8 x i8> %arg2, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15> + ret <16 x i8> %res +} diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir b/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir index 4c67c0daaf744..739fdd5cb4c54 100644 --- a/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir +++ b/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir @@ -1,5 +1,5 @@ -# RUN: llc -O0 -run-pass=regbankselect -global-isel %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=FAST -# RUN: llc -O0 -run-pass=regbankselect -global-isel %s -regbankselect-greedy -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=GREEDY +# RUN: llc -O0 -run-pass=regbankselect -global-isel %s -o - -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix=FAST +# RUN: llc -O0 -run-pass=regbankselect -global-isel %s -regbankselect-greedy -o - -verify-machineinstrs | FileCheck %s --check-prefix=CHECK --check-prefix=GREEDY --- | ; ModuleID = 'generic-virtual-registers-type-error.mir' @@ -315,8 +315,8 @@ body: | ; Fast mode tries to reuse the source of the copy for the destination. ; Now, the default mapping says that %0 and %1 need to be in FPR. ; The repairing code insert two copies to materialize that. - ; FAST-NEXT: %3(s64) = COPY %0 - ; FAST-NEXT: %4(s64) = COPY %1 + ; FAST-NEXT: %3(<2 x s32>) = COPY %0 + ; FAST-NEXT: %4(<2 x s32>) = COPY %1 ; The mapping of G_OR is on FPR. ; FAST-NEXT: %2(<2 x s32>) = G_OR %3, %4 @@ -362,13 +362,13 @@ body: | ; Fast mode tries to reuse the source of the copy for the destination. ; Now, the default mapping says that %0 and %1 need to be in FPR. ; The repairing code insert two copies to materialize that. - ; FAST-NEXT: %3(s64) = COPY %0 - ; FAST-NEXT: %4(s64) = COPY %1 + ; FAST-NEXT: %3(<2 x s32>) = COPY %0 + ; FAST-NEXT: %4(<2 x s32>) = COPY %1 ; The mapping of G_OR is on FPR. ; FAST-NEXT: %2(<2 x s32>) = G_OR %3, %4 ; Greedy mode remapped the instruction on the GPR bank. - ; GREEDY-NEXT: %3(s64) = G_OR %0, %1 + ; GREEDY-NEXT: %3(<2 x s32>) = G_OR %0, %1 ; We need to keep %2 into FPR because we do not know anything about it. ; GREEDY-NEXT: %2(<2 x s32>) = COPY %3 %0(<2 x s32>) = COPY %x0 diff --git a/test/CodeGen/AArch64/GlobalISel/call-translator.ll b/test/CodeGen/AArch64/GlobalISel/call-translator.ll index 7bedad38de1ae..f8d95c88cc8f3 100644 --- a/test/CodeGen/AArch64/GlobalISel/call-translator.ll +++ b/test/CodeGen/AArch64/GlobalISel/call-translator.ll @@ -1,7 +1,9 @@ ; RUN: llc -mtriple=aarch64-linux-gnu -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s ; CHECK-LABEL: name: test_trivial_call +; CHECK: ADJCALLSTACKDOWN 0, implicit-def %sp, implicit %sp ; CHECK: BL @trivial_callee, csr_aarch64_aapcs, implicit-def %lr +; CHECK: ADJCALLSTACKUP 0, 0, implicit-def %sp, implicit %sp declare void @trivial_callee() define void @test_trivial_call() { call void @trivial_callee() @@ -61,7 +63,13 @@ define void @test_multiple_args(i64 %in) { ; CHECK: [[I64:%[0-9]+]](s64) = COPY %x0 ; CHECK: [[I8:%[0-9]+]](s8) = COPY %w1 ; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2 -; CHECK: [[ARG:%[0-9]+]](s192) = G_SEQUENCE [[DBL]](s64), 0, [[I64]](s64), 64, [[I8]](s8), 128 + +; CHECK: [[UNDEF:%[0-9]+]](s192) = IMPLICIT_DEF +; CHECK: [[ARG0:%[0-9]+]](s192) = G_INSERT [[UNDEF]], [[DBL]](s64), 0 +; CHECK: [[ARG1:%[0-9]+]](s192) = G_INSERT [[ARG0]], [[I64]](s64), 64 +; CHECK: [[ARG2:%[0-9]+]](s192) = G_INSERT [[ARG1]], [[I8]](s8), 128 +; CHECK: [[ARG:%[0-9]+]](s192) = COPY [[ARG2]] + ; CHECK: G_STORE [[ARG]](s192), [[ADDR]](p0) ; CHECK: RET_ReallyLR define void @test_struct_formal({double, i64, i8} %in, {double, i64, i8}* %addr) { @@ -73,7 +81,11 @@ define void @test_struct_formal({double, i64, i8} %in, {double, i64, i8}* %addr) ; CHECK-LABEL: name: test_struct_return ; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x0 ; CHECK: [[VAL:%[0-9]+]](s192) = G_LOAD [[ADDR]](p0) -; CHECK: [[DBL:%[0-9]+]](s64), [[I64:%[0-9]+]](s64), [[I32:%[0-9]+]](s32) = G_EXTRACT [[VAL]](s192), 0, 64, 128 + +; CHECK: [[DBL:%[0-9]+]](s64) = G_EXTRACT [[VAL]](s192), 0 +; CHECK: [[I64:%[0-9]+]](s64) = G_EXTRACT [[VAL]](s192), 64 +; CHECK: [[I32:%[0-9]+]](s32) = G_EXTRACT [[VAL]](s192), 128 + ; CHECK: %d0 = COPY [[DBL]](s64) ; CHECK: %x0 = COPY [[I64]](s64) ; CHECK: %w1 = COPY [[I32]](s32) @@ -84,8 +96,14 @@ define {double, i64, i32} @test_struct_return({double, i64, i32}* %addr) { } ; CHECK-LABEL: name: test_arr_call +; CHECK: hasCalls: true ; CHECK: [[ARG:%[0-9]+]](s256) = G_LOAD -; CHECK: [[E0:%[0-9]+]](s64), [[E1:%[0-9]+]](s64), [[E2:%[0-9]+]](s64), [[E3:%[0-9]+]](s64) = G_EXTRACT [[ARG]](s256), 0, 64, 128, 192 + +; CHECK: [[E0:%[0-9]+]](s64) = G_EXTRACT [[ARG]](s256), 0 +; CHECK: [[E1:%[0-9]+]](s64) = G_EXTRACT [[ARG]](s256), 64 +; CHECK: [[E2:%[0-9]+]](s64) = G_EXTRACT [[ARG]](s256), 128 +; CHECK: [[E3:%[0-9]+]](s64) = G_EXTRACT [[ARG]](s256), 192 + ; CHECK: %x0 = COPY [[E0]](s64) ; CHECK: %x1 = COPY [[E1]](s64) ; CHECK: %x2 = COPY [[E2]](s64) @@ -168,6 +186,7 @@ define void @test_stack_slots([8 x i64], i64 %lhs, i64 %rhs, i64* %addr) { ; CHECK: [[C42:%[0-9]+]](s64) = G_CONSTANT i64 42 ; CHECK: [[C12:%[0-9]+]](s64) = G_CONSTANT i64 12 ; CHECK: [[PTR:%[0-9]+]](p0) = G_CONSTANT i64 0 +; CHECK: ADJCALLSTACKDOWN 24, implicit-def %sp, implicit %sp ; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp ; CHECK: [[C42_OFFS:%[0-9]+]](s64) = G_CONSTANT i64 0 ; CHECK: [[C42_LOC:%[0-9]+]](p0) = G_GEP [[SP]], [[C42_OFFS]](s64) @@ -181,6 +200,7 @@ define void @test_stack_slots([8 x i64], i64 %lhs, i64 %rhs, i64* %addr) { ; CHECK: [[PTR_LOC:%[0-9]+]](p0) = G_GEP [[SP]], [[PTR_OFFS]](s64) ; CHECK: G_STORE [[PTR]](p0), [[PTR_LOC]](p0) :: (store 8 into stack + 16, align 0) ; CHECK: BL @test_stack_slots +; CHECK: ADJCALLSTACKUP 24, 0, implicit-def %sp, implicit %sp define void @test_call_stack() { call void @test_stack_slots([8 x i64] undef, i64 42, i64 12, i64* null) ret void diff --git a/test/CodeGen/AArch64/GlobalISel/debug-insts.ll b/test/CodeGen/AArch64/GlobalISel/debug-insts.ll new file mode 100644 index 0000000000000..5a76661180f22 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/debug-insts.ll @@ -0,0 +1,68 @@ +; RUN: llc -global-isel -mtriple=aarch64 %s -stop-after=irtranslator -o - | FileCheck %s +; RUN: llc -mtriple=aarch64 -global-isel --global-isel-abort=0 -o /dev/null + +; CHECK-LABEL: name: debug_declare +; CHECK: stack: +; CHECK: - { id: {{.*}}, name: in.addr, offset: {{.*}}, size: {{.*}}, alignment: {{.*}}, di-variable: '!11', +; CHECK-NEXT: di-expression: '!12', di-location: '!13' } +; CHECK: DBG_VALUE debug-use %0(s32), debug-use _, !11, !12, debug-location !13 +define void @debug_declare(i32 %in) #0 !dbg !7 { +entry: + %in.addr = alloca i32, align 4 + store i32 %in, i32* %in.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %in.addr, metadata !11, metadata !12), !dbg !13 + call void @llvm.dbg.declare(metadata i32 %in, metadata !11, metadata !12), !dbg !13 + ret void, !dbg !14 +} + +; CHECK-LABEL: name: debug_declare_vla +; CHECK: DBG_VALUE debug-use %{{[0-9]+}}(p0), debug-use _, !11, !12, debug-location !13 +define void @debug_declare_vla(i32 %in) #0 !dbg !7 { +entry: + %vla.addr = alloca i32, i32 %in + call void @llvm.dbg.declare(metadata i32* %vla.addr, metadata !11, metadata !12), !dbg !13 + ret void, !dbg !14 +} + +; CHECK-LABEL: name: debug_value +; CHECK: [[IN:%[0-9]+]](s32) = COPY %w0 +define void @debug_value(i32 %in) #0 !dbg !7 { + %addr = alloca i32 +; CHECK: DBG_VALUE debug-use [[IN]](s32), debug-use _, !11, !12, debug-location !13 + call void @llvm.dbg.value(metadata i32 %in, i64 0, metadata !11, metadata !12), !dbg !13 + store i32 %in, i32* %addr +; CHECK: DBG_VALUE debug-use %1(p0), debug-use _, !11, !15, debug-location !13 + call void @llvm.dbg.value(metadata i32* %addr, i64 0, metadata !11, metadata !15), !dbg !13 +; CHECK: DBG_VALUE 123, 0, !11, !12, debug-location !13 + call void @llvm.dbg.value(metadata i32 123, i64 0, metadata !11, metadata !12), !dbg !13 +; CHECK: DBG_VALUE float 1.000000e+00, 0, !11, !12, debug-location !13 + call void @llvm.dbg.value(metadata float 1.000000e+00, i64 0, metadata !11, metadata !12), !dbg !13 +; CHECK: DBG_VALUE _, 0, !11, !12, debug-location !13 + call void @llvm.dbg.value(metadata i32* null, i64 0, metadata !11, metadata !12), !dbg !13 + ret void +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 289075) (llvm/trunk 289080)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "tmp.c", directory: "/Users/tim/llvm/build") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"PIC Level", i32 2} +!6 = !{!"clang version 4.0.0 (trunk 289075) (llvm/trunk 289080)"} +!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DILocalVariable(name: "in", arg: 1, scope: !7, file: !1, line: 1, type: !10) +!12 = !DIExpression() +!13 = !DILocation(line: 1, column: 14, scope: !7) +!14 = !DILocation(line: 2, column: 1, scope: !7) +!15 = !DIExpression(DW_OP_deref) diff --git a/test/CodeGen/AArch64/GlobalISel/dynamic-alloca.ll b/test/CodeGen/AArch64/GlobalISel/dynamic-alloca.ll new file mode 100644 index 0000000000000..196910e96ce3e --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/dynamic-alloca.ll @@ -0,0 +1,48 @@ +; RUN: llc -mtriple=aarch64 -global-isel %s -o - -stop-after=irtranslator | FileCheck %s + +; CHECK-LABEL: name: test_simple_alloca +; CHECK: [[NUMELTS:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[TYPE_SIZE:%[0-9]+]](s64) = G_CONSTANT i64 -1 +; CHECK: [[NUMELTS_64:%[0-9]+]](s64) = G_ZEXT [[NUMELTS]](s32) +; CHECK: [[NUMBYTES:%[0-9]+]](s64) = G_MUL [[NUMELTS_64]], [[TYPE_SIZE]] +; CHECK: [[SP_TMP:%[0-9]+]](p0) = COPY %sp +; CHECK: [[ALLOC:%[0-9]+]](p0) = G_GEP [[SP_TMP]], [[NUMBYTES]] +; CHECK: [[ALIGNED_ALLOC:%[0-9]+]](p0) = G_PTR_MASK [[ALLOC]], 4 +; CHECK: %sp = COPY [[ALIGNED_ALLOC]] +; CHECK: [[ALLOC:%[0-9]+]](p0) = COPY [[ALIGNED_ALLOC]] +; CHECK: %x0 = COPY [[ALLOC]] +define i8* @test_simple_alloca(i32 %numelts) { + %addr = alloca i8, i32 %numelts + ret i8* %addr +} + +; CHECK-LABEL: name: test_aligned_alloca +; CHECK: [[NUMELTS:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[TYPE_SIZE:%[0-9]+]](s64) = G_CONSTANT i64 -1 +; CHECK: [[NUMELTS_64:%[0-9]+]](s64) = G_ZEXT [[NUMELTS]](s32) +; CHECK: [[NUMBYTES:%[0-9]+]](s64) = G_MUL [[NUMELTS_64]], [[TYPE_SIZE]] +; CHECK: [[SP_TMP:%[0-9]+]](p0) = COPY %sp +; CHECK: [[ALLOC:%[0-9]+]](p0) = G_GEP [[SP_TMP]], [[NUMBYTES]] +; CHECK: [[ALIGNED_ALLOC:%[0-9]+]](p0) = G_PTR_MASK [[ALLOC]], 5 +; CHECK: %sp = COPY [[ALIGNED_ALLOC]] +; CHECK: [[ALLOC:%[0-9]+]](p0) = COPY [[ALIGNED_ALLOC]] +; CHECK: %x0 = COPY [[ALLOC]] +define i8* @test_aligned_alloca(i32 %numelts) { + %addr = alloca i8, i32 %numelts, align 32 + ret i8* %addr +} + +; CHECK-LABEL: name: test_natural_alloca +; CHECK: [[NUMELTS:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[TYPE_SIZE:%[0-9]+]](s64) = G_CONSTANT i64 -16 +; CHECK: [[NUMELTS_64:%[0-9]+]](s64) = G_ZEXT [[NUMELTS]](s32) +; CHECK: [[NUMBYTES:%[0-9]+]](s64) = G_MUL [[NUMELTS_64]], [[TYPE_SIZE]] +; CHECK: [[SP_TMP:%[0-9]+]](p0) = COPY %sp +; CHECK: [[ALLOC:%[0-9]+]](p0) = G_GEP [[SP_TMP]], [[NUMBYTES]] +; CHECK: %sp = COPY [[ALLOC]] +; CHECK: [[ALLOC_TMP:%[0-9]+]](p0) = COPY [[ALLOC]] +; CHECK: %x0 = COPY [[ALLOC_TMP]] +define i128* @test_natural_alloca(i32 %numelts) { + %addr = alloca i128, i32 %numelts + ret i128* %addr +} diff --git a/test/CodeGen/AArch64/GlobalISel/gisel-abort.ll b/test/CodeGen/AArch64/GlobalISel/gisel-abort.ll index 76eafdd5af5e4..a1480c46fe40f 100644 --- a/test/CodeGen/AArch64/GlobalISel/gisel-abort.ll +++ b/test/CodeGen/AArch64/GlobalISel/gisel-abort.ll @@ -1,4 +1,4 @@ -; RUN: llc -march aarch64 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s +; RUN: llc -mtriple=aarch64-unknown-unknown -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s ; CHECK-NOT: fallback ; CHECK: empty diff --git a/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll b/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll new file mode 100644 index 0000000000000..3ecdb7bbedfb5 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll @@ -0,0 +1,48 @@ +; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \ +; RUN: -O0 -aarch64-enable-global-isel-at-O=0 \ +; RUN: | FileCheck %s --check-prefix ENABLED --check-prefix NOFALLBACK + +; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \ +; RUN: -O0 -aarch64-enable-global-isel-at-O=0 -global-isel-abort=2 \ +; RUN: | FileCheck %s --check-prefix ENABLED --check-prefix FALLBACK + +; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \ +; RUN: -global-isel \ +; RUN: | FileCheck %s --check-prefix ENABLED --check-prefix NOFALLBACK + +; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \ +; RUN: -global-isel -global-isel-abort=2 \ +; RUN: | FileCheck %s --check-prefix ENABLED --check-prefix FALLBACK + +; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \ +; RUN: -O1 -aarch64-enable-global-isel-at-O=3 \ +; RUN: | FileCheck %s --check-prefix ENABLED + +; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \ +; RUN: -O1 -aarch64-enable-global-isel-at-O=0 \ +; RUN: | FileCheck %s --check-prefix DISABLED + +; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \ +; RUN: -aarch64-enable-global-isel-at-O=-1 \ +; RUN: | FileCheck %s --check-prefix DISABLED + +; RUN: llc -mtriple=aarch64-- -debug-pass=Structure %s -o /dev/null 2>&1 \ +; RUN: | FileCheck %s --check-prefix DISABLED + +; ENABLED: IRTranslator +; ENABLED-NEXT: Legalizer +; ENABLED-NEXT: RegBankSelect +; ENABLED-NEXT: InstructionSelect +; ENABLED-NEXT: ResetMachineFunction + +; FALLBACK: AArch64 Instruction Selection +; NOFALLBACK-NOT: AArch64 Instruction Selection + +; DISABLED-NOT: IRTranslator + +; DISABLED: AArch64 Instruction Selection +; DISABLED: Expand ISel Pseudo-instructions + +define void @empty() { + ret void +} diff --git a/test/CodeGen/AArch64/GlobalISel/gisel-fail-intermediate-legalizer.ll b/test/CodeGen/AArch64/GlobalISel/gisel-fail-intermediate-legalizer.ll new file mode 100644 index 0000000000000..e333f742e04df --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/gisel-fail-intermediate-legalizer.ll @@ -0,0 +1,8 @@ +;RUN: llc -mtriple=aarch64-unknown-unknown -o - -global-isel -global-isel-abort=2 %s 2>&1 | FileCheck %s +; CHECK: fallback +; CHECK-LABEL: foo +define i16 @foo(half* %p) { + %tmp0 = load half, half* %p + %tmp1 = fptoui half %tmp0 to i16 + ret i16 %tmp1 +} diff --git a/test/CodeGen/AArch64/GlobalISel/inline-asm.ll b/test/CodeGen/AArch64/GlobalISel/inline-asm.ll new file mode 100644 index 0000000000000..8ff7c4495dccb --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/inline-asm.ll @@ -0,0 +1,10 @@ +; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 %s -o - | FileCheck %s + +; CHECK-LABEL: test_asm: +; CHECK: {{APP|InlineAsm Start}} +; CHECK: mov x0, {{x[0-9]+}} +; CHECK: {{NO_APP|InlineAsm End}} +define void @test_asm() { + call void asm sideeffect "mov x0, $0", "r"(i64 42) + ret void +} diff --git a/test/CodeGen/AArch64/GlobalISel/irtranslator-bitcast.ll b/test/CodeGen/AArch64/GlobalISel/irtranslator-bitcast.ll new file mode 100644 index 0000000000000..8d1b02216ea76 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/irtranslator-bitcast.ll @@ -0,0 +1,30 @@ +; RUN: llc -O0 -mtriple=aarch64-apple-ios -global-isel -stop-after=irtranslator %s -o - | FileCheck %s + +; Check that we don't invalidate the vreg map. +; This test is brittle: the invalidation only triggers when we grow the map. + +; CHECK-LABEL: name: test_bitcast_invalid_vreg +define i32 @test_bitcast_invalid_vreg() { + %tmp0 = add i32 1, 2 + %tmp1 = add i32 3, 4 + %tmp2 = add i32 5, 6 + %tmp3 = add i32 7, 8 + %tmp4 = add i32 9, 10 + %tmp5 = add i32 11, 12 + %tmp6 = add i32 13, 14 + %tmp7 = add i32 15, 16 + %tmp8 = add i32 17, 18 + %tmp9 = add i32 19, 20 + %tmp10 = add i32 21, 22 + %tmp11 = add i32 23, 24 + %tmp12 = add i32 25, 26 + %tmp13 = add i32 27, 28 + %tmp14 = add i32 29, 30 + %tmp15 = add i32 30, 30 + +; At this point we mapped 46 values. The 'i32 100' constant will grow the map. +; CHECK: %46(s32) = G_CONSTANT i32 100 +; CHECK: %w0 = COPY %46(s32) + %res = bitcast i32 100 to i32 + ret i32 %res +} diff --git a/test/CodeGen/AArch64/GlobalISel/irtranslator-exceptions.ll b/test/CodeGen/AArch64/GlobalISel/irtranslator-exceptions.ll index 718364af2aca7..ef4445111d7b2 100644 --- a/test/CodeGen/AArch64/GlobalISel/irtranslator-exceptions.ll +++ b/test/CodeGen/AArch64/GlobalISel/irtranslator-exceptions.ll @@ -6,7 +6,7 @@ declare i32 @foo(i32) declare i32 @__gxx_personality_v0(...) declare i32 @llvm.eh.typeid.for(i8*) -; CHECK: name: bar +; CHECK-LABEL: name: bar ; CHECK: body: ; CHECK-NEXT: bb.1 (%ir-block.0): ; CHECK: successors: %[[GOOD:bb.[0-9]+.continue]]{{.*}}%[[BAD:bb.[0-9]+.broken]] @@ -15,19 +15,24 @@ declare i32 @llvm.eh.typeid.for(i8*) ; CHECK: BL @foo, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %w0, implicit-def %w0 ; CHECK: {{%[0-9]+}}(s32) = COPY %w0 ; CHECK: EH_LABEL +; CHECK: G_BR %[[GOOD]] ; CHECK: [[BAD]] (landing-pad): ; CHECK: EH_LABEL +; CHECK: [[UNDEF:%[0-9]+]](s128) = IMPLICIT_DEF ; CHECK: [[PTR:%[0-9]+]](p0) = COPY %x0 -; CHECK: [[SEL:%[0-9]+]](p0) = COPY %x1 -; CHECK: [[PTR_SEL:%[0-9]+]](s128) = G_SEQUENCE [[PTR]](p0), 0, [[SEL]](p0), 64 -; CHECK: [[PTR_RET:%[0-9]+]](s64), [[SEL_RET:%[0-9]+]](s32) = G_EXTRACT [[PTR_SEL]](s128), 0, 64 +; CHECK: [[VAL_WITH_PTR:%[0-9]+]](s128) = G_INSERT [[UNDEF]], [[PTR]](p0), 0 +; CHECK: [[SEL_PTR:%[0-9]+]](p0) = COPY %x1 +; CHECK: [[SEL:%[0-9]+]](s32) = G_PTRTOINT [[SEL_PTR]] +; CHECK: [[PTR_SEL:%[0-9]+]](s128) = G_INSERT [[VAL_WITH_PTR]], [[SEL]](s32), 64 +; CHECK: [[PTR_RET:%[0-9]+]](s64) = G_EXTRACT [[PTR_SEL]](s128), 0 +; CHECK: [[SEL_RET:%[0-9]+]](s32) = G_EXTRACT [[PTR_SEL]](s128), 64 ; CHECK: %x0 = COPY [[PTR_RET]] ; CHECK: %w1 = COPY [[SEL_RET]] ; CHECK: [[GOOD]]: ; CHECK: [[SEL:%[0-9]+]](s32) = G_CONSTANT i32 1 -; CHECK: {{%[0-9]+}}(s128) = G_INSERT {{%[0-9]+}}(s128), [[SEL]](s32), 64 +; CHECK: {{%[0-9]+}}(s128) = G_INSERT {{%[0-9]+}}, [[SEL]](s32), 64 define { i8*, i32 } @bar() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { %res32 = invoke i32 @foo(i32 42) to label %continue unwind label %broken @@ -42,3 +47,48 @@ continue: %res.good = insertvalue { i8*, i32 } undef, i32 %sel.int, 1 ret { i8*, i32 } %res.good } + +; CHECK-LABEL: name: test_invoke_indirect +; CHECK: [[CALLEE:%[0-9]+]](p0) = COPY %x0 +; CHECK: BLR [[CALLEE]] +define void @test_invoke_indirect(void()* %callee) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { + invoke void %callee() to label %continue unwind label %broken + +broken: + landingpad { i8*, i32 } catch i8* bitcast(i8** @_ZTIi to i8*) + ret void + +continue: + ret void +} + +; CHECK-LABEL: name: test_invoke_varargs + +; CHECK: [[NULL:%[0-9]+]](p0) = G_CONSTANT i64 0 +; CHECK: [[ANSWER:%[0-9]+]](s32) = G_CONSTANT i32 42 +; CHECK: [[ONE:%[0-9]+]](s32) = G_FCONSTANT float 1.0 + +; CHECK: %x0 = COPY [[NULL]] + +; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp +; CHECK: [[OFFSET:%[0-9]+]](s64) = G_CONSTANT i64 0 +; CHECK: [[SLOT:%[0-9]+]](p0) = G_GEP [[SP]], [[OFFSET]](s64) +; CHECK: G_STORE [[ANSWER]](s32), [[SLOT]] + +; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp +; CHECK: [[OFFSET:%[0-9]+]](s64) = G_CONSTANT i64 8 +; CHECK: [[SLOT:%[0-9]+]](p0) = G_GEP [[SP]], [[OFFSET]](s64) +; CHECK: G_STORE [[ONE]](s32), [[SLOT]] + +; CHECK: BL @printf +declare void @printf(i8*, ...) +define void @test_invoke_varargs() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { + invoke void(i8*, ...) @printf(i8* null, i32 42, float 1.0) to label %continue unwind label %broken + +broken: + landingpad { i8*, i32 } catch i8* bitcast(i8** @_ZTIi to i8*) + ret void + +continue: + ret void +} diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-add.mir b/test/CodeGen/AArch64/GlobalISel/legalize-add.mir index 252e60c6b2ec8..9b27198b961ae 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-add.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-add.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" @@ -33,14 +33,14 @@ body: | bb.0.entry: liveins: %x0, %x1, %x2, %x3 ; CHECK-LABEL: name: test_scalar_add_big - ; CHECK-NOT: G_EXTRACT - ; CHECK-NOT: G_SEQUENCE + ; CHECK-NOT: G_MERGE_VALUES + ; CHECK-NOT: G_UNMERGE_VALUES ; CHECK-DAG: [[CARRY0_32:%.*]](s32) = G_CONSTANT i32 0 ; CHECK-DAG: [[CARRY0:%[0-9]+]](s1) = G_TRUNC [[CARRY0_32]] ; CHECK: [[RES_LO:%.*]](s64), [[CARRY:%.*]](s1) = G_UADDE %0, %2, [[CARRY0]] ; CHECK: [[RES_HI:%.*]](s64), {{%.*}}(s1) = G_UADDE %1, %3, [[CARRY]] - ; CHECK-NOT: G_EXTRACT - ; CHECK-NOT: G_SEQUENCE + ; CHECK-NOT: G_MERGE_VALUES + ; CHECK-NOT: G_UNMERGE_VALUES ; CHECK: %x0 = COPY [[RES_LO]] ; CHECK: %x1 = COPY [[RES_HI]] @@ -48,10 +48,10 @@ body: | %1(s64) = COPY %x1 %2(s64) = COPY %x2 %3(s64) = COPY %x3 - %4(s128) = G_SEQUENCE %0, 0, %1, 64 - %5(s128) = G_SEQUENCE %2, 0, %3, 64 + %4(s128) = G_MERGE_VALUES %0, %1 + %5(s128) = G_MERGE_VALUES %2, %3 %6(s128) = G_ADD %4, %5 - %7(s64), %8(s64) = G_EXTRACT %6, 0, 64 + %7(s64), %8(s64) = G_UNMERGE_VALUES %6 %x0 = COPY %7 %x1 = COPY %8 ... @@ -69,7 +69,10 @@ body: | bb.0.entry: liveins: %x0, %x1, %x2, %x3 ; CHECK-LABEL: name: test_scalar_add_small - ; CHECK: [[RES:%.*]](s8) = G_ADD %2, %3 + ; CHECK: [[OP0:%.*]](s32) = G_ANYEXT %2(s8) + ; CHECK: [[OP1:%.*]](s32) = G_ANYEXT %3(s8) + ; CHECK: [[RES32:%.*]](s32) = G_ADD [[OP0]], [[OP1]] + ; CHECK: [[RES:%.*]](s8) = G_TRUNC [[RES32]](s32) %0(s64) = COPY %x0 %1(s64) = COPY %x1 @@ -109,10 +112,10 @@ body: | %1(<2 x s64>) = COPY %q1 %2(<2 x s64>) = COPY %q2 %3(<2 x s64>) = COPY %q3 - %4(<4 x s64>) = G_SEQUENCE %0, 0, %1, 128 - %5(<4 x s64>) = G_SEQUENCE %2, 0, %3, 128 + %4(<4 x s64>) = G_MERGE_VALUES %0, %1 + %5(<4 x s64>) = G_MERGE_VALUES %2, %3 %6(<4 x s64>) = G_ADD %4, %5 - %7(<2 x s64>), %8(<2 x s64>) = G_EXTRACT %6, 0, 128 + %7(<2 x s64>), %8(<2 x s64>) = G_UNMERGE_VALUES %6 %q0 = COPY %7 %q1 = COPY %8 ... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-and.mir b/test/CodeGen/AArch64/GlobalISel/legalize-and.mir index 69459bfacb0a6..75e1d5163532d 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-and.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-and.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" @@ -22,7 +22,10 @@ body: | bb.0.entry: liveins: %x0, %x1, %x2, %x3 ; CHECK-LABEL: name: test_scalar_and_small - ; CHECK: %4(s8) = G_AND %2, %3 + ; CHECK: [[OP0:%.*]](s32) = G_ANYEXT %2(s8) + ; CHECK: [[OP1:%.*]](s32) = G_ANYEXT %3(s8) + ; CHECK: [[RES32:%.*]](s32) = G_AND [[OP0]], [[OP1]] + ; CHECK: [[RES:%.*]](s8) = G_TRUNC [[RES32]](s32) %0(s64) = COPY %x0 %1(s64) = COPY %x1 diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-cmp.mir b/test/CodeGen/AArch64/GlobalISel/legalize-cmp.mir index 926a62761ce09..29f83b3628958 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-cmp.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-cmp.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-combines.mir b/test/CodeGen/AArch64/GlobalISel/legalize-combines.mir index cc1dc80488ba5..fab6dcf433468 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-combines.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-combines.mir @@ -1,92 +1,132 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" target triple = "aarch64--" - define void @test_combines() { - entry: - ret void - } + define void @test_combines_1() { ret void } + define void @test_combines_2() { ret void } + define void @test_combines_3() { ret void } + define void @test_combines_4() { ret void } + define void @test_combines_5() { ret void } + define void @test_combines_6() { ret void } ... --- -name: test_combines -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: _ } - - { id: 3, class: _ } - - { id: 4, class: _ } - - { id: 5, class: _ } - - { id: 6, class: _ } - - { id: 7, class: _ } - - { id: 8, class: _ } - - { id: 9, class: _ } - - { id: 10, class: _ } - - { id: 11, class: _ } - - { id: 12, class: _ } - - { id: 13, class: _ } - - { id: 14, class: _ } - - { id: 15, class: _ } - - { id: 16, class: _ } - - { id: 17, class: _ } - - { id: 18, class: _ } - - { id: 19, class: _ } - - { id: 20, class: _ } - - { id: 21, class: _ } - - { id: 22, class: _ } - - { id: 23, class: _ } - - { id: 24, class: _ } +name: test_combines_1 body: | - bb.0.entry: - liveins: %w0, %w1, %x2, %x3 + bb.0: + liveins: %w0 - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s8) = G_TRUNC %0 + %0:_(s32) = COPY %w0 + %1:_(s8) = G_TRUNC %0 ; Only one of these extracts can be eliminated, the offsets don't match ; properly in the other cases. - ; CHECK-LABEL: name: test_combines - ; CHECK: %3(s32) = G_SEQUENCE %2(s8), 1 - ; CHECK: %4(s8) = G_EXTRACT %3(s32), 0 + ; CHECK-LABEL: name: test_combines_1 + ; CHECK: %2(s32) = G_SEQUENCE %1(s8), 1 + ; CHECK: %3(s8) = G_EXTRACT %2(s32), 0 ; CHECK-NOT: G_EXTRACT - ; CHECK: %6(s8) = G_EXTRACT %3(s32), 2 - ; CHECK: %7(s32) = G_ZEXT %2(s8) - %3(s32) = G_SEQUENCE %2, 1 - %4(s8) = G_EXTRACT %3, 0 - %5(s8) = G_EXTRACT %3, 1 - %6(s8) = G_EXTRACT %3, 2 - %7(s32) = G_ZEXT %5 + ; CHECK: %5(s8) = G_EXTRACT %2(s32), 2 + ; CHECK: %6(s32) = G_ZEXT %1(s8) + + %2:_(s32) = G_SEQUENCE %1, 1 + %3:_(s8) = G_EXTRACT %2, 0 + %4:_(s8) = G_EXTRACT %2, 1 + %5:_(s8) = G_EXTRACT %2, 2 + %6:_(s32) = G_ZEXT %4 +... + +--- +name: test_combines_2 +body: | + bb.0: + liveins: %w0 + + %0:_(s32) = COPY %w0 ; Similarly, here the types don't match. - ; CHECK: %10(s32) = G_SEQUENCE %8(s16), 0, %9(s16), 16 - ; CHECK: %11(s1) = G_EXTRACT %10(s32), 0 - ; CHECK: %12(s32) = G_EXTRACT %10(s32), 0 - %8(s16) = G_TRUNC %0 - %9(s16) = G_ADD %8, %8 - %10(s32) = G_SEQUENCE %8, 0, %9, 16 - %11(s1) = G_EXTRACT %10, 0 - %12(s32) = G_EXTRACT %10, 0 + ; CHECK-LABEL: name: test_combines_2 + ; CHECK: %2(s64) = G_SEQUENCE %0(s32), 0, %1(s32), 32 + ; CHECK: %3(s1) = G_EXTRACT %2(s64), 0 + ; CHECK: %4(s64) = G_EXTRACT %2(s64), 0 + %1:_(s32) = G_ADD %0, %0 + %2:_(s64) = G_SEQUENCE %0, 0, %1, 32 + %3:_(s1) = G_EXTRACT %2, 0 + %4:_(s64) = G_EXTRACT %2, 0 +... + +--- +name: test_combines_3 +body: | + bb.0: + liveins: %w0 + + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_combines_3 + ; CHECK: %1(s32) = G_ADD %0, %0 + ; CHECK-NOT: G_SEQUENCE + ; CHECK-NOT: G_EXTRACT + ; CHECK: %5(s32) = G_ADD %0, %1 + %1:_(s32) = G_ADD %0, %0 + %2:_(s64) = G_SEQUENCE %0, 0, %1, 32 + %3:_(s32) = G_EXTRACT %2, 0 + %4:_(s32) = G_EXTRACT %2, 32 + %5:_(s32) = G_ADD %3, %4 +... +--- +name: test_combines_4 +body: | + bb.0: + liveins: %x0 + + %0:_(s64) = COPY %x0 + + ; CHECK-LABEL: name: test_combines_4 + ; CHECK: %2(<2 x s32>) = G_EXTRACT %1(s128), 0 + ; CHECK: %3(<2 x s32>) = G_ADD %2, %2 + %1:_(s128) = G_SEQUENCE %0, 0, %0, 64 + %2:_(<2 x s32>) = G_EXTRACT %1, 0 + %3:_(<2 x s32>) = G_ADD %2, %2 +... + +--- +name: test_combines_5 +body: | + bb.0: + liveins: %w0 + + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_combines_5 + ; CHECK-NOT: G_SEQUENCE ; CHECK-NOT: G_EXTRACT - ; CHECK: %15(s16) = G_ADD %8, %9 - %13(s16), %14(s16) = G_EXTRACT %10, 0, 16 - %15(s16) = G_ADD %13, %14 + ; CHECK: %5(s32) = G_ADD %0, %1 + %1:_(s32) = G_ADD %0, %0 + %2:_(s64) = G_SEQUENCE %0, 0, %1, 32 + %3:_(s32) = G_EXTRACT %2, 0 + %4:_(s32) = G_EXTRACT %2, 32 + %5:_(s32) = G_ADD %3, %4 +... + +--- +name: test_combines_6 +body: | + bb.0: + liveins: %w0 - ; CHECK: %18(<2 x s32>) = G_EXTRACT %17(s128), 0 - ; CHECK: %19(<2 x s32>) = G_ADD %18, %18 - %16(s64) = COPY %x0 - %17(s128) = G_SEQUENCE %16, 0, %16, 64 - %18(<2 x s32>) = G_EXTRACT %17, 0 - %19(<2 x s32>) = G_ADD %18, %18 + ; CHECK-LABEL: name: test_combines_6 + ; CHECK: %0(s32) = COPY %w0 + %0:_(s32) = COPY %w0 + ; Check that we replace all the uses of a G_EXTRACT. ; CHECK-NOT: G_SEQUENCE ; CHECK-NOT: G_EXTRACT - ; CHECK: %24(s32) = G_ADD %0, %20 - %20(s32) = G_ADD %0, %0 - %21(s64) = G_SEQUENCE %0, 0, %20, 32 - %22(s32) = G_EXTRACT %21, 0 - %23(s32) = G_EXTRACT %21, 32 - %24(s32) = G_ADD %22, %23 + ; CHECK: %3(s32) = G_MUL %0, %0 + ; CHECK: %4(s32) = G_ADD %0, %3 + %1:_(s32) = G_SEQUENCE %0, 0 + %2:_(s32) = G_EXTRACT %1, 0 + %3:_(s32) = G_MUL %2, %2 + %4:_(s32) = G_ADD %2, %3 ... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-constant.mir b/test/CodeGen/AArch64/GlobalISel/legalize-constant.mir index 56a7d4736ae8e..16d9e59698fe1 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-constant.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-constant.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" @@ -57,7 +57,7 @@ body: | ; CHECK: %0(s32) = G_FCONSTANT float 1.000000e+00 ; CHECK: %1(s64) = G_FCONSTANT double 2.000000e+00 ; CHECK: [[TMP:%[0-9]+]](s32) = G_FCONSTANT half 0xH0000 - ; CHECK; %2(s16) = G_FPTRUNC [[TMP]] + ; CHECK: %2(s16) = G_FPTRUNC [[TMP]] %0(s32) = G_FCONSTANT float 1.0 %1(s64) = G_FCONSTANT double 2.0 diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-div.mir b/test/CodeGen/AArch64/GlobalISel/legalize-div.mir index aaef45d3c928b..c6e0aabfd2c0f 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-div.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-div.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll b/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll new file mode 100644 index 0000000000000..23e7d5163e5a5 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll @@ -0,0 +1,53 @@ +; RUN: llc -O0 -mtriple=aarch64-apple-ios -verify-machineinstrs -global-isel -stop-after=legalizer %s -o - | FileCheck %s + +@_ZTIi = external global i8* + +declare i32 @foo(i32) +declare i32 @__gxx_personality_v0(...) +declare i32 @llvm.eh.typeid.for(i8*) +declare void @_Unwind_Resume(i8*) + +; CHECK: name: bar +; CHECK: body: +; CHECK-NEXT: bb.1 (%ir-block.0): +; CHECK: successors: %{{bb.[0-9]+.continue.*}}%[[LP:bb.[0-9]+.cleanup]] + +; CHECK: [[LP]] (landing-pad): +; CHECK: EH_LABEL + +; CHECK: [[PTR:%[0-9]+]](p0) = COPY %x0 +; CHECK: [[STRUCT_PTR:%[0-9]+]](s64) = G_PTRTOINT [[PTR]](p0) + +; CHECK: [[SEL_PTR:%[0-9]+]](p0) = COPY %x1 +; CHECK: [[SEL:%[0-9]+]](s32) = G_PTRTOINT [[SEL_PTR]] +; CHECK: [[STRUCT_SEL:%[0-9]+]](s64) = G_INSERT {{%[0-9]+}}, [[SEL]](s32), 0 + +; CHECK: [[STRUCT:%[0-9]+]](s128) = G_MERGE_VALUES [[STRUCT_PTR]](s64), [[STRUCT_SEL]] + +; CHECK: [[PTR:%[0-9]+]](p0) = G_EXTRACT [[STRUCT]](s128), 0 +; CHECK: G_STORE [[PTR]](p0), {{%[0-9]+}}(p0) + +; CHECK: [[SEL:%[0-9]+]](s32) = G_EXTRACT [[STRUCT]](s128), 64 +; CHECK: G_STORE [[SEL]](s32), {{%[0-9]+}}(p0) + +define void @bar() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { + %exn.slot = alloca i8* + %ehselector.slot = alloca i32 + %1 = invoke i32 @foo(i32 42) to label %continue unwind label %cleanup + +cleanup: + %2 = landingpad { i8*, i32 } cleanup + %3 = extractvalue { i8*, i32 } %2, 0 + store i8* %3, i8** %exn.slot, align 8 + %4 = extractvalue { i8*, i32 } %2, 1 + store i32 %4, i32* %ehselector.slot, align 4 + br label %eh.resume + +continue: + ret void + +eh.resume: + %exn = load i8*, i8** %exn.slot, align 8 + call void @_Unwind_Resume(i8* %exn) + unreachable +} diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-ext.mir b/test/CodeGen/AArch64/GlobalISel/legalize-ext.mir index 9907f009d9317..70b55e4ebc66d 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-ext.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-ext.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-fcmp.mir b/test/CodeGen/AArch64/GlobalISel/legalize-fcmp.mir index 72bd613fab3ae..8cdc7b78b1e95 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-fcmp.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-fcmp.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-fneg.mir b/test/CodeGen/AArch64/GlobalISel/legalize-fneg.mir new file mode 100644 index 0000000000000..8b5cbdfa55e39 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/legalize-fneg.mir @@ -0,0 +1,48 @@ +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_fneg_f32() { + entry: + ret void + } + define void @test_fneg_f64() { + entry: + ret void + } +... +--- +name: test_fneg_f32 +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +body: | + bb.1: + liveins: %s0 + ; CHECK-LABEL: name: test_fneg_f32 + ; CHECK: [[VAR:%[0-9]+]](s32) = COPY %s0 + ; CHECK: [[ZERO:%[0-9]+]](s32) = G_FCONSTANT float -0.000000e+00 + ; CHECK: [[RES:%[0-9]+]](s32) = G_FSUB [[ZERO]], [[VAR]] + ; CHECK: %s0 = COPY [[RES]](s32) + %0(s32) = COPY %s0 + %1(s32) = G_FNEG %0 + %s0 = COPY %1(s32) +... +--- +name: test_fneg_f64 +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +body: | + bb.1: + liveins: %d0 + ; CHECK-LABEL: name: test_fneg_f64 + ; CHECK: [[VAR:%[0-9]+]](s64) = COPY %d0 + ; CHECK: [[ZERO:%[0-9]+]](s64) = G_FCONSTANT double -0.000000e+00 + ; CHECK: [[RES:%[0-9]+]](s64) = G_FSUB [[ZERO]], [[VAR]] + ; CHECK: %d0 = COPY [[RES]](s64) + %0(s64) = COPY %d0 + %1(s64) = G_FNEG %0 + %d0 = COPY %1(s64) +... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-fptoi.mir b/test/CodeGen/AArch64/GlobalISel/legalize-fptoi.mir new file mode 100644 index 0000000000000..f79d0382ea7c4 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/legalize-fptoi.mir @@ -0,0 +1,201 @@ +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + + define void @test_fptosi_s32_s32() { ret void } + define void @test_fptoui_s32_s32() { ret void } + define void @test_fptosi_s32_s64() { ret void } + define void @test_fptoui_s32_s64() { ret void } + + define void @test_fptosi_s64_s32() { ret void } + define void @test_fptoui_s64_s32() { ret void } + define void @test_fptosi_s64_s64() { ret void } + define void @test_fptoui_s64_s64() { ret void } + + define void @test_fptosi_s1_s32() { ret void } + define void @test_fptoui_s1_s32() { ret void } + + define void @test_fptosi_s8_s64() { ret void } + define void @test_fptoui_s8_s64() { ret void } + + define void @test_fptosi_s16_s32() { ret void } + define void @test_fptoui_s16_s32() { ret void } +... + +--- +name: test_fptosi_s32_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_fptosi_s32_s32 + ; CHECK: %1(s32) = G_FPTOSI %0 + %1:_(s32) = G_FPTOSI %0 +... + +--- +name: test_fptoui_s32_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_fptoui_s32_s32 + ; CHECK: %1(s32) = G_FPTOUI %0 + %1:_(s32) = G_FPTOUI %0 +... + +--- +name: test_fptosi_s32_s64 +body: | + bb.0: + liveins: %x0 + %0:_(s64) = COPY %x0 + + ; CHECK-LABEL: name: test_fptosi_s32_s64 + ; CHECK: %1(s32) = G_FPTOSI %0 + %1:_(s32) = G_FPTOSI %0 +... + +--- +name: test_fptoui_s32_s64 +body: | + bb.0: + liveins: %x0 + %0:_(s64) = COPY %x0 + + ; CHECK-LABEL: name: test_fptoui_s32_s64 + ; CHECK: %1(s32) = G_FPTOUI %0 + %1:_(s32) = G_FPTOUI %0 +... + +--- +name: test_fptosi_s64_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_fptosi_s64_s32 + ; CHECK: %1(s64) = G_FPTOSI %0 + %1:_(s64) = G_FPTOSI %0 +... + +--- +name: test_fptoui_s64_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_fptoui_s64_s32 + ; CHECK: %1(s64) = G_FPTOUI %0 + %1:_(s64) = G_FPTOUI %0 +... + +--- +name: test_fptosi_s64_s64 +body: | + bb.0: + liveins: %x0 + %0:_(s64) = COPY %x0 + + ; CHECK-LABEL: name: test_fptosi_s64_s64 + ; CHECK: %1(s64) = G_FPTOSI %0 + %1:_(s64) = G_FPTOSI %0 +... + +--- +name: test_fptoui_s64_s64 +body: | + bb.0: + liveins: %x0 + %0:_(s64) = COPY %x0 + + ; CHECK-LABEL: name: test_fptoui_s64_s64 + ; CHECK: %1(s64) = G_FPTOUI %0 + %1:_(s64) = G_FPTOUI %0 +... + + + +--- +name: test_fptosi_s1_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_fptosi_s1_s32 + ; CHECK: %2(s32) = G_FPTOSI %0 + ; CHECK: %1(s1) = G_TRUNC %2 + %1:_(s1) = G_FPTOSI %0 +... + +--- +name: test_fptoui_s1_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_fptoui_s1_s32 + ; CHECK: %2(s32) = G_FPTOUI %0 + ; CHECK: %1(s1) = G_TRUNC %2 + %1:_(s1) = G_FPTOUI %0 +... + +--- +name: test_fptosi_s8_s64 +body: | + bb.0: + liveins: %x0 + %0:_(s64) = COPY %x0 + + ; CHECK-LABEL: name: test_fptosi_s8_s64 + ; CHECK: %2(s32) = G_FPTOSI %0 + ; CHECK: %1(s8) = G_TRUNC %2 + %1:_(s8) = G_FPTOSI %0 +... + +--- +name: test_fptoui_s8_s64 +body: | + bb.0: + liveins: %x0 + %0:_(s64) = COPY %x0 + + ; CHECK-LABEL: name: test_fptoui_s8_s64 + ; CHECK: %2(s32) = G_FPTOUI %0 + ; CHECK: %1(s8) = G_TRUNC %2 + %1:_(s8) = G_FPTOUI %0 +... + +--- +name: test_fptosi_s16_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_fptosi_s16_s32 + ; CHECK: %2(s32) = G_FPTOSI %0 + ; CHECK: %1(s16) = G_TRUNC %2 + %1:_(s16) = G_FPTOSI %0 +... + +--- +name: test_fptoui_s16_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_fptoui_s16_s32 + ; CHECK: %2(s32) = G_FPTOUI %0 + ; CHECK: %1(s16) = G_TRUNC %2 + %1:_(s16) = G_FPTOUI %0 +... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-gep.mir b/test/CodeGen/AArch64/GlobalISel/legalize-gep.mir index 3f11c123ba518..d6ec983c2067b 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-gep.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-gep.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir b/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir new file mode 100644 index 0000000000000..917f181099ec1 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/legalize-inserts.mir @@ -0,0 +1,141 @@ +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_inserts_1() { ret void } + define void @test_inserts_2() { ret void } + define void @test_inserts_3() { ret void } + define void @test_inserts_4() { ret void } + define void @test_inserts_5() { ret void } + define void @test_inserts_6() { ret void } +... + +--- +name: test_inserts_1 +body: | + bb.0: + liveins: %w0 + + ; Low part of insertion wipes out the old register entirely, so %0 gets + ; forwarded to the G_STORE. Hi part is unchanged so (split) G_LOAD gets + ; forwarded. + ; CHECK-LABEL: name: test_inserts_1 + ; CHECK: [[LO:%[0-9]+]](s64) = G_LOAD + ; CHECK: [[HI:%[0-9]+]](s64) = G_LOAD + ; CHECK: G_STORE %0(s64) + ; CHECK: G_STORE [[HI]] + %0:_(s64) = COPY %x0 + %1:_(s32) = COPY %w1 + %2:_(p0) = COPY %x2 + %3:_(s128) = G_LOAD %2(p0) :: (load 16) + %4:_(s128) = G_INSERT %3(s128), %0(s64), 0 + G_STORE %4(s128), %2(p0) :: (store 16) + RET_ReallyLR +... + +--- +name: test_inserts_2 +body: | + bb.0: + liveins: %w0 + + ; Low insertion wipes out the old register entirely, so %0 gets forwarded + ; to the G_STORE again. Second insertion is real. + ; CHECK-LABEL: name: test_inserts_2 + ; CHECK: [[LO:%[0-9]+]](s64) = G_LOAD + ; CHECK: [[HI:%[0-9]+]](s64) = G_LOAD + ; CHECK: [[NEWHI:%[0-9]+]](s64) = G_INSERT [[HI]], %1(s32), 0 + ; CHECK: G_STORE %0(s64) + ; CHECK: G_STORE [[NEWHI]] + %0:_(s64) = COPY %x0 + %1:_(s32) = COPY %w1 + %2:_(p0) = COPY %x2 + %3:_(s128) = G_LOAD %2(p0) :: (load 16) + %4:_(s128) = G_INSERT %3(s128), %0(s64), 0 + %5:_(s128) = G_INSERT %4(s128), %1(s32), 64 + G_STORE %5(s128), %2(p0) :: (store 16) + RET_ReallyLR +... + +--- +name: test_inserts_3 +body: | + bb.0: + liveins: %w0 + + ; I'm not entirely convinced inserting a p0 into an s64 is valid, but it's + ; certainly better than the alternative of directly forwarding the value + ; which would cause a nasty type mismatch. + ; CHECK-LABEL: name: test_inserts_3 + ; CHECK: [[LO:%[0-9]+]](s64) = G_LOAD + ; CHECK: [[HI:%[0-9]+]](s64) = G_LOAD + ; CHECK: [[NEWLO:%[0-9]+]](s64) = G_PTRTOINT %0(p0) + ; CHECK: G_STORE [[NEWLO]](s64) + ; CHECK: G_STORE [[HI]] + %0:_(p0) = COPY %x0 + %1:_(s32) = COPY %w1 + %2:_(p0) = COPY %x2 + %3:_(s128) = G_LOAD %2(p0) :: (load 16) + %4:_(s128) = G_INSERT %3(s128), %0(p0), 0 + G_STORE %4(s128), %2(p0) :: (store 16) + RET_ReallyLR +... + +--- +name: test_inserts_4 +body: | + bb.0: + liveins: %w0 + + ; A narrow insert gets surrounded by a G_ANYEXT/G_TRUNC pair. + ; CHECK-LABEL: name: test_inserts_4 + ; CHECK: [[VALEXT:%[0-9]+]](s32) = G_ANYEXT %1(s8) + ; CHECK: [[VAL:%[0-9]+]](s32) = G_INSERT [[VALEXT]], %0(s1), 0 + ; CHECK: %3(s8) = G_TRUNC [[VAL]](s32) + %0:_(s1) = COPY %w0 + %1:_(s8) = COPY %w1 + %2:_(p0) = COPY %x2 + %3:_(s8) = G_INSERT %1(s8), %0(s1), 0 + G_STORE %3(s8), %2(p0) :: (store 1) + RET_ReallyLR +... + +--- +name: test_inserts_5 +body: | + bb.0: + liveins: %x0, %x1, %x2 + + + ; CHECK-LABEL: name: test_inserts_5 + ; CHECK: [[INS_LO:%[0-9]+]](s32) = G_EXTRACT %2(s64), 0 + ; CHECK: [[VAL_LO:%[0-9]+]](s64) = G_INSERT %0, [[INS_LO]](s32), 32 + ; CHECK: [[INS_HI:%[0-9]+]](s32) = G_EXTRACT %2(s64), 32 + ; CHECK: [[VAL_HI:%[0-9]+]](s64) = G_INSERT %1, [[INS_HI]](s32), 0 + ; CHECK: %4(s128) = G_MERGE_VALUES [[VAL_LO]](s64), [[VAL_HI]](s64) + %0:_(s64) = COPY %x0 + %1:_(s64) = COPY %x1 + %2:_(s64) = COPY %x2 + %3:_(s128) = G_MERGE_VALUES %0, %1 + %4:_(s128) = G_INSERT %3, %2, 32 + RET_ReallyLR +... + +--- +name: test_inserts_6 +body: | + bb.0: + liveins: %x0, %x1, %x2 + + + ; CHECK-LABEL: name: test_inserts_6 + ; CHECK: [[VAL_LO:%[0-9]+]](s64) = G_INSERT %0, %2(s32), 32 + ; CHECK: %4(s128) = G_MERGE_VALUES [[VAL_LO]](s64), %1(s64) + %0:_(s64) = COPY %x0 + %1:_(s64) = COPY %x1 + %2:_(s32) = COPY %w2 + %3:_(s128) = G_MERGE_VALUES %0, %1 + %4:_(s128) = G_INSERT %3, %2, 32 + RET_ReallyLR +... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-itofp.mir b/test/CodeGen/AArch64/GlobalISel/legalize-itofp.mir new file mode 100644 index 0000000000000..69e72bcb1f387 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/legalize-itofp.mir @@ -0,0 +1,206 @@ +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + + define void @test_sitofp_s32_s32() { ret void } + define void @test_uitofp_s32_s32() { ret void } + define void @test_sitofp_s32_s64() { ret void } + define void @test_uitofp_s32_s64() { ret void } + + define void @test_sitofp_s64_s32() { ret void } + define void @test_uitofp_s64_s32() { ret void } + define void @test_sitofp_s64_s64() { ret void } + define void @test_uitofp_s64_s64() { ret void } + + define void @test_sitofp_s32_s1() { ret void } + define void @test_uitofp_s32_s1() { ret void } + + define void @test_sitofp_s64_s8() { ret void } + define void @test_uitofp_s64_s8() { ret void } + + define void @test_sitofp_s32_s16() { ret void } + define void @test_uitofp_s32_s16() { ret void } +... + +--- +name: test_sitofp_s32_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_sitofp_s32_s32 + ; CHECK: %1(s32) = G_SITOFP %0 + %1:_(s32) = G_SITOFP %0 +... + +--- +name: test_uitofp_s32_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_uitofp_s32_s32 + ; CHECK: %1(s32) = G_UITOFP %0 + %1:_(s32) = G_UITOFP %0 +... + +--- +name: test_sitofp_s32_s64 +body: | + bb.0: + liveins: %x0 + %0:_(s64) = COPY %x0 + + ; CHECK-LABEL: name: test_sitofp_s32_s64 + ; CHECK: %1(s32) = G_SITOFP %0 + %1:_(s32) = G_SITOFP %0 +... + +--- +name: test_uitofp_s32_s64 +body: | + bb.0: + liveins: %x0 + %0:_(s64) = COPY %x0 + + ; CHECK-LABEL: name: test_uitofp_s32_s64 + ; CHECK: %1(s32) = G_UITOFP %0 + %1:_(s32) = G_UITOFP %0 +... + +--- +name: test_sitofp_s64_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_sitofp_s64_s32 + ; CHECK: %1(s64) = G_SITOFP %0 + %1:_(s64) = G_SITOFP %0 +... + +--- +name: test_uitofp_s64_s32 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + + ; CHECK-LABEL: name: test_uitofp_s64_s32 + ; CHECK: %1(s64) = G_UITOFP %0 + %1:_(s64) = G_UITOFP %0 +... + +--- +name: test_sitofp_s64_s64 +body: | + bb.0: + liveins: %x0 + %0:_(s64) = COPY %x0 + + ; CHECK-LABEL: name: test_sitofp_s64_s64 + ; CHECK: %1(s64) = G_SITOFP %0 + %1:_(s64) = G_SITOFP %0 +... + +--- +name: test_uitofp_s64_s64 +body: | + bb.0: + liveins: %x0 + %0:_(s64) = COPY %x0 + + ; CHECK-LABEL: name: test_uitofp_s64_s64 + ; CHECK: %1(s64) = G_UITOFP %0 + %1:_(s64) = G_UITOFP %0 +... + + +--- +name: test_sitofp_s32_s1 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + %1:_(s1) = G_TRUNC %0 + + ; CHECK-LABEL: name: test_sitofp_s32_s1 + ; CHECK: %3(s32) = G_SEXT %1 + ; CHECK: %2(s32) = G_SITOFP %3 + %2:_(s32) = G_SITOFP %1 +... + +--- +name: test_uitofp_s32_s1 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + %1:_(s1) = G_TRUNC %0 + + ; CHECK-LABEL: name: test_uitofp_s32_s1 + ; CHECK: %3(s32) = G_ZEXT %1 + ; CHECK: %2(s32) = G_UITOFP %3 + %2:_(s32) = G_UITOFP %1 +... + +--- +name: test_sitofp_s64_s8 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + %1:_(s8) = G_TRUNC %0 + + ; CHECK-LABEL: name: test_sitofp_s64_s8 + ; CHECK: %3(s32) = G_SEXT %1 + ; CHECK: %2(s64) = G_SITOFP %3 + %2:_(s64) = G_SITOFP %1 +... + +--- +name: test_uitofp_s64_s8 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + %1:_(s8) = G_TRUNC %0 + + ; CHECK-LABEL: name: test_uitofp_s64_s8 + ; CHECK: %3(s32) = G_ZEXT %1 + ; CHECK: %2(s64) = G_UITOFP %3 + %2:_(s64) = G_UITOFP %1 +... + +--- +name: test_sitofp_s32_s16 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + %1:_(s16) = G_TRUNC %0 + + ; CHECK-LABEL: name: test_sitofp_s32_s16 + ; CHECK: %3(s32) = G_SEXT %1 + ; CHECK: %2(s32) = G_SITOFP %3 + %2:_(s32) = G_SITOFP %1 +... + +--- +name: test_uitofp_s32_s16 +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + %1:_(s16) = G_TRUNC %0 + + ; CHECK-LABEL: name: test_uitofp_s32_s16 + ; CHECK: %3(s32) = G_ZEXT %1 + ; CHECK: %2(s32) = G_UITOFP %3 + %2:_(s32) = G_UITOFP %1 +... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir b/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir index 6a86686fa4bd1..c806b4a7060d1 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" @@ -24,6 +24,7 @@ registers: - { id: 5, class: _ } - { id: 6, class: _ } - { id: 7, class: _ } + - { id: 8, class: _ } body: | bb.0.entry: liveins: %x0, %x1, %x2, %x3 @@ -51,6 +52,15 @@ body: | ; CHECK: %7(<2 x s32>) = G_LOAD %0(p0) :: (load 8 from %ir.addr) %7(<2 x s32>) = G_LOAD %0(p0) :: (load 8 from %ir.addr) + + ; CHECK: [[OFFSET0:%[0-9]+]](s64) = G_CONSTANT i64 0 + ; CHECK: [[GEP0:%[0-9]+]](p0) = G_GEP %0, [[OFFSET0]](s64) + ; CHECK: [[LOAD0:%[0-9]+]](s64) = G_LOAD [[GEP0]](p0) :: (load 16 from %ir.addr) + ; CHECK: [[OFFSET1:%[0-9]+]](s64) = G_CONSTANT i64 8 + ; CHECK: [[GEP1:%[0-9]+]](p0) = G_GEP %0, [[OFFSET1]](s64) + ; CHECK: [[LOAD1:%[0-9]+]](s64) = G_LOAD [[GEP1]](p0) :: (load 16 from %ir.addr) + ; CHECK: %8(s128) = G_MERGE_VALUES [[LOAD0]](s64), [[LOAD1]](s64) + %8(s128) = G_LOAD %0(p0) :: (load 16 from %ir.addr) ... --- @@ -62,6 +72,8 @@ registers: - { id: 3, class: _ } - { id: 4, class: _ } - { id: 5, class: _ } + - { id: 6, class: _ } + - { id: 7, class: _ } body: | bb.0.entry: liveins: %x0, %x1, %x2, %x3 @@ -70,7 +82,7 @@ body: | %0(p0) = COPY %x0 %1(s32) = COPY %w1 - ; CHECK: [[BIT8:%[0-9]+]](s8) = G_ANYEXT %2(s1) + ; CHECK: [[BIT8:%[0-9]+]](s8) = G_ZEXT %2(s1) ; CHECK: G_STORE [[BIT8]](s8), %0(p0) :: (store 1 into %ir.addr) %2(s1) = G_TRUNC %1 G_STORE %2, %0 :: (store 1 into %ir.addr) @@ -92,4 +104,14 @@ body: | ; CHECK: G_STORE %0(p0), %0(p0) :: (store 8 into %ir.addr) G_STORE %0(p0), %0(p0) :: (store 8 into %ir.addr) + + ; CHECK: [[OFFSET0:%[0-9]+]](s64) = G_CONSTANT i64 0 + ; CHECK: [[GEP0:%[0-9]+]](p0) = G_GEP %0, [[OFFSET0]](s64) + ; CHECK: G_STORE %5(s64), [[GEP0]](p0) :: (store 16 into %ir.addr) + ; CHECK: [[OFFSET1:%[0-9]+]](s64) = G_CONSTANT i64 8 + ; CHECK: [[GEP1:%[0-9]+]](p0) = G_GEP %0, [[OFFSET1]](s64) + ; CHECK: G_STORE %6(s64), [[GEP1]](p0) :: (store 16 into %ir.addr) + %6(s64) = G_PTRTOINT %0(p0) + %7(s128) = G_MERGE_VALUES %5, %6 + G_STORE %7, %0 :: (store 16 into %ir.addr) ... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-mul.mir b/test/CodeGen/AArch64/GlobalISel/legalize-mul.mir index eb642d4b1a748..1ea6e9c292f5b 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-mul.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-mul.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" @@ -7,6 +7,7 @@ entry: ret void } + define void @test_mul_overflow() { ret void } ... --- @@ -22,7 +23,10 @@ body: | bb.0.entry: liveins: %x0, %x1, %x2, %x3 ; CHECK-LABEL: name: test_scalar_mul_small - ; CHECK: %4(s8) = G_MUL %2, %3 + ; CHECK: [[OP0:%.*]](s32) = G_ANYEXT %2(s8) + ; CHECK: [[OP1:%.*]](s32) = G_ANYEXT %3(s8) + ; CHECK: [[RES32:%.*]](s32) = G_MUL [[OP0]], [[OP1]] + ; CHECK: [[RES:%.*]](s8) = G_TRUNC [[RES32]](s32) %0(s64) = COPY %x0 %1(s64) = COPY %x1 @@ -32,3 +36,22 @@ body: | %5(s64) = G_ANYEXT %2 %x0 = COPY %5 ... + + +--- +name: test_mul_overflow +body: | + bb.0: + liveins: %x0, %x1, %w2, %w3 + + %0:_(s64) = COPY %x0 + %1:_(s64) = COPY %x1 + + ; CHECK-LABEL: name: test_mul_overflow + ; CHECK: %2(s64) = G_MUL %0, %1 + ; CHECK: [[HI:%[0-9]+]](s64) = G_SMULH %0, %1 + ; CHECK: [[ZERO:%[0-9]+]](s64) = G_CONSTANT i64 0 + ; CHECK: %3(s1) = G_ICMP intpred(ne), [[HI]](s64), [[ZERO]] + %2:_(s64), %3:_(s1) = G_SMULO %0, %1 + +... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-nonpowerof2eltsvec.mir b/test/CodeGen/AArch64/GlobalISel/legalize-nonpowerof2eltsvec.mir new file mode 100644 index 0000000000000..9928ea54d2c98 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/legalize-nonpowerof2eltsvec.mir @@ -0,0 +1,29 @@ +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_legalize_merge_v3s32() { + ret void + } +... +--- +name: test_legalize_merge_v3s32 +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } + - { id: 3, class: _ } +body: | + bb.0: + liveins: %w0, %w1, %w2 + ; CHECK-LABEL: name: test_legalize_merge_v3s32 + ; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0 + ; CHECK: [[ARG2:%[0-9]+]](s32) = COPY %w1 + ; CHECK: [[ARG3:%[0-9]+]](s32) = COPY %w2 + ; CHECK: (<3 x s32>) = G_MERGE_VALUES [[ARG1]](s32), [[ARG2]](s32), [[ARG3]](s32) + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = COPY %w2 + %3(<3 x s32>) = G_MERGE_VALUES %0(s32), %1(s32), %2(s32) +... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-or.mir b/test/CodeGen/AArch64/GlobalISel/legalize-or.mir index edf10cd411ebe..e8b8509824600 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-or.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-or.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" @@ -22,7 +22,10 @@ body: | bb.0.entry: liveins: %x0, %x1, %x2, %x3 ; CHECK-LABEL: name: test_scalar_or_small - ; CHECK: %4(s8) = G_OR %2, %3 + ; CHECK: [[OP0:%.*]](s32) = G_ANYEXT %2(s8) + ; CHECK: [[OP1:%.*]](s32) = G_ANYEXT %3(s8) + ; CHECK: [[RES32:%.*]](s32) = G_OR [[OP0]], [[OP1]] + ; CHECK: [[RES:%.*]](s8) = G_TRUNC [[RES32]](s32) %0(s64) = COPY %x0 %1(s64) = COPY %x1 diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-pow.mir b/test/CodeGen/AArch64/GlobalISel/legalize-pow.mir new file mode 100644 index 0000000000000..2becc2e134b50 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/legalize-pow.mir @@ -0,0 +1,38 @@ +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_pow() { + entry: + ret void + } +... + +--- +name: test_pow +body: | + bb.0.entry: + liveins: %d0, %d1, %s2, %s3 + + ; CHECK-LABEL: name: test_pow + ; CHECK: hasCalls: true + + %0:_(s64) = COPY %d0 + %1:_(s64) = COPY %d1 + %2:_(s32) = COPY %s2 + %3:_(s32) = COPY %s3 + + ; CHECK: %d0 = COPY %0 + ; CHECK: %d1 = COPY %1 + ; CHECK: BL $pow, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %d0, implicit %d1, implicit-def %d0 + ; CHECK: %4(s64) = COPY %d0 + %4:_(s64) = G_FPOW %0, %1 + + ; CHECK: %s0 = COPY %2 + ; CHECK: %s1 = COPY %3 + ; CHECK: BL $powf, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %s0, implicit %s1, implicit-def %s0 + ; CHECK: %5(s32) = COPY %s0 + %5:_(s32) = G_FPOW %2, %3 + +... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir b/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir index e77f3487609f1..50a4d93cbe20c 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" @@ -45,8 +45,15 @@ body: | ; CHECK: [[RHS32:%[0-9]+]](s32) = G_SEXT %7 ; CHECK: [[QUOT32:%[0-9]+]](s32) = G_SDIV [[LHS32]], [[RHS32]] ; CHECK: [[QUOT:%[0-9]+]](s8) = G_TRUNC [[QUOT32]] - ; CHECK: [[PROD:%[0-9]+]](s8) = G_MUL [[QUOT]], %7 - ; CHECK: [[RES:%[0-9]+]](s8) = G_SUB %6, [[PROD]] + + ; CHECK: [[QUOT32_2:%.*]](s32) = G_ANYEXT [[QUOT]](s8) + ; CHECK: [[RHS32_2:%.*]](s32) = G_ANYEXT %7(s8) + ; CHECK: [[PROD32:%.*]](s32) = G_MUL [[QUOT32_2]], [[RHS32_2]] + ; CHECK: [[PROD:%.*]](s8) = G_TRUNC [[PROD32]](s32) + + ; CHECK: [[LHS32_2:%.*]](s32) = G_ANYEXT %6(s8) + ; CHECK: [[PROD32_2:%.*]](s32) = G_ANYEXT [[PROD]](s8) + ; CHECK: [[RES:%[0-9]+]](s32) = G_SUB [[LHS32_2]], [[PROD32_2]] %6(s8) = G_TRUNC %0 %7(s8) = G_TRUNC %1 %8(s8) = G_SREM %6, %7 diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-shift.mir b/test/CodeGen/AArch64/GlobalISel/legalize-shift.mir new file mode 100644 index 0000000000000..f75a2982a3f2d --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/legalize-shift.mir @@ -0,0 +1,47 @@ +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_shift() { + entry: + ret void + } +... + +--- +name: test_shift +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } + - { id: 3, class: _ } + - { id: 4, class: _ } + - { id: 5, class: _ } + - { id: 6, class: _ } +body: | + bb.0.entry: + liveins: %x0, %x1, %x2, %x3 + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s8) = G_TRUNC %0 + %3(s8) = G_TRUNC %1 + + ; CHECK: [[LHS32:%[0-9]+]](s32) = G_SEXT %2 + ; CHECK: [[RHS32:%[0-9]+]](s32) = G_SEXT %3 + ; CHECK: [[RES32:%[0-9]+]](s32) = G_ASHR [[LHS32]], [[RHS32]] + ; CHECK: %4(s8) = G_TRUNC [[RES32]] + %4(s8) = G_ASHR %2, %3 + + ; CHECK: [[LHS32:%[0-9]+]](s32) = G_ZEXT %2 + ; CHECK: [[RHS32:%[0-9]+]](s32) = G_ZEXT %3 + ; CHECK: [[RES32:%[0-9]+]](s32) = G_LSHR [[LHS32]], [[RHS32]] + ; CHECK: %5(s8) = G_TRUNC [[RES32]] + %5(s8) = G_LSHR %2, %3 + + ; CHECK: [[OP0:%.*]](s32) = G_ANYEXT %2(s8) + ; CHECK: [[OP1:%.*]](s32) = G_ANYEXT %3(s8) + ; CHECK: [[RES32:%.*]](s32) = G_SHL [[OP0]], [[OP1]] + ; CHECK: [[RES:%.*]](s8) = G_TRUNC [[RES32]](s32) + %6(s8) = G_SHL %2, %3 +... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-simple.mir b/test/CodeGen/AArch64/GlobalISel/legalize-simple.mir index 41a9c33bfad84..cd24bccfe7713 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-simple.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-simple.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" @@ -31,103 +31,56 @@ registers: - { id: 14, class: _ } - { id: 15, class: _ } - { id: 16, class: _ } - - { id: 17, class: _ } - - { id: 18, class: _ } - - { id: 19, class: _ } - - { id: 20, class: _ } - - { id: 21, class: _ } - - { id: 22, class: _ } - - { id: 23, class: _ } - - { id: 24, class: _ } - - { id: 25, class: _ } - - { id: 26, class: _ } - - { id: 27, class: _ } - - { id: 28, class: _ } - - { id: 29, class: _ } - - { id: 30, class: _ } - - { id: 31, class: _ } - - { id: 32, class: _ } - - { id: 33, class: _ } - - { id: 34, class: _ } body: | bb.0.entry: liveins: %x0, %x1, %x2, %x3 %0(s64) = COPY %x0 + %1(s1) = G_TRUNC %0 + %2(s8) = G_TRUNC %0 + %3(s16) = G_TRUNC %0 + %4(s32) = G_TRUNC %0 + ; CHECK-LABEL: name: test_simple - ; CHECK: %1(p0) = G_INTTOPTR %0 - ; CHECK: %2(s64) = G_PTRTOINT %1 - %1(p0) = G_INTTOPTR %0 - %2(s64) = G_PTRTOINT %1 + ; CHECK: %5(p0) = G_INTTOPTR %0 + ; CHECK: %6(s64) = G_PTRTOINT %5 + %5(p0) = G_INTTOPTR %0 + %6(s64) = G_PTRTOINT %5 - ; CHECK: G_BRCOND %3(s1), %bb.1.next - %3(s1) = G_TRUNC %0 - G_BRCOND %3, %bb.1.next + ; CHECK: G_BRCOND %1(s1), %bb.1.next + G_BRCOND %1, %bb.1.next bb.1.next: - %4(s32) = G_TRUNC %0 - - ; CHECK: %5(s1) = G_FPTOSI %4 - ; CHECK: %6(s8) = G_FPTOUI %4 - ; CHECK: %7(s16) = G_FPTOSI %4 - ; CHECK: %8(s32) = G_FPTOUI %4 - ; CHECK: %9(s64) = G_FPTOSI %4 - %5(s1) = G_FPTOSI %4 - %6(s8) = G_FPTOUI %4 - %7(s16) = G_FPTOSI %4 - %8(s32) = G_FPTOUI %4 - %9(s64) = G_FPTOSI %4 - ; CHECK: %10(s1) = G_FPTOUI %0 - ; CHECK: %11(s8) = G_FPTOSI %0 - ; CHECK: %12(s16) = G_FPTOUI %0 - ; CHECK: %13(s32) = G_FPTOSI %0 - ; CHECK: %14(s32) = G_FPTOUI %0 - %10(s1) = G_FPTOUI %0 - %11(s8) = G_FPTOSI %0 - %12(s16) = G_FPTOUI %0 - %13(s32) = G_FPTOSI %0 - %14(s32) = G_FPTOUI %0 + ; CHECK: [[LHS:%[0-9]+]](s32) = G_ANYEXT %1(s1) + ; CHECK: [[RHS:%[0-9]+]](s32) = G_ANYEXT %1(s1) + ; CHECK: [[RES:%[0-9]+]](s32) = G_SELECT %1(s1), [[LHS]], [[RHS]] + ; CHECK: %7(s1) = G_TRUNC [[RES]](s32) + %7(s1) = G_SELECT %1, %1, %1 - ; CHECK: %15(s32) = G_UITOFP %5 - ; CHECK: %16(s32) = G_SITOFP %11 - ; CHECK: %17(s32) = G_UITOFP %7 - ; CHECK: %18(s32) = G_SITOFP %4 - ; CHECK: %19(s32) = G_UITOFP %0 - %15(s32) = G_UITOFP %5 - %16(s32) = G_SITOFP %11 - %17(s32) = G_UITOFP %7 - %18(s32) = G_SITOFP %4 - %19(s32) = G_UITOFP %0 + ; CHECK: [[LHS:%[0-9]+]](s32) = G_ANYEXT %2(s8) + ; CHECK: [[RHS:%[0-9]+]](s32) = G_ANYEXT %2(s8) + ; CHECK: [[RES:%[0-9]+]](s32) = G_SELECT %1(s1), [[LHS]], [[RHS]] + ; CHECK: %8(s8) = G_TRUNC [[RES]](s32) + %8(s8) = G_SELECT %1, %2, %2 - ; CHECK: %20(s64) = G_SITOFP %5 - ; CHECK: %21(s64) = G_UITOFP %11 - ; CHECK: %22(s64) = G_SITOFP %7 - ; CHECK: %23(s64) = G_UITOFP %4 - ; CHECK: %24(s64) = G_SITOFP %0 - %20(s64) = G_SITOFP %5 - %21(s64) = G_UITOFP %11 - %22(s64) = G_SITOFP %7 - %23(s64) = G_UITOFP %4 - %24(s64) = G_SITOFP %0 + ; CHECK: [[LHS:%[0-9]+]](s32) = G_ANYEXT %3(s16) + ; CHECK: [[RHS:%[0-9]+]](s32) = G_ANYEXT %3(s16) + ; CHECK: [[RES:%[0-9]+]](s32) = G_SELECT %1(s1), [[LHS]], [[RHS]] + ; CHECK: %9(s16) = G_TRUNC [[RES]](s32) + %9(s16) = G_SELECT %1, %3, %3 - ; CHECK: %25(s1) = G_SELECT %10(s1), %10, %5 - ; CHECK: %26(s8) = G_SELECT %10(s1), %6, %11 - ; CHECK: %27(s16) = G_SELECT %10(s1), %12, %7 - ; CHECK: %28(s32) = G_SELECT %10(s1), %15, %16 - ; CHECK: %29(s64) = G_SELECT %10(s1), %9, %24 - %25(s1) = G_SELECT %10, %10, %5 - %26(s8) = G_SELECT %10, %6, %11 - %27(s16) = G_SELECT %10, %12, %7 - %28(s32) = G_SELECT %10, %15, %16 - %29(s64) = G_SELECT %10, %9, %24 + %10(s32) = G_SELECT %1, %4, %4 + %11(s64) = G_SELECT %1, %0, %0 - ; CHECK: %30(<2 x s32>) = G_BITCAST %9 - ; CHECK: %31(s64) = G_BITCAST %30 - ; CHECK: %32(s32) = G_BITCAST %15 - %30(<2 x s32>) = G_BITCAST %9 - %31(s64) = G_BITCAST %30 - %32(s32) = G_BITCAST %15 - %33(<4 x s8>) = G_BITCAST %15 - %34(<2 x s16>) = G_BITCAST %15 + ; CHECK: %12(<2 x s32>) = G_BITCAST %0 + ; CHECK: %13(s64) = G_BITCAST %12 + ; CHECK: %14(s32) = G_BITCAST %10 + ; CHECK: %15(<4 x s8>) = G_BITCAST %0 + ; CHECK: %16(<2 x s16>) = G_BITCAST %0 + %12(<2 x s32>) = G_BITCAST %0 + %13(s64) = G_BITCAST %12 + %14(s32) = G_BITCAST %10 + %15(<4 x s8>) = G_BITCAST %0 + %16(<2 x s16>) = G_BITCAST %0 ... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-sub.mir b/test/CodeGen/AArch64/GlobalISel/legalize-sub.mir index e5403cb73c372..82a1dd09c1a12 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-sub.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-sub.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" @@ -22,7 +22,10 @@ body: | bb.0.entry: liveins: %x0, %x1, %x2, %x3 ; CHECK-LABEL: name: test_scalar_sub_small - ; CHECK: [[RES:%.*]](s8) = G_SUB %2, %3 + ; CHECK: [[OP0:%.*]](s32) = G_ANYEXT %2(s8) + ; CHECK: [[OP1:%.*]](s32) = G_ANYEXT %3(s8) + ; CHECK: [[RES32:%.*]](s32) = G_SUB [[OP0]], [[OP1]] + ; CHECK: [[RES:%.*]](s8) = G_TRUNC [[RES32]](s32) %0(s64) = COPY %x0 %1(s64) = COPY %x1 diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-vaarg.mir b/test/CodeGen/AArch64/GlobalISel/legalize-vaarg.mir new file mode 100644 index 0000000000000..8bda08d0a1d12 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/legalize-vaarg.mir @@ -0,0 +1,39 @@ +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64--" + define void @test_vaarg() { ret void } +... + +--- +name: test_vaarg +body: | + bb.0: + %0:_(p0) = COPY %x0 + + ; CHECK-LABEL: name: test_vaarg + ; CHECK: [[LIST:%[0-9]+]](p0) = G_LOAD %0(p0) :: (load 8) + ; CHECK: %1(s8) = G_LOAD [[LIST]](p0) :: (load 1, align 8) + ; CHECK: [[SLOTSIZE:%[0-9]+]](s64) = G_CONSTANT i64 8 + ; CHECK: [[NEXT:%[0-9]+]](p0) = G_GEP [[LIST]], [[SLOTSIZE]](s64) + ; CHECK: G_STORE [[NEXT]](p0), %0(p0) :: (store 8) + %1:_(s8) = G_VAARG %0(p0), 1 + + ; CHECK: [[LIST:%[0-9]+]](p0) = G_LOAD %0(p0) :: (load 8) + ; CHECK: %2(s64) = G_LOAD [[LIST]](p0) :: (load 8) + ; CHECK: [[SLOTSIZE:%[0-9]+]](s64) = G_CONSTANT i64 8 + ; CHECK: [[NEXT:%[0-9]+]](p0) = G_GEP [[LIST]], [[SLOTSIZE]](s64) + ; CHECK: G_STORE [[NEXT]](p0), %0(p0) :: (store 8) + %2:_(s64) = G_VAARG %0(p0), 8 + + ; CHECK: [[LIST:%[0-9]+]](p0) = G_LOAD %0(p0) :: (load 8) + ; CHECK: [[ALIGNM1:%[0-9]+]](s64) = G_CONSTANT i64 15 + ; CHECK: [[ALIGNTMP:%[0-9]+]](p0) = G_GEP [[LIST]], [[ALIGNM1]](s64) + ; CHECK: [[LIST:%[0-9]+]](p0) = G_PTR_MASK [[ALIGNTMP]], 4 + ; CHECK: %3(s64) = G_LOAD [[LIST]](p0) :: (load 8, align 16) + ; CHECK: [[SLOTSIZE:%[0-9]+]](s64) = G_CONSTANT i64 8 + ; CHECK: [[NEXT:%[0-9]+]](p0) = G_GEP [[LIST]], [[SLOTSIZE]](s64) + ; CHECK: G_STORE [[NEXT]](p0), %0(p0) :: (store 8) + %3:_(s64) = G_VAARG %0(p0), 16 +... diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-xor.mir b/test/CodeGen/AArch64/GlobalISel/legalize-xor.mir index 919e674965c00..460b3d16f1c0c 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-xor.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-xor.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s --- | target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" @@ -22,7 +22,10 @@ body: | bb.0.entry: liveins: %x0, %x1, %x2, %x3 ; CHECK-LABEL: name: test_scalar_xor_small - ; CHECK: %4(s8) = G_XOR %2, %3 + ; CHECK: [[OP0:%.*]](s32) = G_ANYEXT %2(s8) + ; CHECK: [[OP1:%.*]](s32) = G_ANYEXT %3(s8) + ; CHECK: [[RES32:%.*]](s32) = G_XOR [[OP0]], [[OP1]] + ; CHECK: [[RES:%.*]](s8) = G_TRUNC [[RES32]](s32) %0(s64) = COPY %x0 %1(s64) = COPY %x1 diff --git a/test/CodeGen/AArch64/GlobalISel/no-regclass.mir b/test/CodeGen/AArch64/GlobalISel/no-regclass.mir new file mode 100644 index 0000000000000..6832ce0ee8bde --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/no-regclass.mir @@ -0,0 +1,30 @@ +# RUN: llc -O0 -mtriple=aarch64-apple-ios -global-isel -start-before=legalizer -stop-after=instruction-select %s -o - | FileCheck %s + +# We run the legalizer to combine the trivial EXTRACT_SEQ pair, leaving %1 and +# %2 orphaned after instruction-selection (no instructions define or use +# them). This shouldn't be a problem. + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @unused_reg() { ret void } + +--- +# CHECK-LABEL: name: unused_reg +name: unused_reg +legalized: true +regBankSelected: true +tracksRegLiveness: true + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %w0 = COPY %0 + +body: | + bb.0: + liveins: %w0 + %0:gpr(s32) = COPY %w0 + %1:gpr(s32) = G_SEQUENCE %0(s32), 0 + %2:gpr(s32) = G_EXTRACT %1(s32), 0 + %w0 = COPY %2(s32) +... diff --git a/test/CodeGen/AArch64/GlobalISel/regbankselect-dbg-value.mir b/test/CodeGen/AArch64/GlobalISel/regbankselect-dbg-value.mir new file mode 100644 index 0000000000000..73d4d20547292 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/regbankselect-dbg-value.mir @@ -0,0 +1,45 @@ +# RUN: llc -O0 -mtriple arm64-- -run-pass=regbankselect -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @test_dbg_value() !dbg !5 { + ; Keep the dbg metadata live by referencing it in the IR. + call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !7, metadata !9), !dbg !10 + ret void + } + + declare void @llvm.dbg.value(metadata, i64, metadata, metadata) + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3, !4} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "llvm", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) + !1 = !DIFile(filename: "test.ll", directory: "/tmp") + !2 = !{} + !3 = !{i32 2, !"Dwarf Version", i32 4} + !4 = !{i32 2, !"Debug Info Version", i32 3} + !5 = distinct !DISubprogram(name: "test_dbg_value", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) + !6 = !DISubroutineType(types: !2) + !7 = !DILocalVariable(name: "in", arg: 1, scope: !5, file: !1, line: 1, type: !8) + !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + !9 = !DIExpression() + !10 = !DILocation(line: 1, column: 1, scope: !5) +... + +--- +# CHECK-LABEL: name: test_dbg_value +name: test_dbg_value +legalized: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr } +body: | + bb.0: + liveins: %w0 + %0:_(s32) = COPY %w0 + ; CHECK: DBG_VALUE debug-use %0(s32), debug-use _, !7, !9, debug-location !10 + DBG_VALUE debug-use %0(s32), debug-use _, !7, !9, debug-location !10 + + ; CHECK: DBG_VALUE _, 0, !7, !9, debug-location !10 + DBG_VALUE _, 0, !7, !9, debug-location !10 +... diff --git a/test/CodeGen/AArch64/GlobalISel/regbankselect-default.mir b/test/CodeGen/AArch64/GlobalISel/regbankselect-default.mir index 12162eb54a839..14ee40c941bf0 100644 --- a/test/CodeGen/AArch64/GlobalISel/regbankselect-default.mir +++ b/test/CodeGen/AArch64/GlobalISel/regbankselect-default.mir @@ -622,7 +622,7 @@ body: | ; CHECK: %0(p0) = COPY %x0 ; CHECK: %1(s32) = G_LOAD %0 %0(p0) = COPY %x0 - %1(s32) = G_LOAD %0 + %1(s32) = G_LOAD %0 :: (load 4) ... --- @@ -643,7 +643,7 @@ body: | ; CHECK: G_STORE %1(s32), %0(p0) %0(p0) = COPY %x0 %1(s32) = COPY %w1 - G_STORE %1, %0 + G_STORE %1, %0 :: (store 4) ... --- diff --git a/test/CodeGen/AArch64/GlobalISel/regbankselect-reg_sequence.mir b/test/CodeGen/AArch64/GlobalISel/regbankselect-reg_sequence.mir new file mode 100644 index 0000000000000..15ccf1f5459cf --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/regbankselect-reg_sequence.mir @@ -0,0 +1,25 @@ +# RUN: llc %s -mtriple aarch64-- -o - -run-pass regbankselect | FileCheck %s +--- | + define void @foo() { ret void } +... +--- +# CHECK-LABEL: foo +# Check that we produce a valid mapping for REG_SEQUENCE. +# This used to fail the RegisterBankInfo verify because +# we were using the exclusively the type of the definition +# whereas since REG_SEQUENCE are kind of target opcode +# their definition may not have a type. +# +# CHECK: id: 0, class: dd +name: foo +legalized: true +tracksRegLiveness: true +registers: + - { id: 0, class: dd } +body: | + bb.0: + liveins: %d0, %d1 + + %0 = REG_SEQUENCE %d0, %subreg.dsub0, %d1, %subreg.dsub1 + +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-binop.mir b/test/CodeGen/AArch64/GlobalISel/select-binop.mir new file mode 100644 index 0000000000000..8ae2e1b2eb7d2 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-binop.mir @@ -0,0 +1,1042 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @add_s32_gpr() { ret void } + define void @add_s64_gpr() { ret void } + + define void @add_imm_s32_gpr() { ret void } + define void @add_imm_s64_gpr() { ret void } + + define void @add_imm_s32_gpr_bb() { ret void } + + define void @sub_s32_gpr() { ret void } + define void @sub_s64_gpr() { ret void } + + define void @or_s32_gpr() { ret void } + define void @or_s64_gpr() { ret void } + define void @or_v2s32_fpr() { ret void } + + define void @and_s32_gpr() { ret void } + define void @and_s64_gpr() { ret void } + + define void @shl_s32_gpr() { ret void } + define void @shl_s64_gpr() { ret void } + + define void @lshr_s32_gpr() { ret void } + define void @lshr_s64_gpr() { ret void } + + define void @ashr_s32_gpr() { ret void } + define void @ashr_s64_gpr() { ret void } + + define void @mul_s32_gpr() { ret void } + define void @mul_s64_gpr() { ret void } + + define void @mulh_s64_gpr() { ret void } + + define void @sdiv_s32_gpr() { ret void } + define void @sdiv_s64_gpr() { ret void } + + define void @udiv_s32_gpr() { ret void } + define void @udiv_s64_gpr() { ret void } + + define void @fadd_s32_fpr() { ret void } + define void @fadd_s64_fpr() { ret void } + + define void @fsub_s32_fpr() { ret void } + define void @fsub_s64_fpr() { ret void } + + define void @fmul_s32_fpr() { ret void } + define void @fmul_s64_fpr() { ret void } + + define void @fdiv_s32_fpr() { ret void } + define void @fdiv_s64_fpr() { ret void } + +... + +--- +# Check that we select a 32-bit GPR G_ADD into ADDWrr on GPR32. +# Also check that we constrain the register class of the COPY to GPR32. +# CHECK-LABEL: name: add_s32_gpr +name: add_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = ADDWrr %0, %1 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_ADD %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as add_s32_gpr, for 64-bit operations. +# CHECK-LABEL: name: add_s64_gpr +name: add_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = ADDXrr %0, %1 +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_ADD %0, %1 + %x0 = COPY %2(s64) +... + +--- +# CHECK-LABEL: name: add_imm_s32_gpr +name: add_imm_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32sp } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr32sp } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %2 = ADDWri %0, 1, 0 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = G_CONSTANT i32 1 + %2(s32) = G_ADD %0, %1 + %w0 = COPY %2(s32) +... + +--- +# CHECK-LABEL: name: add_imm_s64_gpr +name: add_imm_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr64sp } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %2 = ADDXri %0, 1, 0 +body: | + bb.0: + liveins: %x0, %w1 + + %0(s64) = COPY %x0 + %1(s64) = G_CONSTANT i32 1 + %2(s64) = G_ADD %0, %1 + %x0 = COPY %2(s64) +... + +--- +# CHECK-LABEL: name: add_imm_s32_gpr_bb +name: add_imm_s32_gpr_bb +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32sp } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr32sp } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: bb.1: +# CHECK: %2 = ADDWri %0, 1, 0 +body: | + bb.0: + liveins: %w0, %w1 + successors: %bb.1 + + %0(s32) = COPY %w0 + %1(s32) = G_CONSTANT i32 1 + G_BR %bb.1 + + bb.1: + %2(s32) = G_ADD %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as add_s32_gpr, for G_SUB operations. +# CHECK-LABEL: name: sub_s32_gpr +name: sub_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = SUBSWrr %0, %1, implicit-def %nzcv +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_SUB %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as add_s64_gpr, for G_SUB operations. +# CHECK-LABEL: name: sub_s64_gpr +name: sub_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = SUBSXrr %0, %1, implicit-def %nzcv +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_SUB %0, %1 + %x0 = COPY %2(s64) +... + +--- +# Same as add_s32_gpr, for G_OR operations. +# CHECK-LABEL: name: or_s32_gpr +name: or_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = ORRWrr %0, %1 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_OR %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as add_s64_gpr, for G_OR operations. +# CHECK-LABEL: name: or_s64_gpr +name: or_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = ORRXrr %0, %1 +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_OR %0, %1 + %x0 = COPY %2(s64) +... + +--- +# 64-bit G_OR on vector registers. +# CHECK-LABEL: name: or_v2s32_fpr +name: or_v2s32_fpr +legalized: true +regBankSelected: true +# +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr64 } +# CHECK-NEXT: - { id: 1, class: fpr64 } +# CHECK-NEXT: - { id: 2, class: fpr64 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + - { id: 2, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = COPY %d1 +# The actual OR does not matter as long as it is operating +# on 64-bit width vector. +# CHECK: %2 = ORRv8i8 %0, %1 +body: | + bb.0: + liveins: %d0, %d1 + + %0(<2 x s32>) = COPY %d0 + %1(<2 x s32>) = COPY %d1 + %2(<2 x s32>) = G_OR %0, %1 + %d0 = COPY %2(<2 x s32>) +... + +--- +# Same as add_s32_gpr, for G_AND operations. +# CHECK-LABEL: name: and_s32_gpr +name: and_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = ANDWrr %0, %1 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_AND %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as add_s64_gpr, for G_AND operations. +# CHECK-LABEL: name: and_s64_gpr +name: and_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = ANDXrr %0, %1 +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_AND %0, %1 + %x0 = COPY %2(s64) +... + +--- +# Same as add_s32_gpr, for G_SHL operations. +# CHECK-LABEL: name: shl_s32_gpr +name: shl_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = LSLVWr %0, %1 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_SHL %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as add_s64_gpr, for G_SHL operations. +# CHECK-LABEL: name: shl_s64_gpr +name: shl_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = LSLVXr %0, %1 +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_SHL %0, %1 + %x0 = COPY %2(s64) +... + +--- +# Same as add_s32_gpr, for G_LSHR operations. +# CHECK-LABEL: name: lshr_s32_gpr +name: lshr_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = LSRVWr %0, %1 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_LSHR %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as add_s64_gpr, for G_LSHR operations. +# CHECK-LABEL: name: lshr_s64_gpr +name: lshr_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = LSRVXr %0, %1 +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_LSHR %0, %1 + %x0 = COPY %2(s64) +... + +--- +# Same as add_s32_gpr, for G_ASHR operations. +# CHECK-LABEL: name: ashr_s32_gpr +name: ashr_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = ASRVWr %0, %1 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_ASHR %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as add_s64_gpr, for G_ASHR operations. +# CHECK-LABEL: name: ashr_s64_gpr +name: ashr_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = ASRVXr %0, %1 +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_ASHR %0, %1 + %x0 = COPY %2(s64) +... + +--- +# Check that we select s32 GPR G_MUL. This is trickier than other binops because +# there is only MADDWrrr, and we have to use the WZR physreg. +# CHECK-LABEL: name: mul_s32_gpr +name: mul_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = MADDWrrr %0, %1, %wzr +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_MUL %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as mul_s32_gpr for the s64 type. +# CHECK-LABEL: name: mul_s64_gpr +name: mul_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = MADDXrrr %0, %1, %xzr +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_MUL %0, %1 + %x0 = COPY %2(s64) +... + +--- +# Same as mul_s32_gpr for the s64 type. +# CHECK-LABEL: name: mulh_s64_gpr +name: mulh_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +# CHECK-NEXT: - { id: 3, class: gpr64 } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = SMULHrr %0, %1 +# CHECK: %3 = UMULHrr %0, %1 +body: | + bb.0: + liveins: %x0, %x1 + + %0:gpr(s64) = COPY %x0 + %1:gpr(s64) = COPY %x1 + %2:gpr(s64) = G_SMULH %0, %1 + %3:gpr(s64) = G_UMULH %0, %1 + %x0 = COPY %2(s64) + %x0 = COPY %3(s64) +... + +--- +# Same as add_s32_gpr, for G_SDIV operations. +# CHECK-LABEL: name: sdiv_s32_gpr +name: sdiv_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = SDIVWr %0, %1 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_SDIV %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as add_s64_gpr, for G_SDIV operations. +# CHECK-LABEL: name: sdiv_s64_gpr +name: sdiv_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = SDIVXr %0, %1 +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_SDIV %0, %1 + %x0 = COPY %2(s64) +... + +--- +# Same as add_s32_gpr, for G_UDIV operations. +# CHECK-LABEL: name: udiv_s32_gpr +name: udiv_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = UDIVWr %0, %1 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_UDIV %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as add_s64_gpr, for G_UDIV operations. +# CHECK-LABEL: name: udiv_s64_gpr +name: udiv_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = UDIVXr %0, %1 +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_UDIV %0, %1 + %x0 = COPY %2(s64) +... + +--- +# Check that we select a s32 FPR G_FADD into FADDSrr. +# CHECK-LABEL: name: fadd_s32_fpr +name: fadd_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: fpr32 } +# CHECK-NEXT: - { id: 2, class: fpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + - { id: 2, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %s0 +# CHECK: %1 = COPY %s1 +# CHECK: %2 = FADDSrr %0, %1 +body: | + bb.0: + liveins: %s0, %s1 + + %0(s32) = COPY %s0 + %1(s32) = COPY %s1 + %2(s32) = G_FADD %0, %1 + %s0 = COPY %2(s32) +... + +--- +# CHECK-LABEL: name: fadd_s64_fpr +name: fadd_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr64 } +# CHECK-NEXT: - { id: 1, class: fpr64 } +# CHECK-NEXT: - { id: 2, class: fpr64 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + - { id: 2, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = COPY %d1 +# CHECK: %2 = FADDDrr %0, %1 +body: | + bb.0: + liveins: %d0, %d1 + + %0(s64) = COPY %d0 + %1(s64) = COPY %d1 + %2(s64) = G_FADD %0, %1 + %d0 = COPY %2(s64) +... + +--- +# CHECK-LABEL: name: fsub_s32_fpr +name: fsub_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: fpr32 } +# CHECK-NEXT: - { id: 2, class: fpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + - { id: 2, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %s0 +# CHECK: %1 = COPY %s1 +# CHECK: %2 = FSUBSrr %0, %1 +body: | + bb.0: + liveins: %s0, %s1 + + %0(s32) = COPY %s0 + %1(s32) = COPY %s1 + %2(s32) = G_FSUB %0, %1 + %s0 = COPY %2(s32) +... + +--- +# CHECK-LABEL: name: fsub_s64_fpr +name: fsub_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr64 } +# CHECK-NEXT: - { id: 1, class: fpr64 } +# CHECK-NEXT: - { id: 2, class: fpr64 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + - { id: 2, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = COPY %d1 +# CHECK: %2 = FSUBDrr %0, %1 +body: | + bb.0: + liveins: %d0, %d1 + + %0(s64) = COPY %d0 + %1(s64) = COPY %d1 + %2(s64) = G_FSUB %0, %1 + %d0 = COPY %2(s64) +... + +--- +# CHECK-LABEL: name: fmul_s32_fpr +name: fmul_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: fpr32 } +# CHECK-NEXT: - { id: 2, class: fpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + - { id: 2, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %s0 +# CHECK: %1 = COPY %s1 +# CHECK: %2 = FMULSrr %0, %1 +body: | + bb.0: + liveins: %s0, %s1 + + %0(s32) = COPY %s0 + %1(s32) = COPY %s1 + %2(s32) = G_FMUL %0, %1 + %s0 = COPY %2(s32) +... + +--- +# CHECK-LABEL: name: fmul_s64_fpr +name: fmul_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr64 } +# CHECK-NEXT: - { id: 1, class: fpr64 } +# CHECK-NEXT: - { id: 2, class: fpr64 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + - { id: 2, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = COPY %d1 +# CHECK: %2 = FMULDrr %0, %1 +body: | + bb.0: + liveins: %d0, %d1 + + %0(s64) = COPY %d0 + %1(s64) = COPY %d1 + %2(s64) = G_FMUL %0, %1 + %d0 = COPY %2(s64) +... + +--- +# CHECK-LABEL: name: fdiv_s32_fpr +name: fdiv_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: fpr32 } +# CHECK-NEXT: - { id: 2, class: fpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + - { id: 2, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %s0 +# CHECK: %1 = COPY %s1 +# CHECK: %2 = FDIVSrr %0, %1 +body: | + bb.0: + liveins: %s0, %s1 + + %0(s32) = COPY %s0 + %1(s32) = COPY %s1 + %2(s32) = G_FDIV %0, %1 + %s0 = COPY %2(s32) +... + +--- +# CHECK-LABEL: name: fdiv_s64_fpr +name: fdiv_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr64 } +# CHECK-NEXT: - { id: 1, class: fpr64 } +# CHECK-NEXT: - { id: 2, class: fpr64 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + - { id: 2, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = COPY %d1 +# CHECK: %2 = FDIVDrr %0, %1 +body: | + bb.0: + liveins: %d0, %d1 + + %0(s64) = COPY %d0 + %1(s64) = COPY %d1 + %2(s64) = G_FDIV %0, %1 + %d0 = COPY %2(s64) +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir b/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir new file mode 100644 index 0000000000000..5ca63dbc214d5 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir @@ -0,0 +1,212 @@ +# RUN: llc -O0 -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @bitcast_s32_gpr() { ret void } + define void @bitcast_s32_fpr() { ret void } + define void @bitcast_s32_gpr_fpr() { ret void } + define void @bitcast_s32_fpr_gpr() { ret void } + define void @bitcast_s64_gpr() { ret void } + define void @bitcast_s64_fpr() { ret void } + define void @bitcast_s64_gpr_fpr() { ret void } + define void @bitcast_s64_fpr_gpr() { ret void } +... + +--- +# CHECK-LABEL: name: bitcast_s32_gpr +name: bitcast_s32_gpr +legalized: true +regBankSelected: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32all } +# CHECK-NEXT: - { id: 1, class: gpr32all } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s32) = G_BITCAST %0 + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: bitcast_s32_fpr +name: bitcast_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: fpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %s0 +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %s0 + + %0(s32) = COPY %s0 + %1(s32) = G_BITCAST %0 + %s0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: bitcast_s32_gpr_fpr +name: bitcast_s32_gpr_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32all } +# CHECK-NEXT: - { id: 1, class: fpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s32) = G_BITCAST %0 + %s0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: bitcast_s32_fpr_gpr +name: bitcast_s32_fpr_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32all } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %s0 +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %s0 + + %0(s32) = COPY %s0 + %1(s32) = G_BITCAST %0 + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: bitcast_s64_gpr +name: bitcast_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64all } +# CHECK-NEXT: - { id: 1, class: gpr64all } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %x0 + + %0(s64) = COPY %x0 + %1(s64) = G_BITCAST %0 + %x0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: bitcast_s64_fpr +name: bitcast_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr64 } +# CHECK-NEXT: - { id: 1, class: fpr64 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %d0 + + %0(s64) = COPY %d0 + %1(s64) = G_BITCAST %0 + %d0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: bitcast_s64_gpr_fpr +name: bitcast_s64_gpr_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64all } +# CHECK-NEXT: - { id: 1, class: fpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %x0 + + %0(s64) = COPY %x0 + %1(s64) = G_BITCAST %0 + %d0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: bitcast_s64_fpr_gpr +name: bitcast_s64_fpr_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64all } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %d0 + + %0(s64) = COPY %d0 + %1(s64) = G_BITCAST %0 + %x0 = COPY %1(s64) +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-br.mir b/test/CodeGen/AArch64/GlobalISel/select-br.mir new file mode 100644 index 0000000000000..f46f190260f64 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-br.mir @@ -0,0 +1,71 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @unconditional_br() { ret void } + define void @conditional_br() { ret void } + define void @indirect_br() { ret void } +... + +--- +# CHECK-LABEL: name: unconditional_br +name: unconditional_br +legalized: true +regBankSelected: true + +# CHECK: body: +# CHECK: bb.0: +# CHECK: successors: %bb.0 +# CHECK: B %bb.0 +body: | + bb.0: + successors: %bb.0 + + G_BR %bb.0 +... + +--- +# CHECK-LABEL: name: conditional_br +name: conditional_br +legalized: true +regBankSelected: true + +registers: + - { id: 0, class: gpr } + +# CHECK: body: +# CHECK: bb.0: +# CHECK: TBNZW %0, 0, %bb.1 +# CHECK: B %bb.0 +body: | + bb.0: + successors: %bb.0, %bb.1 + %0(s1) = COPY %w0 + G_BRCOND %0(s1), %bb.1 + G_BR %bb.0 + + bb.1: +... + +--- +# CHECK-LABEL: name: indirect_br +name: indirect_br +legalized: true +regBankSelected: true + +registers: + - { id: 0, class: gpr } + +# CHECK: body: +# CHECK: bb.0: +# CHECK: %0 = COPY %x0 +# CHECK: BR %0 +body: | + bb.0: + successors: %bb.0, %bb.1 + %0(p0) = COPY %x0 + G_BRINDIRECT %0(p0) + + bb.1: +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-cbz.mir b/test/CodeGen/AArch64/GlobalISel/select-cbz.mir new file mode 100644 index 0000000000000..2decb994b967b --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-cbz.mir @@ -0,0 +1,108 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + define void @cbz_s32() { ret void } + define void @cbz_s64() { ret void } + define void @cbnz_s32() { ret void } + define void @cbnz_s64() { ret void } +... + +--- +# CHECK-LABEL: name: cbz_s32 +name: cbz_s32 +legalized: true +regBankSelected: true + +# CHECK: body: +# CHECK: bb.0: +# CHECK: %0 = COPY %w0 +# CHECK: CBZW %0, %bb.1 +# CHECK: B %bb.0 +body: | + bb.0: + liveins: %w0 + successors: %bb.0, %bb.1 + + %0:gpr(s32) = COPY %w0 + %1:gpr(s32) = G_CONSTANT i32 0 + %2:gpr(s1) = G_ICMP intpred(eq), %0, %1 + G_BRCOND %2(s1), %bb.1 + G_BR %bb.0 + + bb.1: +... + +--- +# CHECK-LABEL: name: cbz_s64 +name: cbz_s64 +legalized: true +regBankSelected: true + +# CHECK: body: +# CHECK: bb.0: +# CHECK: %0 = COPY %x0 +# CHECK: CBZX %0, %bb.1 +# CHECK: B %bb.0 +body: | + bb.0: + liveins: %x0 + successors: %bb.0, %bb.1 + + %0:gpr(s64) = COPY %x0 + %1:gpr(s64) = G_CONSTANT i64 0 + %2:gpr(s1) = G_ICMP intpred(eq), %0, %1 + G_BRCOND %2(s1), %bb.1 + G_BR %bb.0 + + bb.1: +... + +--- +# CHECK-LABEL: name: cbnz_s32 +name: cbnz_s32 +legalized: true +regBankSelected: true + +# CHECK: body: +# CHECK: bb.0: +# CHECK: %0 = COPY %w0 +# CHECK: CBNZW %0, %bb.1 +# CHECK: B %bb.0 +body: | + bb.0: + liveins: %w0 + successors: %bb.0, %bb.1 + + %0:gpr(s32) = COPY %w0 + %1:gpr(s32) = G_CONSTANT i32 0 + %2:gpr(s1) = G_ICMP intpred(ne), %0, %1 + G_BRCOND %2(s1), %bb.1 + G_BR %bb.0 + + bb.1: +... + +--- +# CHECK-LABEL: name: cbnz_s64 +name: cbnz_s64 +legalized: true +regBankSelected: true + +# CHECK: body: +# CHECK: bb.0: +# CHECK: %0 = COPY %x0 +# CHECK: CBNZX %0, %bb.1 +# CHECK: B %bb.0 +body: | + bb.0: + liveins: %x0 + successors: %bb.0, %bb.1 + + %0:gpr(s64) = COPY %x0 + %1:gpr(s64) = G_CONSTANT i64 0 + %2:gpr(s1) = G_ICMP intpred(ne), %0, %1 + G_BRCOND %2(s1), %bb.1 + G_BR %bb.0 + + bb.1: +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-constant.mir b/test/CodeGen/AArch64/GlobalISel/select-constant.mir new file mode 100644 index 0000000000000..1a5bac9fb7d6f --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-constant.mir @@ -0,0 +1,77 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define i32 @const_s32() { ret i32 42 } + define i64 @const_s64() { ret i64 1234567890123 } + + define i32 @fconst_s32() { ret i32 42 } + define i64 @fconst_s64() { ret i64 1234567890123 } +... + +--- +# CHECK-LABEL: name: const_s32 +name: const_s32 +legalized: true +regBankSelected: true +registers: + - { id: 0, class: gpr } + +# CHECK: body: +# CHECK: %0 = MOVi32imm 42 +body: | + bb.0: + %0(s32) = G_CONSTANT i32 42 + %w0 = COPY %0(s32) +... + +--- +# CHECK-LABEL: name: const_s64 +name: const_s64 +legalized: true +regBankSelected: true +registers: + - { id: 0, class: gpr } + +# CHECK: body: +# CHECK: %0 = MOVi64imm 1234567890123 +body: | + bb.0: + %0(s64) = G_CONSTANT i64 1234567890123 + %x0 = COPY %0(s64) +... + +--- +# CHECK-LABEL: name: fconst_s32 +name: fconst_s32 +legalized: true +regBankSelected: true +registers: + - { id: 0, class: fpr } + +# CHECK: body: +# CHECK: [[TMP:%[0-9]+]] = MOVi32imm 1080033280 +# CHECK: %0 = COPY [[TMP]] +body: | + bb.0: + %0(s32) = G_FCONSTANT float 3.5 + %s0 = COPY %0(s32) +... + +--- +# CHECK-LABEL: name: fconst_s64 +name: fconst_s64 +legalized: true +regBankSelected: true +registers: + - { id: 0, class: fpr } + +# CHECK: body: +# CHECK: [[TMP:%[0-9]+]] = MOVi64imm 4607182418800017408 +# CHECK: %0 = COPY [[TMP]] +body: | + bb.0: + %0(s64) = G_FCONSTANT double 1.0 + %d0 = COPY %0(s64) +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-dbg-value.mir b/test/CodeGen/AArch64/GlobalISel/select-dbg-value.mir new file mode 100644 index 0000000000000..2f36ec8d2aaa9 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-dbg-value.mir @@ -0,0 +1,69 @@ +# RUN: llc -O0 -mtriple arm64-- -run-pass=instruction-select -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @test_dbg_value(i32 %a) !dbg !5 { + %tmp0 = add i32 %a, %a + call void @llvm.dbg.value(metadata i32 %tmp0, i64 0, metadata !7, metadata !9), !dbg !10 + ret void + } + + define void @test_dbg_value_dead(i32 %a) !dbg !5 { + call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !7, metadata !9), !dbg !10 + ret void + } + + declare void @llvm.dbg.value(metadata, i64, metadata, metadata) + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3, !4} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "llvm", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) + !1 = !DIFile(filename: "test.ll", directory: "/tmp") + !2 = !{} + !3 = !{i32 2, !"Dwarf Version", i32 4} + !4 = !{i32 2, !"Debug Info Version", i32 3} + !5 = distinct !DISubprogram(name: "test_dbg_value", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) + !6 = !DISubroutineType(types: !2) + !7 = !DILocalVariable(name: "in", arg: 1, scope: !5, file: !1, line: 1, type: !8) + !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + !9 = !DIExpression() + !10 = !DILocation(line: 1, column: 1, scope: !5) +... + +--- +# CHECK-LABEL: name: test_dbg_value +name: test_dbg_value +legalized: true +regBankSelected: true +body: | + bb.0: + liveins: %w0 + %0:gpr(s32) = COPY %w0 + %1:gpr(s32) = G_ADD %0, %0 + %w0 = COPY %1(s32) + + ; CHECK: %0 = COPY %w0 + ; CHECK-NEXT: %1 = ADDWrr %0, %0 + ; CHECK-NEXT: %w0 = COPY %1 + ; CHECK-NEXT: DBG_VALUE debug-use %1, debug-use _, !7, !9, debug-location !10 + + DBG_VALUE debug-use %1(s32), debug-use _, !7, !9, debug-location !10 +... + +--- +# CHECK-LABEL: name: test_dbg_value_dead +name: test_dbg_value_dead +legalized: true +regBankSelected: true +body: | + bb.0: + liveins: %w0 + %0:gpr(s32) = COPY %w0 + + ; CHECK-NOT: COPY + ; CHECK: DBG_VALUE debug-use _, debug-use _, !7, !9, debug-location !10 + + DBG_VALUE debug-use %0(s32), debug-use _, !7, !9, debug-location !10 +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-fp-casts.mir b/test/CodeGen/AArch64/GlobalISel/select-fp-casts.mir new file mode 100644 index 0000000000000..fbb11a1c7a4c6 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-fp-casts.mir @@ -0,0 +1,478 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @fptrunc() { ret void } + define void @fpext() { ret void } + + define void @sitofp_s32_s32_fpr() { ret void } + define void @sitofp_s32_s64_fpr() { ret void } + define void @sitofp_s64_s32_fpr() { ret void } + define void @sitofp_s64_s64_fpr() { ret void } + + define void @uitofp_s32_s32_fpr() { ret void } + define void @uitofp_s32_s64_fpr() { ret void } + define void @uitofp_s64_s32_fpr() { ret void } + define void @uitofp_s64_s64_fpr() { ret void } + + define void @fptosi_s32_s32_gpr() { ret void } + define void @fptosi_s32_s64_gpr() { ret void } + define void @fptosi_s64_s32_gpr() { ret void } + define void @fptosi_s64_s64_gpr() { ret void } + + define void @fptoui_s32_s32_gpr() { ret void } + define void @fptoui_s32_s64_gpr() { ret void } + define void @fptoui_s64_s32_gpr() { ret void } + define void @fptoui_s64_s64_gpr() { ret void } +... + +--- +# CHECK-LABEL: name: fptrunc +name: fptrunc +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK: - { id: 0, class: fpr64 } +# CHECK: - { id: 1, class: fpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = FCVTSDr %0 +body: | + bb.0: + liveins: %d0 + + %0(s64) = COPY %d0 + %1(s32) = G_FPTRUNC %0 + %s0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: fpext +name: fpext +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK: - { id: 0, class: fpr32 } +# CHECK: - { id: 1, class: fpr64 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %s0 +# CHECK: %1 = FCVTDSr %0 +body: | + bb.0: + liveins: %d0 + + %0(s32) = COPY %s0 + %1(s64) = G_FPEXT %0 + %d0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: sitofp_s32_s32_fpr +name: sitofp_s32_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: fpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = SCVTFUWSri %0 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s32) = G_SITOFP %0 + %s0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: sitofp_s32_s64_fpr +name: sitofp_s32_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: fpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = SCVTFUXSri %0 +body: | + bb.0: + liveins: %x0 + + %0(s64) = COPY %x0 + %1(s32) = G_SITOFP %0 + %s0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: sitofp_s64_s32_fpr +name: sitofp_s64_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: fpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = SCVTFUWDri %0 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s64) = G_SITOFP %0 + %d0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: sitofp_s64_s64_fpr +name: sitofp_s64_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: fpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = SCVTFUXDri %0 +body: | + bb.0: + liveins: %x0 + + %0(s64) = COPY %x0 + %1(s64) = G_SITOFP %0 + %d0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: uitofp_s32_s32_fpr +name: uitofp_s32_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: fpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = UCVTFUWSri %0 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s32) = G_UITOFP %0 + %s0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: uitofp_s32_s64_fpr +name: uitofp_s32_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: fpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = UCVTFUXSri %0 +body: | + bb.0: + liveins: %x0 + + %0(s64) = COPY %x0 + %1(s32) = G_UITOFP %0 + %s0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: uitofp_s64_s32_fpr +name: uitofp_s64_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: fpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = UCVTFUWDri %0 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s64) = G_UITOFP %0 + %d0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: uitofp_s64_s64_fpr +name: uitofp_s64_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: fpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = UCVTFUXDri %0 +body: | + bb.0: + liveins: %x0 + + %0(s64) = COPY %x0 + %1(s64) = G_UITOFP %0 + %d0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: fptosi_s32_s32_gpr +name: fptosi_s32_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %s0 +# CHECK: %1 = FCVTZSUWSr %0 +body: | + bb.0: + liveins: %s0 + + %0(s32) = COPY %s0 + %1(s32) = G_FPTOSI %0 + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: fptosi_s32_s64_gpr +name: fptosi_s32_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr64 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = FCVTZSUWDr %0 +body: | + bb.0: + liveins: %d0 + + %0(s64) = COPY %d0 + %1(s32) = G_FPTOSI %0 + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: fptosi_s64_s32_gpr +name: fptosi_s64_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %s0 +# CHECK: %1 = FCVTZSUXSr %0 +body: | + bb.0: + liveins: %s0 + + %0(s32) = COPY %s0 + %1(s64) = G_FPTOSI %0 + %x0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: fptosi_s64_s64_gpr +name: fptosi_s64_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = FCVTZSUXDr %0 +body: | + bb.0: + liveins: %d0 + + %0(s64) = COPY %d0 + %1(s64) = G_FPTOSI %0 + %x0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: fptoui_s32_s32_gpr +name: fptoui_s32_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %s0 +# CHECK: %1 = FCVTZUUWSr %0 +body: | + bb.0: + liveins: %s0 + + %0(s32) = COPY %s0 + %1(s32) = G_FPTOUI %0 + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: fptoui_s32_s64_gpr +name: fptoui_s32_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr64 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = FCVTZUUWDr %0 +body: | + bb.0: + liveins: %d0 + + %0(s64) = COPY %d0 + %1(s32) = G_FPTOUI %0 + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: fptoui_s64_s32_gpr +name: fptoui_s64_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %s0 +# CHECK: %1 = FCVTZUUXSr %0 +body: | + bb.0: + liveins: %s0 + + %0(s32) = COPY %s0 + %1(s64) = G_FPTOUI %0 + %x0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: fptoui_s64_s64_gpr +name: fptoui_s64_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %d0 +# CHECK: %1 = FCVTZUUXDr %0 +body: | + bb.0: + liveins: %d0 + + %0(s64) = COPY %d0 + %1(s64) = G_FPTOUI %0 + %x0 = COPY %1(s64) +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-int-ext.mir b/test/CodeGen/AArch64/GlobalISel/select-int-ext.mir new file mode 100644 index 0000000000000..2ba8b7366252e --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-int-ext.mir @@ -0,0 +1,274 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @anyext_s64_from_s32() { ret void } + define void @anyext_s32_from_s8() { 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 @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 } +... + +--- +# CHECK-LABEL: name: anyext_s64_from_s32 +name: anyext_s64_from_s32 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32all } +# CHECK-NEXT: - { id: 1, class: gpr64all } +# CHECK-NEXT: - { id: 2, class: gpr64all } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %2 = SUBREG_TO_REG 0, %0, 15 +# CHECK: %1 = COPY %2 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s64) = G_ANYEXT %0 + %x0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: anyext_s32_from_s8 +name: anyext_s32_from_s8 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32all } +# CHECK-NEXT: - { id: 1, class: gpr32all } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %w0 + + %0(s8) = COPY %w0 + %1(s32) = G_ANYEXT %0 + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: zext_s64_from_s32 +name: zext_s64_from_s32 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %2 = SUBREG_TO_REG 0, %0, 15 +# CHECK: %1 = UBFMXri %2, 0, 31 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s64) = G_ZEXT %0 + %x0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: zext_s32_from_s16 +name: zext_s32_from_s16 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = UBFMWri %0, 0, 15 +body: | + bb.0: + liveins: %w0 + + %0(s16) = COPY %w0 + %1(s32) = G_ZEXT %0 + %w0 = COPY %1 +... + +--- +# CHECK-LABEL: name: zext_s32_from_s8 +name: zext_s32_from_s8 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = UBFMWri %0, 0, 7 +body: | + bb.0: + liveins: %w0 + + %0(s8) = COPY %w0 + %1(s32) = G_ZEXT %0 + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: zext_s16_from_s8 +name: zext_s16_from_s8 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = UBFMWri %0, 0, 7 +body: | + bb.0: + liveins: %w0 + + %0(s8) = COPY %w0 + %1(s16) = G_ZEXT %0 + %w0 = COPY %1(s16) +... + +--- +# CHECK-LABEL: name: sext_s64_from_s32 +name: sext_s64_from_s32 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %2 = SUBREG_TO_REG 0, %0, 15 +# CHECK: %1 = SBFMXri %2, 0, 31 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s64) = G_SEXT %0 + %x0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: sext_s32_from_s16 +name: sext_s32_from_s16 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = SBFMWri %0, 0, 15 +body: | + bb.0: + liveins: %w0 + + %0(s16) = COPY %w0 + %1(s32) = G_SEXT %0 + %w0 = COPY %1 +... + +--- +# CHECK-LABEL: name: sext_s32_from_s8 +name: sext_s32_from_s8 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = SBFMWri %0, 0, 7 +body: | + bb.0: + liveins: %w0 + + %0(s8) = COPY %w0 + %1(s32) = G_SEXT %0 + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: sext_s16_from_s8 +name: sext_s16_from_s8 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = SBFMWri %0, 0, 7 +body: | + bb.0: + liveins: %w0 + + %0(s8) = COPY %w0 + %1(s16) = G_SEXT %0 + %w0 = COPY %1(s16) +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-int-ptr-casts.mir b/test/CodeGen/AArch64/GlobalISel/select-int-ptr-casts.mir new file mode 100644 index 0000000000000..6537408f6d987 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-int-ptr-casts.mir @@ -0,0 +1,150 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @inttoptr_p0_s64() { ret void } + define void @ptrtoint_s64_p0() { ret void } + define void @ptrtoint_s32_p0() { ret void } + define void @ptrtoint_s16_p0() { ret void } + define void @ptrtoint_s8_p0() { ret void } + define void @ptrtoint_s1_p0() { ret void } +... + +--- +# CHECK-LABEL: name: inttoptr_p0_s64 +name: inttoptr_p0_s64 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64all } +# CHECK-NEXT: - { id: 1, class: gpr64all } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %x0 + %0(s64) = COPY %x0 + %1(p0) = G_INTTOPTR %0 + %x0 = COPY %1(p0) +... + +--- +# CHECK-LABEL: name: ptrtoint_s64_p0 +name: ptrtoint_s64_p0 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %x0 + %0(p0) = COPY %x0 + %1(s64) = G_PTRTOINT %0 + %x0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: ptrtoint_s32_p0 +name: ptrtoint_s32_p0 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %0.sub_32 +body: | + bb.0: + liveins: %x0 + %0(p0) = COPY %x0 + %1(s32) = G_PTRTOINT %0 + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: ptrtoint_s16_p0 +name: ptrtoint_s16_p0 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %0.sub_32 +body: | + bb.0: + liveins: %x0 + %0(p0) = COPY %x0 + %1(s16) = G_PTRTOINT %0 + %w0 = COPY %1(s16) +... + +--- +# CHECK-LABEL: name: ptrtoint_s8_p0 +name: ptrtoint_s8_p0 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %0.sub_32 +body: | + bb.0: + liveins: %x0 + %0(p0) = COPY %x0 + %1(s8) = G_PTRTOINT %0 + %w0 = COPY %1(s8) +... + +--- +# CHECK-LABEL: name: ptrtoint_s1_p0 +name: ptrtoint_s1_p0 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %0.sub_32 +body: | + bb.0: + liveins: %x0 + %0(p0) = COPY %x0 + %1(s1) = G_PTRTOINT %0 + %w0 = COPY %1(s1) +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-load.mir b/test/CodeGen/AArch64/GlobalISel/select-load.mir new file mode 100644 index 0000000000000..9188e2b0c0fcc --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-load.mir @@ -0,0 +1,515 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @load_s64_gpr(i64* %addr) { ret void } + define void @load_s32_gpr(i32* %addr) { ret void } + define void @load_s16_gpr(i16* %addr) { ret void } + define void @load_s8_gpr(i8* %addr) { ret void } + + define void @load_fi_s64_gpr() { + %ptr0 = alloca i64 + ret void + } + + define void @load_gep_128_s64_gpr(i64* %addr) { ret void } + define void @load_gep_512_s32_gpr(i32* %addr) { ret void } + define void @load_gep_64_s16_gpr(i16* %addr) { ret void } + define void @load_gep_1_s8_gpr(i8* %addr) { ret void } + + define void @load_s64_fpr(i64* %addr) { ret void } + define void @load_s32_fpr(i32* %addr) { ret void } + define void @load_s16_fpr(i16* %addr) { ret void } + define void @load_s8_fpr(i8* %addr) { ret void } + + define void @load_gep_8_s64_fpr(i64* %addr) { ret void } + define void @load_gep_16_s32_fpr(i32* %addr) { ret void } + define void @load_gep_64_s16_fpr(i16* %addr) { ret void } + define void @load_gep_32_s8_fpr(i8* %addr) { ret void } + +... + +--- +# CHECK-LABEL: name: load_s64_gpr +name: load_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = LDRXui %0, 0 :: (load 8 from %ir.addr) +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s64) = G_LOAD %0 :: (load 8 from %ir.addr) + %x0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: load_s32_gpr +name: load_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = LDRWui %0, 0 :: (load 4 from %ir.addr) +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s32) = G_LOAD %0 :: (load 4 from %ir.addr) + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: load_s16_gpr +name: load_s16_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = LDRHHui %0, 0 :: (load 2 from %ir.addr) +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s16) = G_LOAD %0 :: (load 2 from %ir.addr) + %w0 = COPY %1(s16) +... + +--- +# CHECK-LABEL: name: load_s8_gpr +name: load_s8_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = LDRBBui %0, 0 :: (load 1 from %ir.addr) +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s8) = G_LOAD %0 :: (load 1 from %ir.addr) + %w0 = COPY %1(s8) +... + +--- +# CHECK-LABEL: name: load_fi_s64_gpr +name: load_fi_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr } +# CHECK-NEXT: - { id: 1, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +stack: + - { id: 0, name: ptr0, offset: 0, size: 8, alignment: 8 } + +# CHECK: body: +# CHECK: %1 = LDRXui %stack.0.ptr0, 0 :: (load 8) +# CHECK: %x0 = COPY %1 +body: | + bb.0: + liveins: %x0 + + %0(p0) = G_FRAME_INDEX %stack.0.ptr0 + %1(s64) = G_LOAD %0 :: (load 8) + %x0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: load_gep_128_s64_gpr +name: load_gep_128_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %3 = LDRXui %0, 16 :: (load 8 from %ir.addr) +# CHECK: %x0 = COPY %3 +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s64) = G_CONSTANT i64 128 + %2(p0) = G_GEP %0, %1 + %3(s64) = G_LOAD %2 :: (load 8 from %ir.addr) + %x0 = COPY %3 +... + +--- +# CHECK-LABEL: name: load_gep_512_s32_gpr +name: load_gep_512_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %3 = LDRWui %0, 128 :: (load 4 from %ir.addr) +# CHECK: %w0 = COPY %3 +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s64) = G_CONSTANT i64 512 + %2(p0) = G_GEP %0, %1 + %3(s32) = G_LOAD %2 :: (load 4 from %ir.addr) + %w0 = COPY %3 +... + +--- +# CHECK-LABEL: name: load_gep_64_s16_gpr +name: load_gep_64_s16_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %3 = LDRHHui %0, 32 :: (load 2 from %ir.addr) +# CHECK: %w0 = COPY %3 +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s64) = G_CONSTANT i64 64 + %2(p0) = G_GEP %0, %1 + %3(s16) = G_LOAD %2 :: (load 2 from %ir.addr) + %w0 = COPY %3 +... + +--- +# CHECK-LABEL: name: load_gep_1_s8_gpr +name: load_gep_1_s8_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %3 = LDRBBui %0, 1 :: (load 1 from %ir.addr) +# CHECK: %w0 = COPY %3 +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s64) = G_CONSTANT i64 1 + %2(p0) = G_GEP %0, %1 + %3(s8) = G_LOAD %2 :: (load 1 from %ir.addr) + %w0 = COPY %3 +... + +--- +# CHECK-LABEL: name: load_s64_fpr +name: load_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: fpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = LDRDui %0, 0 :: (load 8 from %ir.addr) +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s64) = G_LOAD %0 :: (load 8 from %ir.addr) + %d0 = COPY %1(s64) +... + +--- +# CHECK-LABEL: name: load_s32_fpr +name: load_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: fpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = LDRSui %0, 0 :: (load 4 from %ir.addr) +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s32) = G_LOAD %0 :: (load 4 from %ir.addr) + %s0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: load_s16_fpr +name: load_s16_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: fpr16 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = LDRHui %0, 0 :: (load 2 from %ir.addr) +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s16) = G_LOAD %0 :: (load 2 from %ir.addr) + %h0 = COPY %1(s16) +... + +--- +# CHECK-LABEL: name: load_s8_fpr +name: load_s8_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: fpr8 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = LDRBui %0, 0 :: (load 1 from %ir.addr) +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s8) = G_LOAD %0 :: (load 1 from %ir.addr) + %b0 = COPY %1(s8) +... + +--- +# CHECK-LABEL: name: load_gep_8_s64_fpr +name: load_gep_8_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: fpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %3 = LDRDui %0, 1 :: (load 8 from %ir.addr) +# CHECK: %d0 = COPY %3 +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s64) = G_CONSTANT i64 8 + %2(p0) = G_GEP %0, %1 + %3(s64) = G_LOAD %2 :: (load 8 from %ir.addr) + %d0 = COPY %3 +... + +--- +# CHECK-LABEL: name: load_gep_16_s32_fpr +name: load_gep_16_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: fpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %3 = LDRSui %0, 4 :: (load 4 from %ir.addr) +# CHECK: %s0 = COPY %3 +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s64) = G_CONSTANT i64 16 + %2(p0) = G_GEP %0, %1 + %3(s32) = G_LOAD %2 :: (load 4 from %ir.addr) + %s0 = COPY %3 +... + +--- +# CHECK-LABEL: name: load_gep_64_s16_fpr +name: load_gep_64_s16_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: fpr16 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %3 = LDRHui %0, 32 :: (load 2 from %ir.addr) +# CHECK: %h0 = COPY %3 +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s64) = G_CONSTANT i64 64 + %2(p0) = G_GEP %0, %1 + %3(s16) = G_LOAD %2 :: (load 2 from %ir.addr) + %h0 = COPY %3 +... + +--- +# CHECK-LABEL: name: load_gep_32_s8_fpr +name: load_gep_32_s8_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: fpr8 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %3 = LDRBui %0, 32 :: (load 1 from %ir.addr) +# CHECK: %b0 = COPY %3 +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s64) = G_CONSTANT i64 32 + %2(p0) = G_GEP %0, %1 + %3(s8) = G_LOAD %2 :: (load 1 from %ir.addr) + %b0 = COPY %3 +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-muladd.mir b/test/CodeGen/AArch64/GlobalISel/select-muladd.mir new file mode 100644 index 0000000000000..7d5b43bc16d5b --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-muladd.mir @@ -0,0 +1,50 @@ +# RUN: llc -O0 -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @SMADDLrrr_gpr() { ret void } +... + +--- +# CHECK-LABEL: name: SMADDLrrr_gpr +name: SMADDLrrr_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +# CHECK-NEXT: - { id: 3, class: gpr } +# CHECK-NEXT: - { id: 4, class: gpr } +# CHECK-NEXT: - { id: 5, class: gpr } +# CHECK-NEXT: - { id: 6, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + - { id: 4, class: gpr } + - { id: 5, class: gpr } + - { id: 6, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = COPY %w2 +# CHECK: %6 = SMADDLrrr %1, %2, %0 +body: | + bb.0: + liveins: %x0, %w1, %w2 + + %0(s64) = COPY %x0 + %1(s32) = COPY %w1 + %2(s32) = COPY %w2 + %3(s64) = G_SEXT %1 + %4(s64) = G_SEXT %2 + %5(s64) = G_MUL %3, %4 + %6(s64) = G_ADD %0, %5 + %x0 = COPY %6 +... + diff --git a/test/CodeGen/AArch64/GlobalISel/select-property.mir b/test/CodeGen/AArch64/GlobalISel/select-property.mir new file mode 100644 index 0000000000000..86961ac597e17 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-property.mir @@ -0,0 +1,21 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @selected_property() { ret void } +... + +--- +# Check that we set the "selected" property. +# CHECK-LABEL: name: selected_property +# CHECK: legalized: true +# CHECK-NEXT: regBankSelected: true +# CHECK-NEXT: selected: true +name: selected_property +legalized: true +regBankSelected: true +selected: false +body: | + bb.0: +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-store.mir b/test/CodeGen/AArch64/GlobalISel/select-store.mir new file mode 100644 index 0000000000000..9b8f5c566ce0d --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-store.mir @@ -0,0 +1,463 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @store_s64_gpr(i64* %addr) { ret void } + define void @store_s32_gpr(i32* %addr) { ret void } + define void @store_s16_gpr(i16* %addr) { ret void } + define void @store_s8_gpr(i8* %addr) { ret void } + + define void @store_zero_s64_gpr(i64* %addr) { ret void } + define void @store_zero_s32_gpr(i32* %addr) { ret void } + + define void @store_fi_s64_gpr() { + %ptr0 = alloca i64 + ret void + } + + define void @store_gep_128_s64_gpr(i64* %addr) { ret void } + define void @store_gep_512_s32_gpr(i32* %addr) { ret void } + define void @store_gep_64_s16_gpr(i16* %addr) { ret void } + define void @store_gep_1_s8_gpr(i8* %addr) { ret void } + + define void @store_s64_fpr(i64* %addr) { ret void } + define void @store_s32_fpr(i32* %addr) { ret void } + + define void @store_gep_8_s64_fpr(i64* %addr) { ret void } + define void @store_gep_8_s32_fpr(i32* %addr) { ret void } +... + +--- +# CHECK-LABEL: name: store_s64_gpr +name: store_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: STRXui %1, %0, 0 :: (store 8 into %ir.addr) +body: | + bb.0: + liveins: %x0, %x1 + + %0(p0) = COPY %x0 + %1(s64) = COPY %x1 + G_STORE %1, %0 :: (store 8 into %ir.addr) + +... + +--- +# CHECK-LABEL: name: store_s32_gpr +name: store_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %w1 +# CHECK: STRWui %1, %0, 0 :: (store 4 into %ir.addr) +body: | + bb.0: + liveins: %x0, %w1 + + %0(p0) = COPY %x0 + %1(s32) = COPY %w1 + G_STORE %1, %0 :: (store 4 into %ir.addr) + +... + +--- +# CHECK-LABEL: name: store_s16_gpr +name: store_s16_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %w1 +# CHECK: STRHHui %1, %0, 0 :: (store 2 into %ir.addr) +body: | + bb.0: + liveins: %x0, %w1 + + %0(p0) = COPY %x0 + %1(s16) = COPY %w1 + G_STORE %1, %0 :: (store 2 into %ir.addr) + +... + +--- +# CHECK-LABEL: name: store_s8_gpr +name: store_s8_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %w1 +# CHECK: STRBBui %1, %0, 0 :: (store 1 into %ir.addr) +body: | + bb.0: + liveins: %x0, %w1 + + %0(p0) = COPY %x0 + %1(s8) = COPY %w1 + G_STORE %1, %0 :: (store 1 into %ir.addr) + +... + +--- +# CHECK-LABEL: name: store_zero_s64_gpr +name: store_zero_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: STRXui %xzr, %0, 0 :: (store 8 into %ir.addr) +body: | + bb.0: + liveins: %x0, %x1 + + %0(p0) = COPY %x0 + %1(s64) = G_CONSTANT i64 0 + G_STORE %1, %0 :: (store 8 into %ir.addr) + +... + +--- +# CHECK-LABEL: name: store_zero_s32_gpr +name: store_zero_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: STRWui %wzr, %0, 0 :: (store 4 into %ir.addr) +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(s32) = G_CONSTANT i32 0 + G_STORE %1, %0 :: (store 4 into %ir.addr) + +... + +--- +# CHECK-LABEL: name: store_fi_s64_gpr +name: store_fi_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +stack: + - { id: 0, name: ptr0, offset: 0, size: 8, alignment: 8 } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: STRXui %0, %stack.0.ptr0, 0 :: (store 8) +body: | + bb.0: + liveins: %x0 + + %0(p0) = COPY %x0 + %1(p0) = G_FRAME_INDEX %stack.0.ptr0 + G_STORE %0, %1 :: (store 8) +... + +--- +# CHECK-LABEL: name: store_gep_128_s64_gpr +name: store_gep_128_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: gpr } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: STRXui %1, %0, 16 :: (store 8 into %ir.addr) +body: | + bb.0: + liveins: %x0, %x1 + + %0(p0) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_CONSTANT i64 128 + %3(p0) = G_GEP %0, %2 + G_STORE %1, %3 :: (store 8 into %ir.addr) +... + +--- +# CHECK-LABEL: name: store_gep_512_s32_gpr +name: store_gep_512_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: gpr } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %w1 +# CHECK: STRWui %1, %0, 128 :: (store 4 into %ir.addr) +body: | + bb.0: + liveins: %x0, %w1 + + %0(p0) = COPY %x0 + %1(s32) = COPY %w1 + %2(s64) = G_CONSTANT i64 512 + %3(p0) = G_GEP %0, %2 + G_STORE %1, %3 :: (store 4 into %ir.addr) +... + +--- +# CHECK-LABEL: name: store_gep_64_s16_gpr +name: store_gep_64_s16_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: gpr } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %w1 +# CHECK: STRHHui %1, %0, 32 :: (store 2 into %ir.addr) +body: | + bb.0: + liveins: %x0, %w1 + + %0(p0) = COPY %x0 + %1(s16) = COPY %w1 + %2(s64) = G_CONSTANT i64 64 + %3(p0) = G_GEP %0, %2 + G_STORE %1, %3 :: (store 2 into %ir.addr) +... + +--- +# CHECK-LABEL: name: store_gep_1_s8_gpr +name: store_gep_1_s8_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: gpr } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %w1 +# CHECK: STRBBui %1, %0, 1 :: (store 1 into %ir.addr) +body: | + bb.0: + liveins: %x0, %w1 + + %0(p0) = COPY %x0 + %1(s8) = COPY %w1 + %2(s64) = G_CONSTANT i64 1 + %3(p0) = G_GEP %0, %2 + G_STORE %1, %3 :: (store 1 into %ir.addr) +... + +--- +# CHECK-LABEL: name: store_s64_fpr +name: store_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: fpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %d1 +# CHECK: STRDui %1, %0, 0 :: (store 8 into %ir.addr) +body: | + bb.0: + liveins: %x0, %d1 + + %0(p0) = COPY %x0 + %1(s64) = COPY %d1 + G_STORE %1, %0 :: (store 8 into %ir.addr) + +... + +--- +# CHECK-LABEL: name: store_s32_fpr +name: store_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: fpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %s1 +# CHECK: STRSui %1, %0, 0 :: (store 4 into %ir.addr) +body: | + bb.0: + liveins: %x0, %s1 + + %0(p0) = COPY %x0 + %1(s32) = COPY %s1 + G_STORE %1, %0 :: (store 4 into %ir.addr) + +... + +--- +# CHECK-LABEL: name: store_gep_8_s64_fpr +name: store_gep_8_s64_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: fpr64 } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: gpr } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %d1 +# CHECK: STRDui %1, %0, 1 :: (store 8 into %ir.addr) +body: | + bb.0: + liveins: %x0, %d1 + + %0(p0) = COPY %x0 + %1(s64) = COPY %d1 + %2(s64) = G_CONSTANT i64 8 + %3(p0) = G_GEP %0, %2 + G_STORE %1, %3 :: (store 8 into %ir.addr) +... + +--- +# CHECK-LABEL: name: store_gep_8_s32_fpr +name: store_gep_8_s32_fpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +# CHECK-NEXT: - { id: 1, class: fpr32 } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: gpr } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %s1 +# CHECK: STRSui %1, %0, 2 :: (store 4 into %ir.addr) +body: | + bb.0: + liveins: %x0, %s1 + + %0(p0) = COPY %x0 + %1(s32) = COPY %s1 + %2(s64) = G_CONSTANT i64 8 + %3(p0) = G_GEP %0, %2 + G_STORE %1, %3 :: (store 4 into %ir.addr) +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-trunc.mir b/test/CodeGen/AArch64/GlobalISel/select-trunc.mir new file mode 100644 index 0000000000000..fc3546e777f70 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-trunc.mir @@ -0,0 +1,81 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @trunc_s32_s64() { ret void } + define void @trunc_s8_s64() { ret void } + define void @trunc_s1_s32() { ret void } +... + +--- +# CHECK-LABEL: name: trunc_s32_s64 +name: trunc_s32_s64 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %1 = COPY %0.sub_32 +body: | + bb.0: + liveins: %x0 + + %0(s64) = COPY %x0 + %1(s32) = G_TRUNC %0 + %w0 = COPY %1(s32) +... + +--- +# CHECK-LABEL: name: trunc_s8_s64 +name: trunc_s8_s64 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %1 = COPY %0.sub_32 +body: | + bb.0: + liveins: %x0 + + %0(s64) = COPY %x0 + %1(s8) = G_TRUNC %0 + %w0 = COPY %1(s8) +... + +--- +# CHECK-LABEL: name: trunc_s1_s32 +name: trunc_s1_s32 +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + +# CHECK: body: +# CHECK: %1 = COPY %0 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s1) = G_TRUNC %0 + %w0 = COPY %1(s1) +... diff --git a/test/CodeGen/AArch64/GlobalISel/select-xor.mir b/test/CodeGen/AArch64/GlobalISel/select-xor.mir new file mode 100644 index 0000000000000..e787849c8d1bf --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select-xor.mir @@ -0,0 +1,165 @@ +# RUN: llc -O0 -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @xor_s32_gpr() { ret void } + define void @xor_s64_gpr() { ret void } + define void @xor_constant_n1_s32_gpr() { ret void } + define void @xor_constant_n1_s64_gpr() { ret void } + define void @xor_constant_n1_s32_gpr_2bb() { ret void } + +... + +--- +# Check that we select a 32-bit GPR G_XOR into EORWrr on GPR32. +# Also check that we constrain the register class of the COPY to GPR32. +# CHECK-LABEL: name: xor_s32_gpr +name: xor_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = EORWrr %0, %1 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_XOR %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as xor_s64_gpr, for 64-bit operations. +# CHECK-LABEL: name: xor_s64_gpr +name: xor_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = EORXrr %0, %1 +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_XOR %0, %1 + %x0 = COPY %2(s64) +... + +--- +# Check that we select a 32-bit GPR G_XOR into EORWrr on GPR32. +# Also check that we constrain the register class of the COPY to GPR32. +# CHECK-LABEL: name: xor_constant_n1_s32_gpr +name: xor_constant_n1_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %2 = ORNWrr %wzr, %0 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s32) = G_CONSTANT i32 -1 + %2(s32) = G_XOR %0, %1 + %w0 = COPY %2(s32) +... + +--- +# Same as xor_constant_n1_s64_gpr, for 64-bit operations. +# CHECK-LABEL: name: xor_constant_n1_s64_gpr +name: xor_constant_n1_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %2 = ORNXrr %xzr, %0 +body: | + bb.0: + liveins: %x0 + + %0(s64) = COPY %x0 + %1(s64) = G_CONSTANT i64 -1 + %2(s64) = G_XOR %0, %1 + %x0 = COPY %2(s64) +... + +--- +# Check that we can obtain constants from other basic blocks. +# CHECK-LABEL: name: xor_constant_n1_s32_gpr_2bb +name: xor_constant_n1_s32_gpr_2bb +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: B %bb.1 +# CHECK: %0 = COPY %w0 +# CHECK: %2 = ORNWrr %wzr, %0 + +body: | + bb.0: + liveins: %w0, %w1 + successors: %bb.1 + %1(s32) = G_CONSTANT i32 -1 + G_BR %bb.1 + bb.1: + %0(s32) = COPY %w0 + %2(s32) = G_XOR %0, %1 + %w0 = COPY %2(s32) +... diff --git a/test/CodeGen/AArch64/GlobalISel/select.mir b/test/CodeGen/AArch64/GlobalISel/select.mir new file mode 100644 index 0000000000000..8bffa085fdca6 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/select.mir @@ -0,0 +1,311 @@ +# RUN: llc -O0 -mtriple=aarch64-apple-ios -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=IOS +# RUN: llc -O0 -mtriple=aarch64-linux-gnu -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=LINUX-DEFAULT +# RUN: llc -O0 -mtriple=aarch64-linux-gnu -relocation-model=pic -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=LINUX-PIC + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @frame_index() { + %ptr0 = alloca i64 + ret void + } + + define i8* @gep(i8* %in) { ret i8* undef } + + define i8* @ptr_mask(i8* %in) { ret i8* undef } + + @var_local = global i8 0 + define i8* @global_local() { ret i8* undef } + + @var_got = external global i8 + define i8* @global_got() { ret i8* undef } + + define void @icmp() { ret void } + define void @fcmp() { ret void } + + define void @phi() { ret void } + + define void @select() { ret void } +... + +--- +# CHECK-LABEL: name: frame_index +name: frame_index +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64sp } +registers: + - { id: 0, class: gpr } + +stack: + - { id: 0, name: ptr0, offset: 0, size: 8, alignment: 8 } + +# CHECK: body: +# CHECK: %0 = ADDXri %stack.0.ptr0, 0, 0 +body: | + bb.0: + %0(p0) = G_FRAME_INDEX %stack.0.ptr0 + %x0 = COPY %0(p0) +... + +--- +# CHECK-LABEL: name: gep +name: gep +legalized: true +regBankSelected: true +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %1 = MOVi64imm 42 +# CHECK: %2 = ADDXrr %0, %1 +body: | + bb.0: + liveins: %x0 + %0(p0) = COPY %x0 + %1(s64) = G_CONSTANT i64 42 + %2(p0) = G_GEP %0, %1(s64) + %x0 = COPY %2(p0) +... + +--- +# CHECK-LABEL: name: ptr_mask +name: ptr_mask +legalized: true +regBankSelected: true + +# CHECK: body: +# CHECK: %1 = ANDXri %0, 8060 +body: | + bb.0: + liveins: %x0 + %0:gpr(p0) = COPY %x0 + %1:gpr(p0) = G_PTR_MASK %0, 3 + %x0 = COPY %1(p0) +... + +--- +# Global defined in the same linkage unit so no GOT is needed +# CHECK-LABEL: name: global_local +name: global_local +legalized: true +regBankSelected: true +registers: + - { id: 0, class: gpr } + +# CHECK: body: +# IOS: %0 = MOVaddr target-flags(aarch64-page) @var_local, target-flags(aarch64-pageoff, aarch64-nc) @var_local +# LINUX-DEFAULT: %0 = MOVaddr target-flags(aarch64-page) @var_local, target-flags(aarch64-pageoff, aarch64-nc) @var_local +# LINUX-PIC: %0 = LOADgot target-flags(aarch64-got) @var_local +body: | + bb.0: + %0(p0) = G_GLOBAL_VALUE @var_local + %x0 = COPY %0(p0) +... + +--- +# CHECK-LABEL: name: global_got +name: global_got +legalized: true +regBankSelected: true +registers: + - { id: 0, class: gpr } + +# CHECK: body: +# IOS: %0 = LOADgot target-flags(aarch64-got) @var_got +# LINUX-DEFAULT: %0 = MOVaddr target-flags(aarch64-page) @var_got, target-flags(aarch64-pageoff, aarch64-nc) @var_got +# LINUX-PIC: %0 = LOADgot target-flags(aarch64-got) @var_got +body: | + bb.0: + %0(p0) = G_GLOBAL_VALUE @var_got + %x0 = COPY %0(p0) +... + +--- +# CHECK-LABEL: name: icmp +name: icmp +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +# CHECK-NEXT: - { id: 3, class: gpr32 } +# CHECK-NEXT: - { id: 4, class: gpr64 } +# CHECK-NEXT: - { id: 5, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + - { id: 4, class: gpr } + - { id: 5, class: gpr } + +# CHECK: body: +# CHECK: %wzr = SUBSWrr %0, %0, implicit-def %nzcv +# CHECK: %1 = CSINCWr %wzr, %wzr, 1, implicit %nzcv + +# CHECK: %xzr = SUBSXrr %2, %2, implicit-def %nzcv +# CHECK: %3 = CSINCWr %wzr, %wzr, 3, implicit %nzcv + +# CHECK: %xzr = SUBSXrr %4, %4, implicit-def %nzcv +# CHECK: %5 = CSINCWr %wzr, %wzr, 0, implicit %nzcv + +body: | + bb.0: + liveins: %w0, %x0 + + %0(s32) = COPY %w0 + %1(s1) = G_ICMP intpred(eq), %0, %0 + %w0 = COPY %1(s1) + + %2(s64) = COPY %x0 + %3(s1) = G_ICMP intpred(uge), %2, %2 + %w0 = COPY %3(s1) + + %4(p0) = COPY %x0 + %5(s1) = G_ICMP intpred(ne), %4, %4 + %w0 = COPY %5(s1) +... + +--- +# CHECK-LABEL: name: fcmp +name: fcmp +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: fpr64 } +# CHECK-NEXT: - { id: 3, class: gpr32 } +# CHECK-NEXT: - { id: 4, class: gpr32 } +# CHECK-NEXT: - { id: 5, class: gpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + - { id: 2, class: fpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: FCMPSrr %0, %0, implicit-def %nzcv +# CHECK: [[TST_MI:%[0-9]+]] = CSINCWr %wzr, %wzr, 5, implicit %nzcv +# CHECK: [[TST_GT:%[0-9]+]] = CSINCWr %wzr, %wzr, 13, implicit %nzcv +# CHECK: %1 = ORRWrr [[TST_MI]], [[TST_GT]] + +# CHECK: FCMPDrr %2, %2, implicit-def %nzcv +# CHECK: %3 = CSINCWr %wzr, %wzr, 4, implicit %nzcv + +body: | + bb.0: + liveins: %w0, %x0 + + %0(s32) = COPY %s0 + %1(s1) = G_FCMP floatpred(one), %0, %0 + %w0 = COPY %1(s1) + + %2(s64) = COPY %d0 + %3(s1) = G_FCMP floatpred(uge), %2, %2 + %w0 = COPY %3(s1) + +... + +--- +# CHECK-LABEL: name: phi +name: phi +legalized: true +regBankSelected: true +tracksRegLiveness: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: fpr32 } +registers: + - { id: 0, class: fpr } + - { id: 1, class: gpr } + - { id: 2, class: fpr } + +# CHECK: body: +# CHECK: bb.1: +# CHECK: %2 = PHI %0, %bb.0, %2, %bb.1 + +body: | + bb.0: + liveins: %s0, %w0 + successors: %bb.1 + %0(s32) = COPY %s0 + %1(s1) = COPY %w0 + + bb.1: + successors: %bb.1, %bb.2 + %2(s32) = PHI %0, %bb.0, %2, %bb.1 + G_BRCOND %1, %bb.1 + + bb.2: + %s0 = COPY %2 + RET_ReallyLR implicit %s0 +... + +--- +# CHECK-LABEL: name: select +name: select +legalized: true +regBankSelected: true +tracksRegLiveness: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +# CHECK-NEXT: - { id: 3, class: gpr32 } +# CHECK-NEXT: - { id: 4, class: gpr64 } +# CHECK-NEXT: - { id: 5, class: gpr64 } +# CHECK-NEXT: - { id: 6, class: gpr64 } +# CHECK-NEXT: - { id: 7, class: gpr64 } +# CHECK-NEXT: - { id: 8, class: gpr64 } +# CHECK-NEXT: - { id: 9, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + - { id: 4, class: gpr } + - { id: 5, class: gpr } + - { id: 6, class: gpr } + - { id: 7, class: gpr } + - { id: 8, class: gpr } + - { id: 9, class: gpr } + +# CHECK: body: +# CHECK: %wzr = ANDSWri %0, 0, implicit-def %nzcv +# CHECK: %3 = CSELWr %1, %2, 1, implicit %nzcv +# CHECK: %wzr = ANDSWri %0, 0, implicit-def %nzcv +# CHECK: %6 = CSELXr %4, %5, 1, implicit %nzcv +# CHECK: %wzr = ANDSWri %0, 0, implicit-def %nzcv +# CHECK: %9 = CSELXr %7, %8, 1, implicit %nzcv +body: | + bb.0: + liveins: %w0, %w1, %w2 + %0(s1) = COPY %w0 + + %1(s32) = COPY %w1 + %2(s32) = COPY %w2 + %3(s32) = G_SELECT %0, %1, %2 + %w0 = COPY %3(s32) + + %4(s64) = COPY %x0 + %5(s64) = COPY %x1 + %6(s64) = G_SELECT %0, %4, %5 + %x0 = COPY %6(s64) + + %7(p0) = COPY %x0 + %8(p0) = COPY %x1 + %9(p0) = G_SELECT %0, %7, %8 + %x0 = COPY %9(p0) +... diff --git a/test/CodeGen/AArch64/GlobalISel/translate-gep.ll b/test/CodeGen/AArch64/GlobalISel/translate-gep.ll index 14dbc7c3c31a9..e4c18757418d0 100644 --- a/test/CodeGen/AArch64/GlobalISel/translate-gep.ll +++ b/test/CodeGen/AArch64/GlobalISel/translate-gep.ll @@ -58,8 +58,8 @@ define i32* @const_then_var(%type1* %addr, i64 %idx) { ; CHECK: [[BASE:%[0-9]+]](p0) = COPY %x0 ; CHECK: [[IDX:%[0-9]+]](s64) = COPY %x1 ; CHECK: [[OFFSET1:%[0-9]+]](s64) = G_CONSTANT i64 272 -; CHECK: [[BASE1:%[0-9]+]](p0) = G_GEP [[BASE]], [[OFFSET1]](s64) ; CHECK: [[SIZE:%[0-9]+]](s64) = G_CONSTANT i64 4 +; CHECK: [[BASE1:%[0-9]+]](p0) = G_GEP [[BASE]], [[OFFSET1]](s64) ; CHECK: [[OFFSET2:%[0-9]+]](s64) = G_MUL [[SIZE]], [[IDX]] ; CHECK: [[BASE2:%[0-9]+]](p0) = G_GEP [[BASE1]], [[OFFSET2]](s64) ; CHECK: [[RES:%[0-9]+]](p0) = COPY [[BASE2]](p0) @@ -74,9 +74,9 @@ define i32* @var_then_const(%type1* %addr, i64 %idx) { ; CHECK: [[BASE:%[0-9]+]](p0) = COPY %x0 ; CHECK: [[IDX:%[0-9]+]](s64) = COPY %x1 ; CHECK: [[SIZE:%[0-9]+]](s64) = G_CONSTANT i64 64 +; CHECK: [[OFFSET2:%[0-9]+]](s64) = G_CONSTANT i64 40 ; CHECK: [[OFFSET1:%[0-9]+]](s64) = G_MUL [[SIZE]], [[IDX]] ; CHECK: [[BASE1:%[0-9]+]](p0) = G_GEP [[BASE]], [[OFFSET1]](s64) -; CHECK: [[OFFSET2:%[0-9]+]](s64) = G_CONSTANT i64 40 ; CHECK: [[BASE2:%[0-9]+]](p0) = G_GEP [[BASE1]], [[OFFSET2]](s64) ; CHECK: %x0 = COPY [[BASE2]](p0) diff --git a/test/CodeGen/AArch64/GlobalISel/varargs-ios-translator.ll b/test/CodeGen/AArch64/GlobalISel/varargs-ios-translator.ll new file mode 100644 index 0000000000000..3bd56fa4cebca --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/varargs-ios-translator.ll @@ -0,0 +1,16 @@ +; RUN: llc -mtriple=aarch64-apple-ios -stop-after=instruction-select -global-isel -verify-machineinstrs %s -o - | FileCheck %s + +define void @test_varargs_sentinel(i8* %list, i64, i64, i64, i64, i64, i64, i64, + i32, ...) { +; CHECK-LABEL: name: test_varargs_sentinel +; CHECK: fixedStack: +; CHECK: - { id: [[VARARGS_SLOT:[0-9]+]], offset: 8 +; CHECK: body: +; CHECK: [[LIST:%[0-9]+]] = COPY %x0 +; CHECK: [[VARARGS_AREA:%[0-9]+]] = ADDXri %fixed-stack.[[VARARGS_SLOT]], 0, 0 +; CHECK: STRXui [[VARARGS_AREA]], [[LIST]], 0 :: (store 8 into %ir.list, align 0) + call void @llvm.va_start(i8* %list) + ret void +} + +declare void @llvm.va_start(i8*) diff --git a/test/CodeGen/AArch64/GlobalISel/vastart.ll b/test/CodeGen/AArch64/GlobalISel/vastart.ll new file mode 100644 index 0000000000000..ae44e8fc5dea2 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/vastart.ll @@ -0,0 +1,13 @@ +; RUN: llc -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - -mtriple=aarch64-apple-ios7.0 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-IOS %s +; RUN: llc -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - -mtriple=aarch64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=CHECK-LINUX %s + + +declare void @llvm.va_start(i8*) +define void @test_va_start(i8* %list) { +; CHECK-LABEL: name: test_va_start +; CHECK: [[LIST:%[0-9]+]](p0) = COPY %x0 +; CHECK-IOS: G_VASTART [[LIST]](p0) :: (store 8 into %ir.list, align 0) +; CHECK-LINUX: G_VASTART [[LIST]](p0) :: (store 32 into %ir.list, align 0) + call void @llvm.va_start(i8* %list) + ret void +} diff --git a/test/CodeGen/AArch64/aarch64-codegen-prepare-atp.ll b/test/CodeGen/AArch64/aarch64-codegen-prepare-atp.ll new file mode 100644 index 0000000000000..3fe7e65bf2454 --- /dev/null +++ b/test/CodeGen/AArch64/aarch64-codegen-prepare-atp.ll @@ -0,0 +1,68 @@ +; RUN: opt -codegenprepare < %s -S | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnu" + +%struct.match_state = type { i64, i64 } + +; %add is also promoted by forking an extra sext. +define void @promoteTwoOne(i32 %i, i32 %j, i64* %P1, i64* %P2 ) { +; CHECK-LABEL: @promoteTwoOne +; CHECK-LABEL: entry: +; CHECK: %[[SEXT1:.*]] = sext i32 %i to i64 +; CHECK: %[[SEXT2:.*]] = sext i32 %j to i64 +; CHECK: %add = add nsw i64 %[[SEXT1]], %[[SEXT2]] +entry: + %add = add nsw i32 %i, %j + %s = sext i32 %add to i64 + %addr1 = getelementptr inbounds i64, i64* %P1, i64 %s + store i64 %s, i64* %addr1 + %s2 = sext i32 %i to i64 + %addr2 = getelementptr inbounds i64, i64* %P2, i64 %s2 + store i64 %s2, i64* %addr2 + ret void +} + +; Both %add1 and %add2 are promoted by forking extra sexts. +define void @promoteTwoTwo(i32 %i, i32 %j, i32 %k, i64* %P1, i64* %P2) { +; CHECK-LABEL: @promoteTwoTwo +; CHECK-LABEL:entry: +; CHECK: %[[SEXT1:.*]] = sext i32 %j to i64 +; CHECK: %[[SEXT2:.*]] = sext i32 %i to i64 +; CHECK: %add1 = add nsw i64 %[[SEXT1]], %[[SEXT2]] +; CHECK: %[[SEXT3:.*]] = sext i32 %k to i64 +; CHECK: %add2 = add nsw i64 %[[SEXT1]], %[[SEXT3]] +entry: + %add1 = add nsw i32 %j, %i + %s = sext i32 %add1 to i64 + %addr1 = getelementptr inbounds i64, i64* %P1, i64 %s + store i64 %s, i64* %addr1 + %add2 = add nsw i32 %j, %k + %s2 = sext i32 %add2 to i64 + %addr2 = getelementptr inbounds i64, i64* %P2, i64 %s2 + store i64 %s2, i64* %addr2 + ret void +} + +define i64 @promoteGEPSunk(i1 %cond, i64* %base, i32 %i) { +; CHECK-LABEL: @promoteGEPSunk +; CHECK-LABEL: entry: +; CHECK: %[[SEXT:.*]] = sext i32 %i to i64 +; CHECK: %add = add nsw i64 %[[SEXT]], 1 +; CHECK: %add2 = add nsw i64 %[[SEXT]], 2 +entry: + %add = add nsw i32 %i, 1 + %s = sext i32 %add to i64 + %addr = getelementptr inbounds i64, i64* %base, i64 %s + %add2 = add nsw i32 %i, 2 + %s2 = sext i32 %add2 to i64 + %addr2 = getelementptr inbounds i64, i64* %base, i64 %s2 + br i1 %cond, label %if.then, label %if.then2 +if.then: + %v = load i64, i64* %addr + %v2 = load i64, i64* %addr2 + %r = add i64 %v, %v2 + ret i64 %r +if.then2: + ret i64 0; +} diff --git a/test/CodeGen/AArch64/aarch64-fold-lslfast.ll b/test/CodeGen/AArch64/aarch64-fold-lslfast.ll new file mode 100644 index 0000000000000..0dfe04b664d0e --- /dev/null +++ b/test/CodeGen/AArch64/aarch64-fold-lslfast.ll @@ -0,0 +1,74 @@ +; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+lsl-fast | FileCheck %s + +%struct.a = type [256 x i16] +%struct.b = type [256 x i32] +%struct.c = type [256 x i64] + +declare void @foo() +define i16 @halfword(%struct.a* %ctx, i32 %xor72) nounwind { +; CHECK-LABEL: halfword: +; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #8 +; CHECK: ldrh [[REG1:w[0-9]+]], [{{.*}}[[REG2:x[0-9]+]], [[REG]], lsl #1] +; CHECK: strh [[REG1]], [{{.*}}[[REG2]], [[REG]], lsl #1] + %shr81 = lshr i32 %xor72, 9 + %conv82 = zext i32 %shr81 to i64 + %idxprom83 = and i64 %conv82, 255 + %arrayidx86 = getelementptr inbounds %struct.a, %struct.a* %ctx, i64 0, i64 %idxprom83 + %result = load i16, i16* %arrayidx86, align 2 + call void @foo() + store i16 %result, i16* %arrayidx86, align 2 + ret i16 %result +} + +define i32 @word(%struct.b* %ctx, i32 %xor72) nounwind { +; CHECK-LABEL: word: +; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #8 +; CHECK: ldr [[REG1:w[0-9]+]], [{{.*}}[[REG2:x[0-9]+]], [[REG]], lsl #2] +; CHECK: str [[REG1]], [{{.*}}[[REG2]], [[REG]], lsl #2] + %shr81 = lshr i32 %xor72, 9 + %conv82 = zext i32 %shr81 to i64 + %idxprom83 = and i64 %conv82, 255 + %arrayidx86 = getelementptr inbounds %struct.b, %struct.b* %ctx, i64 0, i64 %idxprom83 + %result = load i32, i32* %arrayidx86, align 4 + call void @foo() + store i32 %result, i32* %arrayidx86, align 4 + ret i32 %result +} + +define i64 @doubleword(%struct.c* %ctx, i32 %xor72) nounwind { +; CHECK-LABEL: doubleword: +; CHECK: ubfx [[REG:x[0-9]+]], x1, #9, #8 +; CHECK: ldr [[REG1:x[0-9]+]], [{{.*}}[[REG2:x[0-9]+]], [[REG]], lsl #3] +; CHECK: str [[REG1]], [{{.*}}[[REG2]], [[REG]], lsl #3] + %shr81 = lshr i32 %xor72, 9 + %conv82 = zext i32 %shr81 to i64 + %idxprom83 = and i64 %conv82, 255 + %arrayidx86 = getelementptr inbounds %struct.c, %struct.c* %ctx, i64 0, i64 %idxprom83 + %result = load i64, i64* %arrayidx86, align 8 + call void @foo() + store i64 %result, i64* %arrayidx86, align 8 + ret i64 %result +} + +define i64 @multi_use_non_memory(i64 %a, i64 %b) { +; CHECK-LABEL: multi_use_non_memory: +; CHECK: lsl [[REG1:x[0-9]+]], x0, #3 +; CHECK-NOT: cmp [[REG1]], x1, lsl # 3 +; CHECK-NEXT: lsl [[REG2:x[0-9]+]], x1, #3 +; CHECK-NEXT: cmp [[REG1]], [[REG2]] +entry: + %mul1 = shl i64 %a, 3 + %mul2 = shl i64 %b, 3 + %cmp = icmp slt i64 %mul1, %mul2 + br i1 %cmp, label %truebb, label %falsebb +truebb: + tail call void @foo() + unreachable +falsebb: + %cmp2 = icmp sgt i64 %mul1, %mul2 + br i1 %cmp2, label %exitbb, label %endbb +exitbb: + ret i64 %mul1 +endbb: + ret i64 %mul2 +} diff --git a/test/CodeGen/AArch64/aarch64-gep-opt.ll b/test/CodeGen/AArch64/aarch64-gep-opt.ll index 6e4a47b04406d..df9534ffde097 100644 --- a/test/CodeGen/AArch64/aarch64-gep-opt.ll +++ b/test/CodeGen/AArch64/aarch64-gep-opt.ll @@ -96,9 +96,13 @@ exit: ; CHECK-NoAA: add i64 [[TMP:%[a-zA-Z0-9]+]], 528 ; CHECK-NoAA: add i64 [[TMP]], 532 ; CHECK-NoAA: if.true: -; CHECK-NoAA: {{%sunk[a-zA-Z0-9]+}} = add i64 [[TMP]], 532 +; CHECK-NoAA: inttoptr +; CHECK-NoAA: bitcast +; CHECK-NoAA: {{%sunk[a-zA-Z0-9]+}} = getelementptr i8, {{.*}}, i64 532 ; CHECK-NoAA: exit: -; CHECK-NoAA: {{%sunk[a-zA-Z0-9]+}} = add i64 [[TMP]], 528 +; CHECK-NoAA: inttoptr +; CHECK-NoAA: bitcast +; CHECK-NoAA: {{%sunk[a-zA-Z0-9]+}} = getelementptr i8, {{.*}}, i64 528 ; CHECK-UseAA-LABEL: test_GEP_across_BB( ; CHECK-UseAA: [[PTR0:%[a-zA-Z0-9]+]] = getelementptr diff --git a/test/CodeGen/AArch64/aarch64-named-reg-w18.ll b/test/CodeGen/AArch64/aarch64-named-reg-w18.ll new file mode 100644 index 0000000000000..341c7683dbaa4 --- /dev/null +++ b/test/CodeGen/AArch64/aarch64-named-reg-w18.ll @@ -0,0 +1,14 @@ +; RUN: not llc -mtriple=aarch64-fuchsia -o - %s 2>&1 | FileCheck %s --check-prefix=ERROR +; RUN: llc -mtriple=aarch64-fuchsia -mattr=+reserve-x18 -o - %s + +define void @set_w18(i32 %x) { +entry: +; FIXME: Include an allocatable-specific error message +; ERROR: Invalid register name "w18". + tail call void @llvm.write_register.i32(metadata !0, i32 %x) + ret void +} + +declare void @llvm.write_register.i32(metadata, i32) nounwind + +!0 = !{!"w18"} diff --git a/test/CodeGen/AArch64/aarch64-named-reg-x18.ll b/test/CodeGen/AArch64/aarch64-named-reg-x18.ll new file mode 100644 index 0000000000000..eed852710ba00 --- /dev/null +++ b/test/CodeGen/AArch64/aarch64-named-reg-x18.ll @@ -0,0 +1,14 @@ +; RUN: not llc -mtriple=aarch64-fuchsia -o - %s 2>&1 | FileCheck %s --check-prefix=ERROR +; RUN: llc -mtriple=aarch64-fuchsia -mattr=+reserve-x18 -o - %s + +define void @set_x18(i64 %x) { +entry: +; FIXME: Include an allocatable-specific error message +; ERROR: Invalid register name "x18". + tail call void @llvm.write_register.i64(metadata !0, i64 %x) + ret void +} + +declare void @llvm.write_register.i64(metadata, i64) nounwind + +!0 = !{!"x18"} diff --git a/test/CodeGen/AArch64/and-sink.ll b/test/CodeGen/AArch64/and-sink.ll new file mode 100644 index 0000000000000..91b7bd0db1726 --- /dev/null +++ b/test/CodeGen/AArch64/and-sink.ll @@ -0,0 +1,90 @@ +; RUN: llc -mtriple=aarch64-linux-gnu -verify-machineinstrs < %s | FileCheck %s +; RUN: opt -S -codegenprepare -mtriple=aarch64-linux %s | FileCheck --check-prefix=CHECK-CGP %s + +@A = global i32 zeroinitializer +@B = global i32 zeroinitializer +@C = global i32 zeroinitializer + +; Test that and is sunk into cmp block to form tbz. +define i32 @and_sink1(i32 %a, i1 %c) { +; CHECK-LABEL: and_sink1: +; CHECK: tbz w1, #0 +; CHECK: str wzr, [x{{[0-9]+}}, :lo12:A] +; CHECK: tbnz {{w[0-9]+}}, #2 + +; CHECK-CGP-LABEL: @and_sink1( +; CHECK-CGP-NOT: and i32 + %and = and i32 %a, 4 + br i1 %c, label %bb0, label %bb2 +bb0: +; CHECK-CGP-LABEL: bb0: +; CHECK-CGP: and i32 +; CHECK-CGP-NEXT: icmp eq i32 +; CHECK-CGP-NEXT: store +; CHECK-CGP-NEXT: br + %cmp = icmp eq i32 %and, 0 + store i32 0, i32* @A + br i1 %cmp, label %bb1, label %bb2 +bb1: + ret i32 1 +bb2: + ret i32 0 +} + +; Test that both 'and' and cmp get sunk to form tbz. +define i32 @and_sink2(i32 %a, i1 %c, i1 %c2) { +; CHECK-LABEL: and_sink2: +; CHECK: str wzr, [x{{[0-9]+}}, :lo12:A] +; CHECK: tbz w1, #0 +; CHECK: str wzr, [x{{[0-9]+}}, :lo12:B] +; CHECK: tbz w2, #0 +; CHECK: str wzr, [x{{[0-9]+}}, :lo12:C] +; CHECK: tbnz {{w[0-9]+}}, #2 + +; CHECK-CGP-LABEL: @and_sink2( +; CHECK-CGP-NOT: and i32 + %and = and i32 %a, 4 + store i32 0, i32* @A + br i1 %c, label %bb0, label %bb3 +bb0: +; CHECK-CGP-LABEL: bb0: +; CHECK-CGP-NOT: and i32 +; CHECK-CGP-NOT: icmp + %cmp = icmp eq i32 %and, 0 + store i32 0, i32* @B + br i1 %c2, label %bb1, label %bb3 +bb1: +; CHECK-CGP-LABEL: bb1: +; CHECK-CGP: and i32 +; CHECK-CGP-NEXT: icmp eq i32 +; CHECK-CGP-NEXT: store +; CHECK-CGP-NEXT: br + store i32 0, i32* @C + br i1 %cmp, label %bb2, label %bb0 +bb2: + ret i32 1 +bb3: + ret i32 0 +} + +; Test that 'and' is not sunk since cbz is a better alternative. +define i32 @and_sink3(i32 %a) { +; CHECK-LABEL: and_sink3: +; CHECK: and [[REG:w[0-9]+]], w0, #0x3 +; CHECK: [[LOOP:.L[A-Z0-9_]+]]: +; CHECK: str wzr, [x{{[0-9]+}}, :lo12:A] +; CHECK: cbz [[REG]], [[LOOP]] + +; CHECK-CGP-LABEL: @and_sink3( +; CHECK-CGP-NEXT: and i32 + %and = and i32 %a, 3 + br label %bb0 +bb0: +; CHECK-CGP-LABEL: bb0: +; CHECK-CGP-NOT: and i32 + %cmp = icmp eq i32 %and, 0 + store i32 0, i32* @A + br i1 %cmp, label %bb0, label %bb2 +bb2: + ret i32 0 +} diff --git a/test/CodeGen/AArch64/argument-blocks.ll b/test/CodeGen/AArch64/argument-blocks.ll index 3169abc2dcb3a..b5374ca8ced53 100644 --- a/test/CodeGen/AArch64/argument-blocks.ll +++ b/test/CodeGen/AArch64/argument-blocks.ll @@ -59,10 +59,10 @@ define i64 @test_hfa_ignores_gprs([7 x float], [2 x float] %in, i64, i64 %res) { } ; [2 x float] should not be promoted to double by the Darwin varargs handling, -; but should go in an 8-byte aligned slot. +; but should go in an 8-byte aligned slot and can be merged as integer stores. define void @test_varargs_stackalign() { ; CHECK-LABEL: test_varargs_stackalign: -; CHECK-DARWINPCS: stp {{w[0-9]+}}, {{w[0-9]+}}, [sp, #16] +; CHECK-DARWINPCS: str {{x[0-9]+}}, [sp, #16] call void(...) @callee([3 x float] undef, [2 x float] [float 1.0, float 2.0]) ret void diff --git a/test/CodeGen/AArch64/arm64-abi-varargs.ll b/test/CodeGen/AArch64/arm64-abi-varargs.ll index a29f8c4b57ab6..0a79655714806 100644 --- a/test/CodeGen/AArch64/arm64-abi-varargs.ll +++ b/test/CodeGen/AArch64/arm64-abi-varargs.ll @@ -3,7 +3,7 @@ ; rdar://13625505 ; Here we have 9 fixed integer arguments the 9th argument in on stack, the ; varargs start right after at 8-byte alignment. -define void @fn9(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7, i32 %a8, i32 %a9, ...) nounwind noinline ssp { +define void @fn9(i32* %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7, i32 %a8, i32 %a9, ...) nounwind noinline ssp { ; CHECK-LABEL: fn9: ; 9th fixed argument ; CHECK: ldr {{w[0-9]+}}, [sp, #64] @@ -30,7 +30,6 @@ define void @fn9(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7, %a10 = alloca i32, align 4 %a11 = alloca i32, align 4 %a12 = alloca i32, align 4 - store i32 %a1, i32* %1, align 4 store i32 %a2, i32* %2, align 4 store i32 %a3, i32* %3, align 4 store i32 %a4, i32* %4, align 4 @@ -39,6 +38,7 @@ define void @fn9(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7, store i32 %a7, i32* %7, align 4 store i32 %a8, i32* %8, align 4 store i32 %a9, i32* %9, align 4 + store i32 %a9, i32* %a1 %10 = bitcast i8** %args to i8* call void @llvm.va_start(i8* %10) %11 = va_arg i8** %args, i32 @@ -93,7 +93,7 @@ define i32 @main() nounwind ssp { %10 = load i32, i32* %a10, align 4 %11 = load i32, i32* %a11, align 4 %12 = load i32, i32* %a12, align 4 - call void (i32, i32, i32, i32, i32, i32, i32, i32, i32, ...) @fn9(i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9, i32 %10, i32 %11, i32 %12) + call void (i32*, i32, i32, i32, i32, i32, i32, i32, i32, ...) @fn9(i32* %a1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9, i32 %10, i32 %11, i32 %12) ret i32 0 } diff --git a/test/CodeGen/AArch64/arm64-abi.ll b/test/CodeGen/AArch64/arm64-abi.ll index fb52b1d99fc95..6cf0ab35b9b52 100644 --- a/test/CodeGen/AArch64/arm64-abi.ll +++ b/test/CodeGen/AArch64/arm64-abi.ll @@ -205,10 +205,7 @@ declare i32 @args_i32(i32, i32, i32, i32, i32, i32, i32, i32, i16 signext, i32, define i32 @test8(i32 %argc, i8** nocapture %argv) nounwind { entry: ; CHECK-LABEL: test8 -; CHECK: strb {{w[0-9]+}}, [sp, #3] -; CHECK: strb wzr, [sp, #2] -; CHECK: strb {{w[0-9]+}}, [sp, #1] -; CHECK: strb wzr, [sp] +; CHECK: str w8, [sp] ; CHECK: bl ; FAST-LABEL: test8 ; FAST: strb {{w[0-9]+}}, [sp] diff --git a/test/CodeGen/AArch64/arm64-addr-type-promotion.ll b/test/CodeGen/AArch64/arm64-addr-type-promotion.ll index c57be5684ade4..0009fe52e177a 100644 --- a/test/CodeGen/AArch64/arm64-addr-type-promotion.ll +++ b/test/CodeGen/AArch64/arm64-addr-type-promotion.ll @@ -10,14 +10,17 @@ define zeroext i8 @fullGtU(i32 %i1, i32 %i2) { ; CHECK: fullGtU ; CHECK: adrp [[PAGE:x[0-9]+]], _block@GOTPAGE ; CHECK: ldr [[ADDR:x[0-9]+]], {{\[}}[[PAGE]], _block@GOTPAGEOFF] +; CHECK: sxtw [[I1:x[0-9]+]], w0 +; CHECK: sxtw [[I2:x[0-9]+]], w1 ; CHECK-NEXT: ldr [[BLOCKBASE:x[0-9]+]], {{\[}}[[ADDR]]] -; CHECK-NEXT: ldrb [[BLOCKVAL1:w[0-9]+]], {{\[}}[[BLOCKBASE]], w0, sxtw] -; CHECK-NEXT: ldrb [[BLOCKVAL2:w[0-9]+]], {{\[}}[[BLOCKBASE]], w1, sxtw] +; CHECK-NEXT: ldrb [[BLOCKVAL1:w[0-9]+]], {{\[}}[[BLOCKBASE]], [[I1]]] +; CHECK-NEXT: ldrb [[BLOCKVAL2:w[0-9]+]], {{\[}}[[BLOCKBASE]], [[I2]]] + ; CHECK-NEXT: cmp [[BLOCKVAL1]], [[BLOCKVAL2]] ; CHECK-NEXT: b.ne ; Next BB -; CHECK: add [[BLOCKBASE2:x[0-9]+]], [[BLOCKBASE]], w1, sxtw -; CHECK-NEXT: add [[BLOCKBASE1:x[0-9]+]], [[BLOCKBASE]], w0, sxtw +; CHECK: add [[BLOCKBASE2:x[0-9]+]], [[BLOCKBASE]], [[I2]] +; CHECK-NEXT: add [[BLOCKBASE1:x[0-9]+]], [[BLOCKBASE]], [[I1]] ; CHECK-NEXT: ldrb [[LOADEDVAL1:w[0-9]+]], {{\[}}[[BLOCKBASE1]], #1] ; CHECK-NEXT: ldrb [[LOADEDVAL2:w[0-9]+]], {{\[}}[[BLOCKBASE2]], #1] ; CHECK-NEXT: cmp [[LOADEDVAL1]], [[LOADEDVAL2]] diff --git a/test/CodeGen/AArch64/arm64-addrmode.ll b/test/CodeGen/AArch64/arm64-addrmode.ll index e8fc4e68fcbe2..6da767921632f 100644 --- a/test/CodeGen/AArch64/arm64-addrmode.ll +++ b/test/CodeGen/AArch64/arm64-addrmode.ll @@ -112,8 +112,8 @@ define void @t10(i64 %a) { define void @t11(i64 %a) { ; CHECK-LABEL: t11: -; CHECK: mov w[[NUM:[0-9]+]], #19070976 -; CHECK: movk w[[NUM:[0-9]+]], #17767 +; CHECK: mov w[[NUM:[0-9]+]], #17767 +; CHECK: movk w[[NUM:[0-9]+]], #291 ; CHECK-NEXT: ldr xzr, [x0, x[[NUM]]] %1 = add i64 %a, 19088743 ;0x1234567 %2 = inttoptr i64 %1 to i64* diff --git a/test/CodeGen/AArch64/arm64-atomic.ll b/test/CodeGen/AArch64/arm64-atomic.ll index c87103481adf6..2c9a3bbaa5001 100644 --- a/test/CodeGen/AArch64/arm64-atomic.ll +++ b/test/CodeGen/AArch64/arm64-atomic.ll @@ -9,10 +9,10 @@ define i32 @val_compare_and_swap(i32* %p, i32 %cmp, i32 %new) #0 { ; CHECK-NEXT: b.ne [[FAILBB:.?LBB[0-9_]+]] ; CHECK-NEXT: stxr [[SCRATCH_REG:w[0-9]+]], w2, [x[[ADDR]]] ; CHECK-NEXT: cbnz [[SCRATCH_REG]], [[TRYBB]] -; CHECK-NEXT: b [[EXITBB:.?LBB[0-9_]+]] +; CHECK-NEXT: ret ; CHECK-NEXT: [[FAILBB]]: ; CHECK-NEXT: clrex -; CHECK-NEXT: [[EXITBB]]: +; CHECK-NEXT: ret %pair = cmpxchg i32* %p, i32 %cmp, i32 %new acquire acquire %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val @@ -27,10 +27,12 @@ define i32 @val_compare_and_swap_from_load(i32* %p, i32 %cmp, i32* %pnew) #0 { ; CHECK-NEXT: b.ne [[FAILBB:.?LBB[0-9_]+]] ; CHECK-NEXT: stxr [[SCRATCH_REG:w[0-9]+]], [[NEW]], [x0] ; CHECK-NEXT: cbnz [[SCRATCH_REG]], [[TRYBB]] -; CHECK-NEXT: b [[EXITBB:.?LBB[0-9_]+]] +; CHECK-NEXT: mov x0, x[[ADDR]] +; CHECK-NEXT: ret ; CHECK-NEXT: [[FAILBB]]: ; CHECK-NEXT: clrex -; CHECK-NEXT: [[EXITBB]]: +; CHECK-NEXT: mov x0, x[[ADDR]] +; CHECK-NEXT: ret %new = load i32, i32* %pnew %pair = cmpxchg i32* %p, i32 %cmp, i32 %new acquire acquire %val = extractvalue { i32, i1 } %pair, 0 @@ -41,15 +43,15 @@ define i32 @val_compare_and_swap_rel(i32* %p, i32 %cmp, i32 %new) #0 { ; CHECK-LABEL: val_compare_and_swap_rel: ; CHECK-NEXT: mov x[[ADDR:[0-9]+]], x0 ; CHECK-NEXT: [[TRYBB:.?LBB[0-9_]+]]: -; CHECK-NEXT: ldaxr [[RESULT:w[0-9]+]], [x[[ADDR]] +; CHECK-NEXT: ldaxr [[RESULT:w[0-9]+]], [x[[ADDR]]] ; CHECK-NEXT: cmp [[RESULT]], w1 ; CHECK-NEXT: b.ne [[FAILBB:.?LBB[0-9_]+]] -; CHECK-NEXT: stlxr [[SCRATCH_REG:w[0-9]+]], w2, [x[[ADDR]] +; CHECK-NEXT: stlxr [[SCRATCH_REG:w[0-9]+]], w2, [x[[ADDR]]] ; CHECK-NEXT: cbnz [[SCRATCH_REG]], [[TRYBB]] -; CHECK-NEXT: b [[EXITBB:.?LBB[0-9_]+]] +; CHECK-NEXT: ret ; CHECK-NEXT: [[FAILBB]]: ; CHECK-NEXT: clrex -; CHECK-NEXT: [[EXITBB]]: +; CHECK-NEXT: ret %pair = cmpxchg i32* %p, i32 %cmp, i32 %new acq_rel monotonic %val = extractvalue { i32, i1 } %pair, 0 ret i32 %val @@ -64,10 +66,10 @@ define i64 @val_compare_and_swap_64(i64* %p, i64 %cmp, i64 %new) #0 { ; CHECK-NEXT: b.ne [[FAILBB:.?LBB[0-9_]+]] ; CHECK-NEXT: stxr [[SCRATCH_REG:w[0-9]+]], x2, [x[[ADDR]]] ; CHECK-NEXT: cbnz [[SCRATCH_REG]], [[TRYBB]] -; CHECK-NEXT: b [[EXITBB:.?LBB[0-9_]+]] +; CHECK-NEXT: ret ; CHECK-NEXT: [[FAILBB]]: ; CHECK-NEXT: clrex -; CHECK-NEXT: [[EXITBB]]: +; CHECK-NEXT: ret %pair = cmpxchg i64* %p, i64 %cmp, i64 %new monotonic monotonic %val = extractvalue { i64, i1 } %pair, 0 ret i64 %val diff --git a/test/CodeGen/AArch64/arm64-bitfield-extract.ll b/test/CodeGen/AArch64/arm64-bitfield-extract.ll index 339dbbe18fc09..91aed060677ae 100644 --- a/test/CodeGen/AArch64/arm64-bitfield-extract.ll +++ b/test/CodeGen/AArch64/arm64-bitfield-extract.ll @@ -348,8 +348,8 @@ entry: ; CHECK-LABEL: fct16: ; CHECK: ldr [[REG1:w[0-9]+]], ; Create the constant -; CHECK: mov [[REGCST:w[0-9]+]], #1703936 -; CHECK: movk [[REGCST]], #33120 +; CHECK: mov [[REGCST:w[0-9]+]], #33120 +; CHECK: movk [[REGCST]], #26, lsl #16 ; Do the masking ; CHECK: and [[REG2:w[0-9]+]], [[REG1]], [[REGCST]] ; CHECK-NEXT: bfxil [[REG2]], w1, #16, #3 @@ -377,8 +377,8 @@ entry: ; CHECK-LABEL: fct17: ; CHECK: ldr [[REG1:x[0-9]+]], ; Create the constant -; CHECK: mov w[[REGCST:[0-9]+]], #1703936 -; CHECK: movk w[[REGCST]], #33120 +; CHECK: mov w[[REGCST:[0-9]+]], #33120 +; CHECK: movk w[[REGCST]], #26, lsl #16 ; Do the masking ; CHECK: and [[REG2:x[0-9]+]], [[REG1]], x[[REGCST]] ; CHECK-NEXT: bfxil [[REG2]], x1, #16, #3 diff --git a/test/CodeGen/AArch64/arm64-blockaddress.ll b/test/CodeGen/AArch64/arm64-blockaddress.ll index 5df8402163520..b50ffdef5ddd5 100644 --- a/test/CodeGen/AArch64/arm64-blockaddress.ll +++ b/test/CodeGen/AArch64/arm64-blockaddress.ll @@ -15,10 +15,10 @@ entry: ; CHECK-LINUX: add {{x[0-9]+}}, [[REG]], :lo12:.Ltmp1 ; CHECK-LARGE-LABEL: t: -; CHECK-LARGE: movz [[ADDR_REG:x[0-9]+]], #:abs_g3:[[DEST_LBL:.Ltmp[0-9]+]] -; CHECK-LARGE: movk [[ADDR_REG]], #:abs_g2_nc:[[DEST_LBL]] +; CHECK-LARGE: movz [[ADDR_REG:x[0-9]+]], #:abs_g0_nc:[[DEST_LBL:.Ltmp[0-9]+]] ; CHECK-LARGE: movk [[ADDR_REG]], #:abs_g1_nc:[[DEST_LBL]] -; CHECK-LARGE: movk [[ADDR_REG]], #:abs_g0_nc:[[DEST_LBL]] +; CHECK-LARGE: movk [[ADDR_REG]], #:abs_g2_nc:[[DEST_LBL]] +; CHECK-LARGE: movk [[ADDR_REG]], #:abs_g3:[[DEST_LBL]] %recover = alloca i64, align 8 store volatile i64 ptrtoint (i8* blockaddress(@t, %mylabel) to i64), i64* %recover, align 8 diff --git a/test/CodeGen/AArch64/arm64-builtins-linux.ll b/test/CodeGen/AArch64/arm64-builtins-linux.ll index 64239582f230d..f86ee1afe555e 100644 --- a/test/CodeGen/AArch64/arm64-builtins-linux.ll +++ b/test/CodeGen/AArch64/arm64-builtins-linux.ll @@ -1,4 +1,6 @@ ; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s +; RUN: llc < %s -mtriple=aarch64-fuchsia | FileCheck %s +; RUN: llc < %s -mtriple=aarch64-fuchsia -code-model=kernel | FileCheck --check-prefix=FUCHSIA-KERNEL %s ; Function Attrs: nounwind readnone declare i8* @llvm.thread.pointer() #1 @@ -6,6 +8,8 @@ declare i8* @llvm.thread.pointer() #1 define i8* @thread_pointer() { ; CHECK: thread_pointer: ; CHECK: mrs {{x[0-9]+}}, TPIDR_EL0 +; FUCHSIA-KERNEL: thread_pointer: +; FUCHSIA-KERNEL: mrs {{x[0-9]+}}, TPIDR_EL1 %1 = tail call i8* @llvm.thread.pointer() ret i8* %1 } diff --git a/test/CodeGen/AArch64/arm64-code-model-large-abs.ll b/test/CodeGen/AArch64/arm64-code-model-large-abs.ll index 9f50fea370e40..171941748c8fd 100644 --- a/test/CodeGen/AArch64/arm64-code-model-large-abs.ll +++ b/test/CodeGen/AArch64/arm64-code-model-large-abs.ll @@ -9,10 +9,10 @@ define i8* @global_addr() { ; CHECK-LABEL: global_addr: ret i8* @var8 ; The movz/movk calculation should end up returned directly in x0. -; CHECK: movz x0, #:abs_g3:var8 -; CHECK: movk x0, #:abs_g2_nc:var8 +; CHECK: movz x0, #:abs_g0_nc:var8 ; CHECK: movk x0, #:abs_g1_nc:var8 -; CHECK: movk x0, #:abs_g0_nc:var8 +; CHECK: movk x0, #:abs_g2_nc:var8 +; CHECK: movk x0, #:abs_g3:var8 ; CHECK-NEXT: ret } @@ -20,10 +20,10 @@ define i8 @global_i8() { ; CHECK-LABEL: global_i8: %val = load i8, i8* @var8 ret i8 %val -; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g3:var8 -; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var8 +; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g0_nc:var8 ; CHECK: movk x[[ADDR_REG]], #:abs_g1_nc:var8 -; CHECK: movk x[[ADDR_REG]], #:abs_g0_nc:var8 +; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var8 +; CHECK: movk x[[ADDR_REG]], #:abs_g3:var8 ; CHECK: ldrb w0, [x[[ADDR_REG]]] } @@ -31,10 +31,10 @@ define i16 @global_i16() { ; CHECK-LABEL: global_i16: %val = load i16, i16* @var16 ret i16 %val -; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g3:var16 -; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var16 +; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g0_nc:var16 ; CHECK: movk x[[ADDR_REG]], #:abs_g1_nc:var16 -; CHECK: movk x[[ADDR_REG]], #:abs_g0_nc:var16 +; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var16 +; CHECK: movk x[[ADDR_REG]], #:abs_g3:var16 ; CHECK: ldrh w0, [x[[ADDR_REG]]] } @@ -42,10 +42,10 @@ define i32 @global_i32() { ; CHECK-LABEL: global_i32: %val = load i32, i32* @var32 ret i32 %val -; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g3:var32 -; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var32 +; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g0_nc:var32 ; CHECK: movk x[[ADDR_REG]], #:abs_g1_nc:var32 -; CHECK: movk x[[ADDR_REG]], #:abs_g0_nc:var32 +; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var32 +; CHECK: movk x[[ADDR_REG]], #:abs_g3:var32 ; CHECK: ldr w0, [x[[ADDR_REG]]] } @@ -53,10 +53,10 @@ define i64 @global_i64() { ; CHECK-LABEL: global_i64: %val = load i64, i64* @var64 ret i64 %val -; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g3:var64 -; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var64 +; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g0_nc:var64 ; CHECK: movk x[[ADDR_REG]], #:abs_g1_nc:var64 -; CHECK: movk x[[ADDR_REG]], #:abs_g0_nc:var64 +; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var64 +; CHECK: movk x[[ADDR_REG]], #:abs_g3:var64 ; CHECK: ldr x0, [x[[ADDR_REG]]] } @@ -64,9 +64,9 @@ define <2 x i64> @constpool() { ; CHECK-LABEL: constpool: ret <2 x i64> <i64 123456789, i64 987654321100> -; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g3:[[CPADDR:.LCPI[0-9]+_[0-9]+]] -; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:[[CPADDR]] +; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g0_nc:[[CPADDR:.LCPI[0-9]+_[0-9]+]] ; CHECK: movk x[[ADDR_REG]], #:abs_g1_nc:[[CPADDR]] -; CHECK: movk x[[ADDR_REG]], #:abs_g0_nc:[[CPADDR]] +; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:[[CPADDR]] +; CHECK: movk x[[ADDR_REG]], #:abs_g3:[[CPADDR]] ; CHECK: ldr q0, [x[[ADDR_REG]]] } diff --git a/test/CodeGen/AArch64/arm64-codegen-prepare-extload.ll b/test/CodeGen/AArch64/arm64-codegen-prepare-extload.ll index c9f668f2c4249..a104b65ea861d 100644 --- a/test/CodeGen/AArch64/arm64-codegen-prepare-extload.ll +++ b/test/CodeGen/AArch64/arm64-codegen-prepare-extload.ll @@ -258,8 +258,7 @@ false: ; => We have one zext of %zextld left and we created one sext of %ld2. ; 2. We try to promote the operand of %sextaddza. ; a. This creates one sext of %zexta and one of %zextld -; b. The sext of %zexta does not lead to any load, it stays here, even if it -; could have been combine with the zext of %a. +; b. The sext of %zexta can be combined with the zext of %a. ; c. The sext of %zextld leads to %ld and can be combined with it. This is ; done by promoting %zextld. This is fine with the current heuristic: ; neutral. @@ -281,16 +280,14 @@ false: ; OPTALL: [[LD:%[a-zA-Z_0-9-]+]] = load i8, i8* %addr1 ; OPT-NEXT: [[ZEXTLD1_1:%[a-zA-Z_0-9-]+]] = zext i8 [[LD]] to i64 ; OPT-NEXT: [[ZEXTLD1_2:%[a-zA-Z_0-9-]+]] = zext i8 [[LD]] to i64 -; OPT-NEXT: [[ZEXTLD1_3:%[a-zA-Z_0-9-]+]] = zext i8 [[LD]] to i64 ; OPT-NEXT: [[LD2:%[a-zA-Z_0-9-]+]] = load i32, i32* %addr2 ; OPT-NEXT: [[SEXTLD2:%[a-zA-Z_0-9-]+]] = sext i32 [[LD2]] to i64 -; OPT-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = add nsw i64 [[SEXTLD2]], [[ZEXTLD1_1]] -; We do not combine this one: see 2.b. -; OPT-NEXT: [[ZEXTA:%[a-zA-Z_0-9-]+]] = zext i8 %a to i32 -; OPT-NEXT: [[SEXTZEXTA:%[a-zA-Z_0-9-]+]] = sext i32 [[ZEXTA]] to i64 -; OPT-NEXT: [[RESZA:%[a-zA-Z_0-9-]+]] = add nsw i64 [[SEXTZEXTA]], [[ZEXTLD1_3]] +; OPT-NEXT: [[ZEXTLD1_3:%[a-zA-Z_0-9-]+]] = zext i8 [[LD]] to i64 +; OPT-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = add nsw i64 [[SEXTLD2]], [[ZEXTLD1_3]] +; OPT-NEXT: [[ZEXTLD1_4:%[a-zA-Z_0-9-]+]] = zext i8 %a to i64 +; OPT-NEXT: [[RESZA:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ZEXTLD1_4]], [[ZEXTLD1_2]] ; OPT-NEXT: [[SEXTB:%[a-zA-Z_0-9-]+]] = sext i32 %b to i64 -; OPT-NEXT: [[RESB:%[a-zA-Z_0-9-]+]] = add nsw i64 [[SEXTB]], [[ZEXTLD1_2]] +; OPT-NEXT: [[RESB:%[a-zA-Z_0-9-]+]] = add nsw i64 [[SEXTB]], [[ZEXTLD1_1]] ; ; DISABLE: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 ; DISABLE: [[RES:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64 @@ -636,3 +633,24 @@ define i64 @doNotPromoteBecauseOfPairedLoad(i32* %p, i32 %cst) { %final = add i64 %sextres, %zextLd0 ret i64 %final } + +define i64 @promoteZextShl(i1 %c, i16* %P) { +entry: +; OPTALL-LABEL: promoteZextShl +; OPTALL-LABEL: entry: +; OPT: %[[LD:.*]] = load i16, i16* %P +; OPT: %[[EXT:.*]] = zext i16 %[[LD]] to i64 +; OPT-LABEL: if.then: +; OPT: shl nsw i64 %[[EXT]], 1 +; DISABLE-LABEL: if.then: +; DISABLE: %r = sext i32 %shl2 to i64 + %ld = load i16, i16* %P + br i1 %c, label %end, label %if.then +if.then: + %z = zext i16 %ld to i32 + %shl2 = shl nsw i32 %z, 1 + %r = sext i32 %shl2 to i64 + ret i64 %r +end: + ret i64 0 +} diff --git a/test/CodeGen/AArch64/arm64-const-addr.ll b/test/CodeGen/AArch64/arm64-const-addr.ll index e55db29044894..bbb1ce4aced72 100644 --- a/test/CodeGen/AArch64/arm64-const-addr.ll +++ b/test/CodeGen/AArch64/arm64-const-addr.ll @@ -5,8 +5,8 @@ ; Test if the constant base address gets only materialized once. define i32 @test1() nounwind { ; CHECK-LABEL: test1 -; CHECK: mov w8, #68091904 -; CHECK-NEXT: movk w8, #49152 +; CHECK: mov w8, #49152 +; CHECK-NEXT: movk w8, #1039, lsl #16 ; CHECK-NEXT: ldp w9, w10, [x8, #4] ; CHECK: ldr w8, [x8, #12] %at = inttoptr i64 68141056 to %T* diff --git a/test/CodeGen/AArch64/arm64-crc32.ll b/test/CodeGen/AArch64/arm64-crc32.ll index 22111de5a3aa5..df9465a6bda57 100644 --- a/test/CodeGen/AArch64/arm64-crc32.ll +++ b/test/CodeGen/AArch64/arm64-crc32.ll @@ -1,4 +1,5 @@ ; RUN: llc -mtriple=arm64-eabi -mattr=+crc -o - %s | FileCheck %s +; RUN: llc -mtriple=arm64-eabi -mcpu=cortex-a53 -mattr=+crc -o - %s | FileCheck %s define i32 @test_crc32b(i32 %cur, i8 %next) { ; CHECK-LABEL: test_crc32b: diff --git a/test/CodeGen/AArch64/arm64-elf-globals.ll b/test/CodeGen/AArch64/arm64-elf-globals.ll index b1d5524aee873..92dc8179f8ea6 100644 --- a/test/CodeGen/AArch64/arm64-elf-globals.ll +++ b/test/CodeGen/AArch64/arm64-elf-globals.ll @@ -2,6 +2,10 @@ ; RUN: llc -mtriple=arm64-linux-gnu -o - %s -O0 -mcpu=cyclone | FileCheck %s --check-prefix=CHECK-FAST ; RUN: llc -mtriple=arm64-linux-gnu -relocation-model=pic -o - %s -mcpu=cyclone | FileCheck %s --check-prefix=CHECK-PIC ; RUN: llc -mtriple=arm64-linux-gnu -O0 -relocation-model=pic -o - %s -mcpu=cyclone | FileCheck %s --check-prefix=CHECK-FAST-PIC +; RUN: llc -mtriple=aarch64-fuchsia -code-model=kernel -o - %s -mcpu=cyclone | FileCheck %s +; RUN: llc -mtriple=aarch64-fuchsia -code-model=kernel -o - %s -O0 -mcpu=cyclone | FileCheck %s --check-prefix=CHECK-FAST +; RUN: llc -mtriple=aarch64-fuchsia -code-model=kernel -relocation-model=pic -o - %s -mcpu=cyclone | FileCheck %s --check-prefix=CHECK-PIC +; RUN: llc -mtriple=aarch64-fuchsia -code-model=kernel -O0 -relocation-model=pic -o - %s -mcpu=cyclone | FileCheck %s --check-prefix=CHECK-FAST-PIC @var8 = external global i8, align 1 @var16 = external global i16, align 2 diff --git a/test/CodeGen/AArch64/arm64-extern-weak.ll b/test/CodeGen/AArch64/arm64-extern-weak.ll index f00efbcea7804..990782cb69a00 100644 --- a/test/CodeGen/AArch64/arm64-extern-weak.ll +++ b/test/CodeGen/AArch64/arm64-extern-weak.ll @@ -15,10 +15,10 @@ define i32()* @foo() { ; In the large model, the usual relocations are absolute and can ; materialise 0. -; CHECK-LARGE: movz x0, #:abs_g3:var -; CHECK-LARGE: movk x0, #:abs_g2_nc:var +; CHECK-LARGE: movz x0, #:abs_g0_nc:var ; CHECK-LARGE: movk x0, #:abs_g1_nc:var -; CHECK-LARGE: movk x0, #:abs_g0_nc:var +; CHECK-LARGE: movk x0, #:abs_g2_nc:var +; CHECK-LARGE: movk x0, #:abs_g3:var } @@ -33,10 +33,10 @@ define i32* @bar() { ; In the large model, the usual relocations are absolute and can ; materialise 0. -; CHECK-LARGE: movz [[ARR_VAR:x[0-9]+]], #:abs_g3:arr_var -; CHECK-LARGE: movk [[ARR_VAR]], #:abs_g2_nc:arr_var +; CHECK-LARGE: movz [[ARR_VAR:x[0-9]+]], #:abs_g0_nc:arr_var ; CHECK-LARGE: movk [[ARR_VAR]], #:abs_g1_nc:arr_var -; CHECK-LARGE: movk [[ARR_VAR]], #:abs_g0_nc:arr_var +; CHECK-LARGE: movk [[ARR_VAR]], #:abs_g2_nc:arr_var +; CHECK-LARGE: movk [[ARR_VAR]], #:abs_g3:arr_var } @defined_weak_var = internal unnamed_addr global i32 0 @@ -46,8 +46,8 @@ define i32* @wibble() { ; CHECK: adrp [[BASE:x[0-9]+]], defined_weak_var ; CHECK: add x0, [[BASE]], :lo12:defined_weak_var -; CHECK-LARGE: movz x0, #:abs_g3:defined_weak_var -; CHECK-LARGE: movk x0, #:abs_g2_nc:defined_weak_var +; CHECK-LARGE: movz x0, #:abs_g0_nc:defined_weak_var ; CHECK-LARGE: movk x0, #:abs_g1_nc:defined_weak_var -; CHECK-LARGE: movk x0, #:abs_g0_nc:defined_weak_var +; CHECK-LARGE: movk x0, #:abs_g2_nc:defined_weak_var +; CHECK-LARGE: movk x0, #:abs_g3:defined_weak_var } diff --git a/test/CodeGen/AArch64/arm64-fast-isel-addr-offset.ll b/test/CodeGen/AArch64/arm64-fast-isel-addr-offset.ll index 9dae7a6f5b690..4aa10da7243d9 100644 --- a/test/CodeGen/AArch64/arm64-fast-isel-addr-offset.ll +++ b/test/CodeGen/AArch64/arm64-fast-isel-addr-offset.ll @@ -37,9 +37,9 @@ entry: define signext i8 @foo3() nounwind ssp { entry: ; CHECK-LABEL: @foo3 -; CHECK: mov x[[REG:[0-9]+]], #12343736008704 +; CHECK: mov x[[REG:[0-9]+]], #12274 ; CHECK: movk x[[REG]], #29646, lsl #16 -; CHECK: movk x[[REG]], #12274 +; CHECK: movk x[[REG]], #2874, lsl #32 %0 = load i8*, i8** @pd2, align 8 %arrayidx = getelementptr inbounds i8, i8* %0, i64 12345678901234 %1 = load i8, i8* %arrayidx, align 1 diff --git a/test/CodeGen/AArch64/arm64-indexed-vector-ldst.ll b/test/CodeGen/AArch64/arm64-indexed-vector-ldst.ll index 071b2d0dbca41..a502800923fdc 100644 --- a/test/CodeGen/AArch64/arm64-indexed-vector-ldst.ll +++ b/test/CodeGen/AArch64/arm64-indexed-vector-ldst.ll @@ -6216,11 +6216,11 @@ define <4 x i16> @test_v4i16_post_reg_ld1lane_forced_narrow(i16* %bar, i16** %pt declare <2 x i32> @llvm.ctpop.v2i32(<2 x i32>) ; CHECK-LABEL: test_ld1lane_build: -; CHECK-DAG: ld1.s { [[REG0:v[0-9]+]] }[0], [x0] -; CHECK-DAG: ld1.s { [[REG0:v[0-9]+]] }[1], [x1] -; CHECK-DAG: ld1.s { [[REG1:v[0-9]+]] }[0], [x2] -; CHECK-DAG: ld1.s { [[REG1:v[0-9]+]] }[1], [x3] -; CHECK: sub.2s v[[REGNUM2:[0-9]+]], [[REG0]], [[REG1]] +; CHECK-DAG: ldr s[[REGNUM0:[0-9]+]], [x0] +; CHECK-DAG: ld1.s { v[[REGNUM0:[0-9]+]] }[1], [x1] +; CHECK-DAG: ldr s[[REGNUM1:[0-9]+]], [x2] +; CHECK-DAG: ld1.s { v[[REGNUM1:[0-9]+]] }[1], [x3] +; CHECK: sub.2s v[[REGNUM2:[0-9]+]], v[[REGNUM0]], v[[REGNUM1]] ; CHECK-NEXT: str d[[REGNUM2]], [x4] ; CHECK-NEXT: ret define void @test_ld1lane_build(i32* %ptr0, i32* %ptr1, i32* %ptr2, i32* %ptr3, <2 x i32>* %out) { @@ -6238,3 +6238,84 @@ define void @test_ld1lane_build(i32* %ptr0, i32* %ptr1, i32* %ptr2, i32* %ptr3, store <2 x i32> %sub, <2 x i32>* %out, align 16 ret void } + +; CHECK-LABEL: test_ld1lane_build_i16: +; CHECK-DAG: ldr h[[REGNUM1:[0-9]+]], [x0] +; CHECK-DAG: ld1.h { v[[REGNUM1]] }[1], [x1] +; CHECK-DAG: ld1.h { v[[REGNUM1]] }[2], [x2] +; CHECK-DAG: ld1.h { v[[REGNUM1]] }[3], [x3] +; CHECK: sub.4h v[[REGNUM2:[0-9]+]], v[[REGNUM1]], v0 +; CHECK-NEXT: str d[[REGNUM2]], [x4] +; CHECK-NEXT: ret +define void @test_ld1lane_build_i16(i16* %a, i16* %b, i16* %c, i16* %d, <4 x i16> %e, <4 x i16>* %p) { + %ld.a = load i16, i16* %a + %ld.b = load i16, i16* %b + %ld.c = load i16, i16* %c + %ld.d = load i16, i16* %d + %v.a = insertelement <4 x i16> undef, i16 %ld.a, i64 0 + %v.b = insertelement <4 x i16> %v.a, i16 %ld.b, i64 1 + %v.c = insertelement <4 x i16> %v.b, i16 %ld.c, i64 2 + %v = insertelement <4 x i16> %v.c, i16 %ld.d, i64 3 + %sub = sub nsw <4 x i16> %v, %e + store <4 x i16> %sub, <4 x i16>* %p + ret void +} + +; CHECK-LABEL: test_ld1lane_build_half: +; CHECK-DAG: ldr h[[REGNUM1:[0-9]+]], [x0] +; CHECK-DAG: ld1.h { v[[REGNUM1]] }[1], [x1] +; CHECK-DAG: ld1.h { v[[REGNUM1]] }[2], [x2] +; CHECK-DAG: ld1.h { v[[REGNUM1]] }[3], [x3] +; CHECK-DAG: fcvtl v[[REGNUM01:[0-9]+]].4s, v0.4h +; CHECK-DAG: fcvtl v[[REGNUM11:[0-9]+]].4s, v[[REGNUM1]].4h +; CHECK: fsub.4s v[[REGNUM2:[0-9]+]], v[[REGNUM11]], v[[REGNUM01]] +; CHECK-DAG: fcvtn v[[REGNUM3:[0-9]+]].4h, v[[REGNUM2]].4s +; CHECK-NEXT: str d[[REGNUM2]], [x4] +; CHECK-NEXT: ret +define void @test_ld1lane_build_half(half* %a, half* %b, half* %c, half* %d, <4 x half> %e, <4 x half>* %p) { + %ld.a = load half, half* %a + %ld.b = load half, half* %b + %ld.c = load half, half* %c + %ld.d = load half, half* %d + %v.a = insertelement <4 x half> undef, half %ld.a, i64 0 + %v.b = insertelement <4 x half> %v.a, half %ld.b, i64 1 + %v.c = insertelement <4 x half> %v.b, half %ld.c, i64 2 + %v = insertelement <4 x half> %v.c, half %ld.d, i64 3 + %sub = fsub <4 x half> %v, %e + store <4 x half> %sub, <4 x half>* %p + ret void +} + +; CHECK-LABEL: test_ld1lane_build_i8: +; CHECK-DAG: ldr b[[REGNUM1:[0-9]+]], [x0] +; CHECK-DAG: ld1.b { v[[REGNUM1]] }[1], [x1] +; CHECK-DAG: ld1.b { v[[REGNUM1]] }[2], [x2] +; CHECK-DAG: ld1.b { v[[REGNUM1]] }[3], [x3] +; CHECK-DAG: ld1.b { v[[REGNUM1]] }[4], [x4] +; CHECK-DAG: ld1.b { v[[REGNUM1]] }[5], [x5] +; CHECK-DAG: ld1.b { v[[REGNUM1]] }[6], [x6] +; CHECK-DAG: ld1.b { v[[REGNUM1]] }[7], [x7] +; CHECK: sub.8b v[[REGNUM2:[0-9]+]], v[[REGNUM1]], v0 +; CHECK-NEXT: str d[[REGNUM2]], [x +; CHECK-NEXT: ret +define void @test_ld1lane_build_i8(i8* %a, i8* %b, i8* %c, i8* %d, i8* %e, i8* %f, i8* %g, i8* %h, <8 x i8> %v, <8 x i8>* %p) { + %ld.a = load i8, i8* %a + %ld.b = load i8, i8* %b + %ld.c = load i8, i8* %c + %ld.d = load i8, i8* %d + %ld.e = load i8, i8* %e + %ld.f = load i8, i8* %f + %ld.g = load i8, i8* %g + %ld.h = load i8, i8* %h + %v.a = insertelement <8 x i8> undef, i8 %ld.a, i64 0 + %v.b = insertelement <8 x i8> %v.a, i8 %ld.b, i64 1 + %v.c = insertelement <8 x i8> %v.b, i8 %ld.c, i64 2 + %v.d = insertelement <8 x i8> %v.c, i8 %ld.d, i64 3 + %v.e = insertelement <8 x i8> %v.d, i8 %ld.e, i64 4 + %v.f = insertelement <8 x i8> %v.e, i8 %ld.f, i64 5 + %v.g = insertelement <8 x i8> %v.f, i8 %ld.g, i64 6 + %v1 = insertelement <8 x i8> %v.g, i8 %ld.h, i64 7 + %sub = sub nsw <8 x i8> %v1, %v + store <8 x i8> %sub, <8 x i8>* %p + ret void +} diff --git a/test/CodeGen/AArch64/arm64-inline-asm.ll b/test/CodeGen/AArch64/arm64-inline-asm.ll index f3f3593804406..f28d0ab07c5ac 100644 --- a/test/CodeGen/AArch64/arm64-inline-asm.ll +++ b/test/CodeGen/AArch64/arm64-inline-asm.ll @@ -236,14 +236,14 @@ define void @test_zero_reg(i32* %addr) { define <2 x float> @test_vreg_64bit(<2 x float> %in) nounwind { ; CHECK-LABEL: test_vreg_64bit: %1 = tail call <2 x float> asm sideeffect "fadd ${0}.2s, ${1}.2s, ${1}.2s", "={v14},w"(<2 x float> %in) nounwind - ; CHECK fadd v14.2s, v0.2s, v0.2s: + ; CHECK: fadd v14.2s, v0.2s, v0.2s ret <2 x float> %1 } define <4 x float> @test_vreg_128bit(<4 x float> %in) nounwind { ; CHECK-LABEL: test_vreg_128bit: %1 = tail call <4 x float> asm sideeffect "fadd ${0}.4s, ${1}.4s, ${1}.4s", "={v14},w"(<4 x float> %in) nounwind - ; CHECK fadd v14.4s, v0.4s, v0.4s: + ; CHECK: fadd v14.4s, v0.4s, v0.4s ret <4 x float> %1 } diff --git a/test/CodeGen/AArch64/arm64-memset-inline.ll b/test/CodeGen/AArch64/arm64-memset-inline.ll index 8f22f97ca0870..384aaa8541df2 100644 --- a/test/CodeGen/AArch64/arm64-memset-inline.ll +++ b/test/CodeGen/AArch64/arm64-memset-inline.ll @@ -13,8 +13,8 @@ define void @t2() nounwind ssp { entry: ; CHECK-LABEL: t2: ; CHECK: strh wzr, [sp, #32] -; CHECK: stp xzr, xzr, [sp, #16] -; CHECK: str xzr, [sp, #8] +; CHECK: stp xzr, xzr, [sp, #8] +; CHECK: str xzr, [sp, #24] %buf = alloca [26 x i8], align 1 %0 = getelementptr inbounds [26 x i8], [26 x i8]* %buf, i32 0, i32 0 call void @llvm.memset.p0i8.i32(i8* %0, i8 0, i32 26, i32 1, i1 false) diff --git a/test/CodeGen/AArch64/arm64-movi.ll b/test/CodeGen/AArch64/arm64-movi.ll index c24490665d62c..8d6caa81d9785 100644 --- a/test/CodeGen/AArch64/arm64-movi.ll +++ b/test/CodeGen/AArch64/arm64-movi.ll @@ -51,24 +51,24 @@ define i32 @movz() nounwind { define i64 @movz_3movk() nounwind { ; CHECK-LABEL: movz_3movk: -; CHECK: mov x0, #1407374883553280 -; CHECK-NEXT: movk x0, #4660, lsl #32 +; CHECK: mov x0, #22136 ; CHECK-NEXT: movk x0, #43981, lsl #16 -; CHECK-NEXT: movk x0, #22136 +; CHECK-NEXT: movk x0, #4660, lsl #32 +; CHECK-NEXT: movk x0, #5, lsl #48 ret i64 1427392313513592 } define i64 @movz_movk_skip1() nounwind { ; CHECK-LABEL: movz_movk_skip1: -; CHECK: mov x0, #21474836480 -; CHECK-NEXT: movk x0, #17185, lsl #16 +; CHECK: mov x0, #1126236160 +; CHECK-NEXT: movk x0, #5, lsl #32 ret i64 22601072640 } define i64 @movz_skip1_movk() nounwind { ; CHECK-LABEL: movz_skip1_movk: -; CHECK: mov x0, #147695335374848 -; CHECK-NEXT: movk x0, #4660 +; CHECK: mov x0, #4660 +; CHECK-NEXT: movk x0, #34388, lsl #32 ret i64 147695335379508 } @@ -84,8 +84,8 @@ define i64 @movn() nounwind { define i64 @movn_skip1_movk() nounwind { ; CHECK-LABEL: movn_skip1_movk: -; CHECK: mov x0, #-176093659137 -; CHECK-NEXT: movk x0, #4660 +; CHECK: mov x0, #-60876 +; CHECK-NEXT: movk x0, #65494, lsl #32 ret i64 -176093720012 } @@ -195,8 +195,8 @@ define i64 @orr_movk13() nounwind { ; rdar://13944082 define i64 @g() nounwind { ; CHECK-LABEL: g: -; CHECK: mov x0, #-281474976710656 -; CHECK: movk x0, #2 +; CHECK: mov x0, #2 +; CHECK: movk x0, #65535, lsl #48 entry: ret i64 -281474976710654 } diff --git a/test/CodeGen/AArch64/arm64-neon-copy.ll b/test/CodeGen/AArch64/arm64-neon-copy.ll index 8d9a8c06aa3c5..a7b95e717910d 100644 --- a/test/CodeGen/AArch64/arm64-neon-copy.ll +++ b/test/CodeGen/AArch64/arm64-neon-copy.ll @@ -906,7 +906,7 @@ define <8 x i8> @getl(<16 x i8> %x) #0 { ; CHECK: str q0 ; CHECK-DAG: and [[MASKED_IDX:x[0-9]+]], x0, #0x7 ; CHECK: bfi [[PTR:x[0-9]+]], [[MASKED_IDX]], #1, #3 -; CHECK-DAG: ld1 { v[[R:[0-9]+]].h }[0], {{\[}}[[PTR]]{{\]}} +; CHECK-DAG: ldr h[[R:[0-9]+]], {{\[}}[[PTR]]{{\]}} ; CHECK-DAG: ins v[[R]].h[1], v0.h[1] ; CHECK-DAG: ins v[[R]].h[2], v0.h[2] ; CHECK-DAG: ins v[[R]].h[3], v0.h[3] diff --git a/test/CodeGen/AArch64/arm64-neon-v8.1a.ll b/test/CodeGen/AArch64/arm64-neon-v8.1a.ll index 45dba479ccc45..ae087ab8cf05d 100644 --- a/test/CodeGen/AArch64/arm64-neon-v8.1a.ll +++ b/test/CodeGen/AArch64/arm64-neon-v8.1a.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -verify-machineinstrs -mtriple=arm64-eabi -aarch64-neon-syntax=generic | FileCheck %s --check-prefix=CHECK-V8a +; RUN: llc < %s -verify-machineinstrs -mtriple=arm64-eabi -mattr=+rdm -aarch64-neon-syntax=generic | FileCheck %s --check-prefix=CHECK-V81a ; RUN: llc < %s -verify-machineinstrs -mtriple=arm64-eabi -mattr=+v8.1a -aarch64-neon-syntax=generic | FileCheck %s --check-prefix=CHECK-V81a ; RUN: llc < %s -verify-machineinstrs -mtriple=arm64-eabi -mattr=+v8.1a -aarch64-neon-syntax=apple | FileCheck %s --check-prefix=CHECK-V81a-apple diff --git a/test/CodeGen/AArch64/arm64-opt-remarks-lazy-bfi.ll b/test/CodeGen/AArch64/arm64-opt-remarks-lazy-bfi.ll new file mode 100644 index 0000000000000..7efb4bf6d5963 --- /dev/null +++ b/test/CodeGen/AArch64/arm64-opt-remarks-lazy-bfi.ll @@ -0,0 +1,63 @@ +; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -pass-remarks-analysis=asm-printer \ +; RUN: -pass-remarks-with-hotness=1 -asm-verbose=0 \ +; RUN: -debug-only=lazy-machine-block-freq,block-freq \ +; RUN: -debug-pass=Executions 2>&1 | FileCheck %s -check-prefix=HOTNESS + +; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -pass-remarks-analysis=asm-printer \ +; RUN: -pass-remarks-with-hotness=0 -asm-verbose=0 \ +; RUN: -debug-only=lazy-machine-block-freq,block-freq \ +; RUN: -debug-pass=Executions 2>&1 | FileCheck %s -check-prefix=NO_HOTNESS + +; REQUIRES: asserts + + +; Verify that we don't new populate MachineBFI for passes that already use +; MBFI, e.g. GreedyRegAlloc. (This hard-codes the previous pass to the +; GreedyRegAlloc, please adjust accordingly.) + +; HOTNESS: Executing Pass 'Spill Code Placement Analysis' +; HOTNESS-NEXT: Executing Pass 'Lazy Machine Block Frequency Analysis' +; HOTNESS-NEXT: Executing Pass 'Machine Optimization Remark Emitter' +; HOTNESS-NEXT: MachineBlockFrequencyInfo is available +; HOTNESS-NEXT: Executing Pass 'Greedy Register Allocator' + + +; Verify that we only populate MachineBFI on behalf of ORE when hotness is +; requested. (This hard-codes the previous pass to the Assembly Printer, +; please adjust accordingly.) + +; HOTNESS: Executing Pass 'Implement the 'patchable-function' attribute' +; HOTNESS-NEXT: Freeing Pass 'Implement the 'patchable-function' attribute' +; HOTNESS-NEXT: Executing Pass 'Lazy Machine Block Frequency Analysis' +; HOTNESS-NEXT: Executing Pass 'Machine Optimization Remark Emitter' +; HOTNESS-NEXT: Building MachineBlockFrequencyInfo on the fly +; HOTNESS-NEXT: Building LoopInfo on the fly +; HOTNESS-NEXT: Building DominatorTree on the fly +; HOTNESS-NOT: Executing Pass +; HOTNESS: block-frequency: empty_func +; HOTNESS-NOT: Executing Pass +; HOTNESS: Executing Pass 'AArch64 Assembly Printer' + +; HOTNESS: arm64-summary-remarks.ll:5:0: 1 instructions in function (hotness: 33) + + +; NO_HOTNESS: Executing Pass 'Implement the 'patchable-function' attribute' +; NO_HOTNESS-NEXT: Freeing Pass 'Implement the 'patchable-function' attribute' +; NO_HOTNESS-NEXT: Executing Pass 'Lazy Machine Block Frequency Analysis' +; NO_HOTNESS-NEXT: Executing Pass 'Machine Optimization Remark Emitter' +; NO_HOTNESS-NEXT: Executing Pass 'AArch64 Assembly Printer' + +; NO_HOTNESS: arm64-summary-remarks.ll:5:0: 1 instructions in function{{$}} + +define void @empty_func() nounwind ssp !dbg !3 !prof !4 { + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2} + +!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1) +!1 = !DIFile(filename: "arm64-summary-remarks.ll", directory: "") +!2 = !{i32 2, !"Debug Info Version", i32 3} +!3 = distinct !DISubprogram(name: "empty_func", scope: !1, file: !1, line: 5, scopeLine: 5, unit: !0) +!4 = !{!"function_entry_count", i64 33} diff --git a/test/CodeGen/AArch64/arm64-regress-opt-cmp.mir b/test/CodeGen/AArch64/arm64-regress-opt-cmp.mir index bda025af51936..9ad47c721c3a0 100644 --- a/test/CodeGen/AArch64/arm64-regress-opt-cmp.mir +++ b/test/CodeGen/AArch64/arm64-regress-opt-cmp.mir @@ -1,4 +1,4 @@ -# RUN: llc -mtriple=aarch64-linux-gnu -run-pass peephole-opt -o - %s 2>&1 | FileCheck %s +# RUN: llc -mtriple=aarch64-linux-gnu -run-pass peephole-opt -o - %s | FileCheck %s # CHECK: %1 = ANDWri {{.*}} # CHECK-NEXT: %wzr = SUBSWri {{.*}} --- | diff --git a/test/CodeGen/AArch64/arm64-shrink-wrapping.ll b/test/CodeGen/AArch64/arm64-shrink-wrapping.ll index 255cd8e4a0d3c..4df220eddbbbe 100644 --- a/test/CodeGen/AArch64/arm64-shrink-wrapping.ll +++ b/test/CodeGen/AArch64/arm64-shrink-wrapping.ll @@ -346,19 +346,15 @@ entry: ; CHECK-NEXT: sub w1, w1, #1 ; CHECK-NEXT: add [[SUM]], [[SUM]], [[VA_VAL]] ; CHECK-NEXT: cbnz w1, [[LOOP_LABEL]] -; DISABLE-NEXT: b [[IFEND_LABEL]] -; -; DISABLE: [[ELSE_LABEL]]: ; %if.else -; DISABLE: lsl w0, w1, #1 -; -; CHECK: [[IFEND_LABEL]]: +; CHECK-NEXT: [[IFEND_LABEL]]: ; Epilogue code. ; CHECK: add sp, sp, #16 ; CHECK-NEXT: ret ; -; ENABLE: [[ELSE_LABEL]]: ; %if.else -; ENABLE-NEXT: lsl w0, w1, #1 -; ENABLE_NEXT: ret +; CHECK: [[ELSE_LABEL]]: ; %if.else +; CHECK-NEXT: lsl w0, w1, #1 +; DISABLE-NEXT: add sp, sp, #16 +; CHECK-NEXT: ret define i32 @variadicFunc(i32 %cond, i32 %count, ...) #0 { entry: %ap = alloca i8*, align 8 diff --git a/test/CodeGen/AArch64/arm64-spill-remarks.ll b/test/CodeGen/AArch64/arm64-spill-remarks.ll new file mode 100644 index 0000000000000..bc9340352d754 --- /dev/null +++ b/test/CodeGen/AArch64/arm64-spill-remarks.ll @@ -0,0 +1,117 @@ +; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -aarch64-neon-syntax=apple -pass-remarks-missed=regalloc 2>&1 | FileCheck -check-prefix=REMARK %s +; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -aarch64-neon-syntax=apple -pass-remarks-missed=regalloc -pass-remarks-with-hotness 2>&1 | FileCheck -check-prefix=HOTNESS %s +; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -aarch64-neon-syntax=apple 2>&1 | FileCheck -check-prefix=NO_REMARK %s +; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -aarch64-neon-syntax=apple -pass-remarks-output=%t.yaml -pass-remarks-with-hotness 2>&1 | FileCheck -check-prefix=NO_REMARK %s +; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s + +; This has two nested loops, each with one value that has to be spilled and +; then reloaded. + +; (loop3:) +; REMARK: remark: /tmp/kk.c:3:20: 1 spills 1 reloads generated in loop{{$}} +; (loop2:) +; REMARK: remark: /tmp/kk.c:2:20: 1 spills 1 reloads generated in loop{{$}} +; (loop:) +; REMARK: remark: /tmp/kk.c:1:20: 2 spills 2 reloads generated in loop{{$}} + +; (loop3:) +; HOTNESS: remark: /tmp/kk.c:3:20: 1 spills 1 reloads generated in loop (hotness: 300) +; (loop2:) +; HOTNESS: remark: /tmp/kk.c:2:20: 1 spills 1 reloads generated in loop (hotness: 30000) +; (loop:) +; HOTNESS: remark: /tmp/kk.c:1:20: 2 spills 2 reloads generated in loop (hotness: 300) + +; NO_REMARK-NOT: remark + +; YAML: --- !Missed +; YAML: Pass: regalloc +; YAML: Name: LoopSpillReload +; YAML: DebugLoc: { File: /tmp/kk.c, Line: 3, Column: 20 } +; YAML: Function: fpr128 +; YAML: Hotness: 300 +; YAML: Args: +; YAML: - NumSpills: '1' +; YAML: - String: ' spills ' +; YAML: - NumReloads: '1' +; YAML: - String: ' reloads ' +; YAML: - String: generated in loop +; YAML: ... +; YAML: --- !Missed +; YAML: Pass: regalloc +; YAML: Name: LoopSpillReload +; YAML: DebugLoc: { File: /tmp/kk.c, Line: 2, Column: 20 } +; YAML: Function: fpr128 +; YAML: Hotness: 30000 +; YAML: Args: +; YAML: - NumSpills: '1' +; YAML: - String: ' spills ' +; YAML: - NumReloads: '1' +; YAML: - String: ' reloads ' +; YAML: - String: generated in loop +; YAML: ... +; YAML: --- !Missed +; YAML: Pass: regalloc +; YAML: Name: LoopSpillReload +; YAML: DebugLoc: { File: /tmp/kk.c, Line: 1, Column: 20 } +; YAML: Function: fpr128 +; YAML: Hotness: 300 +; YAML: Args: +; YAML: - NumSpills: '2' +; YAML: - String: ' spills ' +; YAML: - NumReloads: '2' +; YAML: - String: ' reloads ' +; YAML: - String: generated in loop +; YAML: ... + +define void @fpr128(<4 x float>* %p) nounwind ssp !prof !11 { +entry: + br label %loop, !dbg !8 + +loop: + %i = phi i32 [ 0, %entry], [ %i.2, %end2 ] + br label %loop2, !dbg !9 + +loop2: + %j = phi i32 [ 0, %loop], [ %j.2, %loop2 ] + call void asm sideeffect "; inlineasm", "~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{q16},~{q17},~{q18},~{q19},~{q20},~{q21},~{q22},~{q23},~{q24},~{q25},~{q26},~{q27},~{q28},~{q29},~{q30},~{q31},~{x0},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x13},~{x14},~{x15},~{x16},~{x17},~{x18},~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28},~{fp},~{lr},~{sp},~{memory}"() nounwind + %j.2 = add i32 %j, 1 + %c2 = icmp slt i32 %j.2, 100 + br i1 %c2, label %loop2, label %end2, !prof !12 + +end2: + call void asm sideeffect "; inlineasm", "~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{q16},~{q17},~{q18},~{q19},~{q20},~{q21},~{q22},~{q23},~{q24},~{q25},~{q26},~{q27},~{q28},~{q29},~{q30},~{q31},~{x0},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x13},~{x14},~{x15},~{x16},~{x17},~{x18},~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28},~{fp},~{lr},~{sp},~{memory}"() nounwind + %i.2 = add i32 %i, 1 + %c = icmp slt i32 %i.2, 100 + br i1 %c, label %loop, label %end, !prof !12 + +end: + br label %loop3 + +loop3: + %k = phi i32 [ 0, %end], [ %k.2, %loop3 ] + call void asm sideeffect "; inlineasm", "~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{q16},~{q17},~{q18},~{q19},~{q20},~{q21},~{q22},~{q23},~{q24},~{q25},~{q26},~{q27},~{q28},~{q29},~{q30},~{q31},~{x0},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x13},~{x14},~{x15},~{x16},~{x17},~{x18},~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28},~{fp},~{lr},~{sp},~{memory}"() nounwind + %k.2 = add i32 %k, 1 + %c3 = icmp slt i32 %k.2, 100 + br i1 %c3, label %loop3, label %end3, !dbg !10, !prof !12 + +end3: + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} +!llvm.ident = !{!5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2) +!1 = !DIFile(filename: "/tmp/kk.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"PIC Level", i32 2} +!5 = !{!"clang version 3.9.0 "} +!6 = distinct !DISubprogram(name: "success", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2) +!7 = !DISubroutineType(types: !2) +!8 = !DILocation(line: 1, column: 20, scope: !6) +!9 = !DILocation(line: 2, column: 20, scope: !6) +!10 = !DILocation(line: 3, column: 20, scope: !6) +!11 = !{!"function_entry_count", i64 3} +!12 = !{!"branch_weights", i32 99, i32 1} diff --git a/test/CodeGen/AArch64/arm64-summary-remarks.ll b/test/CodeGen/AArch64/arm64-summary-remarks.ll new file mode 100644 index 0000000000000..70e7fdffd63db --- /dev/null +++ b/test/CodeGen/AArch64/arm64-summary-remarks.ll @@ -0,0 +1,15 @@ +; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -pass-remarks-analysis=asm-printer 2>&1 | FileCheck %s + +; CHECK: arm64-summary-remarks.ll:5:0: 1 instructions in function + +define void @empty_func() nounwind ssp !dbg !3 { + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2} + +!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1) +!1 = !DIFile(filename: "arm64-summary-remarks.ll", directory: "") +!2 = !{i32 2, !"Debug Info Version", i32 3} +!3 = distinct !DISubprogram(name: "empty_func", scope: !1, file: !1, line: 5, scopeLine: 5, unit: !0) diff --git a/test/CodeGen/AArch64/arm64-variadic-aapcs.ll b/test/CodeGen/AArch64/arm64-variadic-aapcs.ll index 16ddf690fe959..375877c517989 100644 --- a/test/CodeGen/AArch64/arm64-variadic-aapcs.ll +++ b/test/CodeGen/AArch64/arm64-variadic-aapcs.ll @@ -99,7 +99,7 @@ define void @test_nospare([8 x i64], [8 x float], ...) { ; __stack field should point just past them. define void @test_offsetstack([8 x i64], [2 x i64], [3 x float], ...) { ; CHECK-LABEL: test_offsetstack: -; CHECK: sub sp, sp, #80 +; CHECK: stp {{q[0-9]+}}, {{q[0-9]+}}, [sp, #-80]! ; CHECK: add [[STACK_TOP:x[0-9]+]], sp, #96 ; CHECK: add x[[VAR:[0-9]+]], {{x[0-9]+}}, :lo12:var ; CHECK: str [[STACK_TOP]], [x[[VAR]]] diff --git a/test/CodeGen/AArch64/bitfield-insert.ll b/test/CodeGen/AArch64/bitfield-insert.ll index 735be244d4575..42b0051a2dd60 100644 --- a/test/CodeGen/AArch64/bitfield-insert.ll +++ b/test/CodeGen/AArch64/bitfield-insert.ll @@ -428,8 +428,8 @@ define i32 @test5(i32 %a) { ; BFXIL will use the same constant as the ORR, so we don't care how the constant ; is materialized (it's an equal cost either way). ; CHECK-LABEL: @test6 -; CHECK: mov [[REG:w[0-9]+]], #720896 -; CHECK: movk [[REG]], #23250 +; CHECK: mov [[REG:w[0-9]+]], #23250 +; CHECK: movk [[REG]], #11, lsl #16 ; CHECK: bfxil w0, [[REG]], #0, #20 define i32 @test6(i32 %a) { %1 = and i32 %a, 4293918720 ; 0xfff00000 @@ -440,8 +440,8 @@ define i32 @test6(i32 %a) { ; BFIs that require the same number of instruction to materialize the constant ; as the original ORR are okay. ; CHECK-LABEL: @test7 -; CHECK: mov [[REG:w[0-9]+]], #327680 -; CHECK: movk [[REG]], #44393 +; CHECK: mov [[REG:w[0-9]+]], #44393 +; CHECK: movk [[REG]], #5, lsl #16 ; CHECK: bfi w0, [[REG]], #1, #19 define i32 @test7(i32 %a) { %1 = and i32 %a, 4293918721 ; 0xfff00001 @@ -454,9 +454,9 @@ define i32 @test7(i32 %a) { ; 'and' with a 'movk', which would decrease ILP while using the same number of ; instructions. ; CHECK-LABEL: @test8 -; CHECK: mov [[REG2:x[0-9]+]], #157599529959424 +; CHECK: mov [[REG2:x[0-9]+]], #2035482624 ; CHECK: and [[REG1:x[0-9]+]], x0, #0xff000000000000ff -; CHECK: movk [[REG2]], #31059, lsl #16 +; CHECK: movk [[REG2]], #36694, lsl #32 ; CHECK: orr x0, [[REG1]], [[REG2]] define i64 @test8(i64 %a) { %1 = and i64 %a, -72057594037927681 ; 0xff000000000000ff diff --git a/test/CodeGen/AArch64/blockaddress.ll b/test/CodeGen/AArch64/blockaddress.ll index 7c0755a13d0e0..3683332c2c64a 100644 --- a/test/CodeGen/AArch64/blockaddress.ll +++ b/test/CodeGen/AArch64/blockaddress.ll @@ -14,10 +14,10 @@ define void @test_blockaddress() { ; CHECK: ldr [[NEWDEST:x[0-9]+]] ; CHECK: br [[NEWDEST]] -; CHECK-LARGE: movz [[ADDR_REG:x[0-9]+]], #:abs_g3:[[DEST_LBL:.Ltmp[0-9]+]] -; CHECK-LARGE: movk [[ADDR_REG]], #:abs_g2_nc:[[DEST_LBL]] +; CHECK-LARGE: movz [[ADDR_REG:x[0-9]+]], #:abs_g0_nc:[[DEST_LBL:.Ltmp[0-9]+]] ; CHECK-LARGE: movk [[ADDR_REG]], #:abs_g1_nc:[[DEST_LBL]] -; CHECK-LARGE: movk [[ADDR_REG]], #:abs_g0_nc:[[DEST_LBL]] +; CHECK-LARGE: movk [[ADDR_REG]], #:abs_g2_nc:[[DEST_LBL]] +; CHECK-LARGE: movk [[ADDR_REG]], #:abs_g3:[[DEST_LBL]] ; CHECK-LARGE: str [[ADDR_REG]], ; CHECK-LARGE: ldr [[NEWDEST:x[0-9]+]] ; CHECK-LARGE: br [[NEWDEST]] diff --git a/test/CodeGen/AArch64/br-cond-not-merge.ll b/test/CodeGen/AArch64/br-cond-not-merge.ll new file mode 100644 index 0000000000000..bf21ef3079056 --- /dev/null +++ b/test/CodeGen/AArch64/br-cond-not-merge.ll @@ -0,0 +1,94 @@ +; RUN: llc -mtriple=aarch64 -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK --check-prefix=OPT %s +; RUN: llc -mtriple=aarch64 -verify-machineinstrs -O0 -fast-isel=0 < %s | FileCheck --check-prefix=CHECK --check-prefix=NOOPT %s + +declare void @foo() + +; Check that the inverted or doesn't inhibit the splitting of the +; complex conditional into three branch instructions. +; CHECK-LABEL: test_and_not: +; CHECK: cbz w0, [[L:\.LBB[0-9_]+]] +; OPT: cmp w1, #2 +; NOOPT: subs w{{[0-9]+}}, w{{[0-9]+}}, #2 +; CHECK: b.lo [[L]] +; OPT: cmp w2, #2 +; NOOPT: subs w{{[0-9]+}}, w{{[0-9]+}}, #2 +; CHECK: b.hi [[L]] +define void @test_and_not(i32 %a, i32 %b, i32 %c) { +bb1: + %cmp1 = icmp ult i32 %a, 1 + %cmp2 = icmp ult i32 %b, 2 + %cmp3 = icmp ult i32 %c, 3 + %or = or i1 %cmp1, %cmp2 + %not.or = xor i1 %or, -1 + %and = and i1 %not.or, %cmp3 + br i1 %and, label %bb2, label %bb3 + +bb2: + ret void + +bb3: + call void @foo() + ret void +} + +; Check that non-canonicalized xor not is handled correctly by FindMergedConditions. +; CHECK-LABEL: test_and_not2: +; CHECK: cbz w0, [[L:\.LBB[0-9_]+]] +; OPT: cmp w1, #2 +; NOOPT: subs w{{[0-9]+}}, w{{[0-9]+}}, #2 +; CHECK: b.lo [[L]] +; OPT: cmp w2, #2 +; NOOPT: subs w{{[0-9]+}}, w{{[0-9]+}}, #2 +; CHECK: b.hi [[L]] +define void @test_and_not2(i32 %a, i32 %b, i32 %c) { +bb1: + %cmp1 = icmp ult i32 %a, 1 + %cmp2 = icmp ult i32 %b, 2 + %cmp3 = icmp ult i32 %c, 3 + %or = or i1 %cmp1, %cmp2 + %not.or = xor i1 -1, %or + %and = and i1 %not.or, %cmp3 + br i1 %and, label %bb2, label %bb3 + +bb2: + ret void + +bb3: + call void @foo() + ret void +} + +; Check that cmps in different blocks are handled correctly by FindMergedConditions. +; CHECK-LABEL: test_cmp_other_block: +; OPT: cmp w{{[0-9]+}}, #0 +; OPT: b.gt [[L:\.LBB[0-9_]+]] +; OPT: tbz w1, #0, [[L]] +; +; NOOPT: subs w{{[0-9]+}}, w{{[0-9]+}}, #0 +; NOOPT: cset [[R1:w[0-9]+]], gt +; NOOPT: str w1, [sp, #[[SLOT2:[0-9]+]]] +; NOOPT: str [[R1]], [sp, #[[SLOT1:[0-9]+]]] +; NOOPT: b .LBB +; NOOPT: ldr [[R2:w[0-9]+]], [sp, #[[SLOT1]]] +; NOOPT: tbnz [[R2]], #0, [[L:\.LBB[0-9_]+]] +; NOOPT: ldr [[R3:w[0-9]+]], [sp, #[[SLOT2]]] +; NOOPT: tbz [[R3]], #0, [[L]] +define void @test_cmp_other_block(i32* %p, i1 %c) { +entry: + %l = load i32, i32* %p + %cmp = icmp sgt i32 %l, 0 + br label %bb1 + +bb1: + %cmp.i = xor i1 %cmp, true + %or.cond1.i = and i1 %cmp.i, %c + br i1 %or.cond1.i, label %bb2, label %bb3 + +bb2: + ret void + +bb3: + call void @foo() + ret void +} + diff --git a/test/CodeGen/AArch64/branch-relax-cbz.ll b/test/CodeGen/AArch64/branch-relax-cbz.ll index c654b94e49cf0..d13c0f677bcb5 100644 --- a/test/CodeGen/AArch64/branch-relax-cbz.ll +++ b/test/CodeGen/AArch64/branch-relax-cbz.ll @@ -6,23 +6,22 @@ ; CHECK-NEXT: ; BB#1: ; %b3 ; CHECK: ldr [[LOAD:w[0-9]+]] -; CHECK: cbz [[LOAD]], [[SKIP_LONG_B:LBB[0-9]+_[0-9]+]] -; CHECK-NEXT: b [[B8:LBB[0-9]+_[0-9]+]] - -; CHECK-NEXT: [[SKIP_LONG_B]]: +; CHECK: cbnz [[LOAD]], [[B8:LBB[0-9]+_[0-9]+]] ; CHECK-NEXT: b [[B7:LBB[0-9]+_[0-9]+]] +; CHECK-NEXT: [[B8]]: ; %b8 +; CHECK-NEXT: ret + ; CHECK-NEXT: [[B2]]: ; %b2 ; CHECK: mov w{{[0-9]+}}, #93 ; CHECK: bl _extfunc ; CHECK: cbz w{{[0-9]+}}, [[B7]] - -; CHECK-NEXT: [[B8]]: ; %b8 -; CHECK-NEXT: ret +; CHECK-NEXT: b [[B8]] ; CHECK-NEXT: [[B7]]: ; %b7 ; CHECK: mov w{{[0-9]+}}, #13 ; CHECK: b _extfunc + define void @split_block_no_fallthrough(i64 %val) #0 { bb: %c0 = icmp sgt i64 %val, -5 diff --git a/test/CodeGen/AArch64/code-model-large-abs.ll b/test/CodeGen/AArch64/code-model-large-abs.ll index 1680815d93ea4..82169acc3e561 100644 --- a/test/CodeGen/AArch64/code-model-large-abs.ll +++ b/test/CodeGen/AArch64/code-model-large-abs.ll @@ -9,10 +9,10 @@ define i8* @global_addr() { ; CHECK-LABEL: global_addr: ret i8* @var8 ; The movz/movk calculation should end up returned directly in x0. -; CHECK: movz x0, #:abs_g3:var8 -; CHECK: movk x0, #:abs_g2_nc:var8 +; CHECK: movz x0, #:abs_g0_nc:var8 ; CHECK: movk x0, #:abs_g1_nc:var8 -; CHECK: movk x0, #:abs_g0_nc:var8 +; CHECK: movk x0, #:abs_g2_nc:var8 +; CHECK: movk x0, #:abs_g3:var8 ; CHECK-NEXT: ret } @@ -20,10 +20,10 @@ define i8 @global_i8() { ; CHECK-LABEL: global_i8: %val = load i8, i8* @var8 ret i8 %val -; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g3:var8 -; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var8 +; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g0_nc:var8 ; CHECK: movk x[[ADDR_REG]], #:abs_g1_nc:var8 -; CHECK: movk x[[ADDR_REG]], #:abs_g0_nc:var8 +; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var8 +; CHECK: movk x[[ADDR_REG]], #:abs_g3:var8 ; CHECK: ldrb w0, [x[[ADDR_REG]]] } @@ -31,10 +31,10 @@ define i16 @global_i16() { ; CHECK-LABEL: global_i16: %val = load i16, i16* @var16 ret i16 %val -; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g3:var16 -; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var16 +; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g0_nc:var16 ; CHECK: movk x[[ADDR_REG]], #:abs_g1_nc:var16 -; CHECK: movk x[[ADDR_REG]], #:abs_g0_nc:var16 +; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var16 +; CHECK: movk x[[ADDR_REG]], #:abs_g3:var16 ; CHECK: ldrh w0, [x[[ADDR_REG]]] } @@ -42,10 +42,10 @@ define i32 @global_i32() { ; CHECK-LABEL: global_i32: %val = load i32, i32* @var32 ret i32 %val -; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g3:var32 -; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var32 +; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g0_nc:var32 ; CHECK: movk x[[ADDR_REG]], #:abs_g1_nc:var32 -; CHECK: movk x[[ADDR_REG]], #:abs_g0_nc:var32 +; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var32 +; CHECK: movk x[[ADDR_REG]], #:abs_g3:var32 ; CHECK: ldr w0, [x[[ADDR_REG]]] } @@ -53,9 +53,9 @@ define i64 @global_i64() { ; CHECK-LABEL: global_i64: %val = load i64, i64* @var64 ret i64 %val -; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g3:var64 -; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var64 +; CHECK: movz x[[ADDR_REG:[0-9]+]], #:abs_g0_nc:var64 ; CHECK: movk x[[ADDR_REG]], #:abs_g1_nc:var64 -; CHECK: movk x[[ADDR_REG]], #:abs_g0_nc:var64 +; CHECK: movk x[[ADDR_REG]], #:abs_g2_nc:var64 +; CHECK: movk x[[ADDR_REG]], #:abs_g3:var64 ; CHECK: ldr x0, [x[[ADDR_REG]]] } diff --git a/test/CodeGen/AArch64/concat_vector-scalar-combine.ll b/test/CodeGen/AArch64/concat_vector-scalar-combine.ll index 1c64af636cb35..3abb14241ea07 100644 --- a/test/CodeGen/AArch64/concat_vector-scalar-combine.ll +++ b/test/CodeGen/AArch64/concat_vector-scalar-combine.ll @@ -38,7 +38,7 @@ entry: define <8 x i8> @test_concat_scalars_2x_v2i8_to_v8i8(i32 %x, i32 %y) #0 { entry: ; CHECK-LABEL: test_concat_scalars_2x_v2i8_to_v8i8: -; CHECK-NEXT: ins.h v0[0], w0 +; CHECK-NEXT: fmov s0, w0 ; CHECK-NEXT: ins.h v0[1], w1 ; CHECK-NEXT: ins.h v0[3], w1 ; CHECK-NEXT: ret @@ -84,7 +84,7 @@ define <8 x i8> @test_concat_scalars_mixed_2x_v2i8_to_v8i8(float %dummy, i32 %x, entry: ; CHECK-LABEL: test_concat_scalars_mixed_2x_v2i8_to_v8i8: ; CHECK-NEXT: fmov s[[X:[0-9]+]], w0 -; CHECK-NEXT: ins.h v0[0], v[[X]][0] +; CHECK-NEXT: mov.16b v0, v[[X]] ; CHECK-NEXT: ins.h v0[1], v1[0] ; CHECK-NEXT: ins.h v0[2], v[[X]][0] ; CHECK-NEXT: ins.h v0[3], v1[0] @@ -99,7 +99,7 @@ entry: define <2 x float> @test_concat_scalars_fp_2x_v2i8_to_v8i8(float %dummy, half %x, half %y) #0 { entry: ; CHECK-LABEL: test_concat_scalars_fp_2x_v2i8_to_v8i8: -; CHECK-NEXT: ins.h v0[0], v1[0] +; CHECK-NEXT: mov.16b v0, v1 ; CHECK-NEXT: ins.h v0[1], v2[0] ; CHECK-NEXT: ins.h v0[2], v1[0] ; CHECK-NEXT: ins.h v0[3], v2[0] diff --git a/test/CodeGen/AArch64/cpus.ll b/test/CodeGen/AArch64/cpus.ll index 50685cf5d3432..f65144def2457 100644 --- a/test/CodeGen/AArch64/cpus.ll +++ b/test/CodeGen/AArch64/cpus.ll @@ -12,7 +12,7 @@ ; RUN: llc < %s -mtriple=arm64-unknown-unknown -mcpu=exynos-m3 2>&1 | FileCheck %s ; RUN: llc < %s -mtriple=arm64-unknown-unknown -mcpu=falkor 2>&1 | FileCheck %s ; RUN: llc < %s -mtriple=arm64-unknown-unknown -mcpu=kryo 2>&1 | FileCheck %s -; RUN: llc < %s -mtriple=arm64-unknown-unknown -mcpu=vulcan 2>&1 | FileCheck %s +; RUN: llc < %s -mtriple=arm64-unknown-unknown -mcpu=thunderx2t99 2>&1 | FileCheck %s ; RUN: llc < %s -mtriple=arm64-unknown-unknown -mcpu=invalidcpu 2>&1 | FileCheck %s --check-prefix=INVALID ; CHECK-NOT: {{.*}} is not a recognized processor for this target diff --git a/test/CodeGen/AArch64/dag-numsignbits.ll b/test/CodeGen/AArch64/dag-numsignbits.ll new file mode 100644 index 0000000000000..217c3df77c9c8 --- /dev/null +++ b/test/CodeGen/AArch64/dag-numsignbits.ll @@ -0,0 +1,33 @@ +; RUN: llc < %s -mtriple=aarch64-unknown | FileCheck %s + +; PR32273 + +define void @signbits_vXi1(<4 x i16> %a1) { +; CHECK-LABEL: signbits_vXi1 +; CHECK: cmgt v0.4h, v1.4h, v0.4h +; CHECK-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-NEXT: shl v0.4h, v0.4h, #15 +; CHECK-NEXT: sshr v0.4h, v0.4h, #15 +; CHECK-NEXT: umov w0, v0.h[0] +; CHECK-NEXT: umov w3, v0.h[3] +; CHECK-NEXT: mov w1, wzr +; CHECK-NEXT: mov w2, wzr +; CHECK-NEXT: b foo + %tmp3 = shufflevector <4 x i16> %a1, <4 x i16> undef, <4 x i32> zeroinitializer + %tmp5 = add <4 x i16> %tmp3, <i16 18249, i16 6701, i16 -18744, i16 -25086> + %tmp6 = icmp slt <4 x i16> %tmp5, <i16 1, i16 1, i16 1, i16 1> + %tmp7 = and <4 x i1> %tmp6, <i1 true, i1 false, i1 false, i1 true> + %tmp8 = sext <4 x i1> %tmp7 to <4 x i16> + %tmp9 = extractelement <4 x i16> %tmp8, i32 0 + %tmp10 = zext i16 %tmp9 to i32 + %tmp11 = extractelement <4 x i16> %tmp8, i32 1 + %tmp12 = zext i16 %tmp11 to i32 + %tmp13 = extractelement <4 x i16> %tmp8, i32 2 + %tmp14 = zext i16 %tmp13 to i32 + %tmp15 = extractelement <4 x i16> %tmp8, i32 3 + %tmp16 = zext i16 %tmp15 to i32 + tail call void @foo(i32 %tmp10, i32 %tmp12, i32 %tmp14, i32 %tmp16) + ret void +} + +declare void @foo(i32, i32, i32, i32) diff --git a/test/CodeGen/AArch64/eliminate-trunc.ll b/test/CodeGen/AArch64/eliminate-trunc.ll index bc4ac7d717044..83730d15d7f5f 100644 --- a/test/CodeGen/AArch64/eliminate-trunc.ll +++ b/test/CodeGen/AArch64/eliminate-trunc.ll @@ -6,7 +6,7 @@ ; CHECK-NOT: add {{x[0-9]+}}, {{x[0-9]+}}, #1 ; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, #1 ; CHECK-NEXT: cmp {{w[0-9]+}}, {{w[0-9]+}} -define void @test1_signed([8 x i8]* nocapture %a, i8* nocapture readonly %box, i8 %limit) minsize { +define void @test1_signed([8 x i8]* nocapture %a, i8* nocapture readonly %box, i8 %limit, i64 %inv) minsize { entry: %conv = zext i8 %limit to i32 %cmp223 = icmp eq i8 %limit, 0 @@ -14,7 +14,7 @@ entry: for.body4.us: %indvars.iv = phi i64 [ 0, %for.body4.lr.ph.us ], [ %indvars.iv.next, %for.body4.us ] - %arrayidx6.us = getelementptr inbounds [8 x i8], [8 x i8]* %a, i64 %indvars.iv26, i64 %indvars.iv + %arrayidx6.us = getelementptr inbounds [8 x i8], [8 x i8]* %a, i64 %indvars.iv, i64 %inv %0 = load i8, i8* %arrayidx6.us, align 1 %idxprom7.us = zext i8 %0 to i64 %arrayidx8.us = getelementptr inbounds i8, i8* %box, i64 %idxprom7.us diff --git a/test/CodeGen/AArch64/extern-weak.ll b/test/CodeGen/AArch64/extern-weak.ll index 921009cf821db..ac2153ad8ffed 100644 --- a/test/CodeGen/AArch64/extern-weak.ll +++ b/test/CodeGen/AArch64/extern-weak.ll @@ -16,10 +16,10 @@ define i32()* @foo() { ; In the large model, the usual relocations are absolute and can ; materialise 0. -; CHECK-LARGE: movz x0, #:abs_g3:var -; CHECK-LARGE: movk x0, #:abs_g2_nc:var +; CHECK-LARGE: movz x0, #:abs_g0_nc:var ; CHECK-LARGE: movk x0, #:abs_g1_nc:var -; CHECK-LARGE: movk x0, #:abs_g0_nc:var +; CHECK-LARGE: movk x0, #:abs_g2_nc:var +; CHECK-LARGE: movk x0, #:abs_g3:var } @@ -37,10 +37,10 @@ define i32* @bar() { ; In the large model, the usual relocations are absolute and can ; materialise 0. -; CHECK-LARGE: movz [[ADDR:x[0-9]+]], #:abs_g3:arr_var -; CHECK-LARGE: movk [[ADDR]], #:abs_g2_nc:arr_var +; CHECK-LARGE: movz [[ADDR:x[0-9]+]], #:abs_g0_nc:arr_var ; CHECK-LARGE: movk [[ADDR]], #:abs_g1_nc:arr_var -; CHECK-LARGE: movk [[ADDR]], #:abs_g0_nc:arr_var +; CHECK-LARGE: movk [[ADDR]], #:abs_g2_nc:arr_var +; CHECK-LARGE: movk [[ADDR]], #:abs_g3:arr_var } @defined_weak_var = internal unnamed_addr global i32 0 @@ -51,8 +51,8 @@ define i32* @wibble() { ; CHECK: adrp [[BASE:x[0-9]+]], defined_weak_var ; CHECK: add x0, [[BASE]], :lo12:defined_weak_var -; CHECK-LARGE: movz x0, #:abs_g3:defined_weak_var -; CHECK-LARGE: movk x0, #:abs_g2_nc:defined_weak_var +; CHECK-LARGE: movz x0, #:abs_g0_nc:defined_weak_var ; CHECK-LARGE: movk x0, #:abs_g1_nc:defined_weak_var -; CHECK-LARGE: movk x0, #:abs_g0_nc:defined_weak_var +; CHECK-LARGE: movk x0, #:abs_g2_nc:defined_weak_var +; CHECK-LARGE: movk x0, #:abs_g3:defined_weak_var } diff --git a/test/CodeGen/AArch64/fast-isel-tail-call.ll b/test/CodeGen/AArch64/fast-isel-tail-call.ll new file mode 100644 index 0000000000000..0efaa37344862 --- /dev/null +++ b/test/CodeGen/AArch64/fast-isel-tail-call.ll @@ -0,0 +1,24 @@ +; RUN: llc -fast-isel -pass-remarks-missed=isel -pass-remarks-missed=isel \ +; RUN: -mtriple arm64-- < %s 2> %t | FileCheck %s +; RUN: cat %t | FileCheck %s --check-prefix MISSED + +%struct = type { [4 x i32] } + +declare %struct @external() + +; Check that, when fastisel falls back to SDAG, we don't emit instructions +; that follow a tail-call and would have been dropped by pure SDAGISel. + +; Here, the %struct extractvalue should fail FastISel. + +; MISSED: FastISel missed: %tmp1 = extractvalue %struct %tmp0, 0 + +; CHECK-LABEL: test: +; CHECK: b external +; CHECK-NEXT: .Lfunc_end0: +define i32 @test() nounwind { + %tmp0 = tail call %struct @external() + %tmp1 = extractvalue %struct %tmp0, 0 + %tmp2 = extractvalue [4 x i32] %tmp1, 0 + ret i32 %tmp2 +} diff --git a/test/CodeGen/AArch64/fast-isel-tbz.ll b/test/CodeGen/AArch64/fast-isel-tbz.ll index af817777143dd..d6d10318bf025 100644 --- a/test/CodeGen/AArch64/fast-isel-tbz.ll +++ b/test/CodeGen/AArch64/fast-isel-tbz.ll @@ -278,8 +278,24 @@ bb2: ; Test that we don't fold the 'and' instruction into the compare. define i32 @icmp_eq_and_i32(i32 %a, i1 %c) { ; CHECK-LABEL: icmp_eq_and_i32 -; CHECK: and [[REG:w[0-9]+]], w0, #0x4 +; CHECK: and [[REG:w[0-9]+]], w0, #0x3 ; CHECK-NEXT: cbz [[REG]], {{LBB.+_3}} + %1 = and i32 %a, 3 + br i1 %c, label %bb0, label %bb2 +bb0: + %2 = icmp eq i32 %1, 0 + br i1 %2, label %bb1, label %bb2, !prof !0 +bb1: + ret i32 1 +bb2: + ret i32 0 +} + +; Test that we do fold the 'and' instruction into the compare and +; generate a tbz instruction for the conditional branch. +define i32 @icmp_eq_and1bit_i32(i32 %a, i1 %c) { +; CHECK-LABEL: icmp_eq_and1bit_i32 +; CHECK: tbz {{w[0-9]+}}, #2, {{LBB.+_3}} %1 = and i32 %a, 4 br i1 %c, label %bb0, label %bb2 bb0: diff --git a/test/CodeGen/AArch64/fpimm.ll b/test/CodeGen/AArch64/fpimm.ll index b4faef750a2c3..d19777c4d27e4 100644 --- a/test/CodeGen/AArch64/fpimm.ll +++ b/test/CodeGen/AArch64/fpimm.ll @@ -38,18 +38,18 @@ define void @check_double() { } ; LARGE-LABEL: check_float2 -; LARGE: mov [[REG:w[0-9]+]], #1078525952 -; LARGE-NEXT: movk [[REG]], #4059 +; LARGE: mov [[REG:w[0-9]+]], #4059 +; LARGE-NEXT: movk [[REG]], #16457, lsl #16 ; LARGE-NEXT: fmov s0, [[REG]] define float @check_float2() { ret float 3.14159274101257324218750 } ; LARGE-LABEL: check_double2 -; LARGE: mov [[REG:x[0-9]+]], #4614219293217783808 -; LARGE-NEXT: movk [[REG]], #8699, lsl #32 +; LARGE: mov [[REG:x[0-9]+]], #11544 ; LARGE-NEXT: movk [[REG]], #21572, lsl #16 -; LARGE-NEXT: movk [[REG]], #11544 +; LARGE-NEXT: movk [[REG]], #8699, lsl #32 +; LARGE-NEXT: movk [[REG]], #16393, lsl #48 ; LARGE-NEXT: fmov d0, [[REG]] define double @check_double2() { ret double 3.1415926535897931159979634685441851615905761718750 diff --git a/test/CodeGen/AArch64/jump-table.ll b/test/CodeGen/AArch64/jump-table.ll index d6a7fceac84da..f71d4356be35a 100644 --- a/test/CodeGen/AArch64/jump-table.ll +++ b/test/CodeGen/AArch64/jump-table.ll @@ -16,10 +16,10 @@ define i32 @test_jumptable(i32 %in) { ; CHECK: ldr [[DEST:x[0-9]+]], [x[[JT]], {{x[0-9]+}}, lsl #3] ; CHECK: br [[DEST]] -; CHECK-LARGE: movz x[[JTADDR:[0-9]+]], #:abs_g3:.LJTI0_0 -; CHECK-LARGE: movk x[[JTADDR]], #:abs_g2_nc:.LJTI0_0 +; CHECK-LARGE: movz x[[JTADDR:[0-9]+]], #:abs_g0_nc:.LJTI0_0 ; CHECK-LARGE: movk x[[JTADDR]], #:abs_g1_nc:.LJTI0_0 -; CHECK-LARGE: movk x[[JTADDR]], #:abs_g0_nc:.LJTI0_0 +; CHECK-LARGE: movk x[[JTADDR]], #:abs_g2_nc:.LJTI0_0 +; CHECK-LARGE: movk x[[JTADDR]], #:abs_g3:.LJTI0_0 ; CHECK-LARGE: ldr [[DEST:x[0-9]+]], [x[[JTADDR]], {{x[0-9]+}}, lsl #3] ; CHECK-LARGE: br [[DEST]] diff --git a/test/CodeGen/AArch64/large-consts.ll b/test/CodeGen/AArch64/large-consts.ll index 6bf85e829f61e..e351c35306961 100644 --- a/test/CodeGen/AArch64/large-consts.ll +++ b/test/CodeGen/AArch64/large-consts.ll @@ -5,10 +5,10 @@ define double @foo() { -; CHECK: movz [[CPADDR:x[0-9]+]], #:abs_g3:.LCPI0_0 // encoding: [0bAAA01000,A,0b111AAAAA,0xd2] -; CHECK: movk [[CPADDR]], #:abs_g2_nc:.LCPI0_0 // encoding: [0bAAA01000,A,0b110AAAAA,0xf2] +; CHECK: movz [[CPADDR:x[0-9]+]], #:abs_g0_nc:.LCPI0_0 // encoding: [0bAAA01000,A,0b100AAAAA,0xd2] ; CHECK: movk [[CPADDR]], #:abs_g1_nc:.LCPI0_0 // encoding: [0bAAA01000,A,0b101AAAAA,0xf2] -; CHECK: movk [[CPADDR]], #:abs_g0_nc:.LCPI0_0 // encoding: [0bAAA01000,A,0b100AAAAA,0xf2] +; CHECK: movk [[CPADDR]], #:abs_g2_nc:.LCPI0_0 // encoding: [0bAAA01000,A,0b110AAAAA,0xf2] +; CHECK: movk [[CPADDR]], #:abs_g3:.LCPI0_0 // encoding: [0bAAA01000,A,0b111AAAAA,0xf2] ret double 3.14159 } diff --git a/test/CodeGen/AArch64/ldst-opt-aa.mir b/test/CodeGen/AArch64/ldst-opt-aa.mir new file mode 100644 index 0000000000000..808926ae3cd1f --- /dev/null +++ b/test/CodeGen/AArch64/ldst-opt-aa.mir @@ -0,0 +1,30 @@ +# RUN: llc -mtriple=aarch64--linux-gnu -run-pass=aarch64-ldst-opt %s -verify-machineinstrs -o - | FileCheck %s +--- | + define void @ldr_str_aa(i32* noalias nocapture %x, i32* noalias nocapture readonly %y) { + entry: + %0 = load i32, i32* %y, align 4 + store i32 %0, i32* %x, align 4 + %arrayidx2 = getelementptr inbounds i32, i32* %y, i32 1 + %1 = load i32, i32* %arrayidx2, align 4 + %arrayidx3 = getelementptr inbounds i32, i32* %x, i32 1 + store i32 %1, i32* %arrayidx3, align 4 + ret void + } + +... +--- +# CHECK-LABEL: name: ldr_str_aa +# CHECK: %w8, %w9 = LDPWi %x1, 0 +# CHECK: STPWi %w8, %w9, %x0, 0 +name: ldr_str_aa +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: %x0, %x1 + + %w8 = LDRWui %x1, 0 :: (load 4 from %ir.y) + STRWui killed %w8, %x0, 0 :: (store 4 into %ir.x) + %w9 = LDRWui killed %x1, 1 :: (load 4 from %ir.arrayidx2) + STRWui killed %w9, killed %x0, 1 :: (store 4 into %ir.arrayidx3) + RET undef %lr + diff --git a/test/CodeGen/AArch64/ldst-opt.mir b/test/CodeGen/AArch64/ldst-opt.mir index 85b655b717ca9..f7641d3ffd04c 100644 --- a/test/CodeGen/AArch64/ldst-opt.mir +++ b/test/CodeGen/AArch64/ldst-opt.mir @@ -1,4 +1,4 @@ -# RUN: llc -mtriple=aarch64--linux-gnu -run-pass=aarch64-ldst-opt %s -verify-machineinstrs -o - 2>&1 | FileCheck %s +# RUN: llc -mtriple=aarch64--linux-gnu -run-pass=aarch64-ldst-opt %s -verify-machineinstrs -o - | FileCheck %s --- name: promote-load-from-store tracksRegLiveness: true diff --git a/test/CodeGen/AArch64/literal_pools_float.ll b/test/CodeGen/AArch64/literal_pools_float.ll index f5d6a17f3a114..6ad685ad7c495 100644 --- a/test/CodeGen/AArch64/literal_pools_float.ll +++ b/test/CodeGen/AArch64/literal_pools_float.ll @@ -15,10 +15,10 @@ define void @floating_lits() { ; CHECK: ldr [[LIT128:s[0-9]+]], [x[[LITBASE]], {{#?}}:lo12:[[CURLIT]]] ; CHECK-NOFP-NOT: ldr {{s[0-9]+}}, -; CHECK-LARGE: movz x[[LITADDR:[0-9]+]], #:abs_g3:[[CURLIT:.LCPI[0-9]+_[0-9]+]] -; CHECK-LARGE: movk x[[LITADDR]], #:abs_g2_nc:[[CURLIT]] +; CHECK-LARGE: movz x[[LITADDR:[0-9]+]], #:abs_g0_nc:[[CURLIT:.LCPI[0-9]+_[0-9]+]] ; CHECK-LARGE: movk x[[LITADDR]], #:abs_g1_nc:[[CURLIT]] -; CHECK-LARGE: movk x[[LITADDR]], #:abs_g0_nc:[[CURLIT]] +; CHECK-LARGE: movk x[[LITADDR]], #:abs_g2_nc:[[CURLIT]] +; CHECK-LARGE: movk x[[LITADDR]], #:abs_g3:[[CURLIT]] ; CHECK-LARGE: ldr {{s[0-9]+}}, [x[[LITADDR]]] ; CHECK-LARGE: fadd ; CHECK-NOFP-LARGE-NOT: ldr {{s[0-9]+}}, @@ -33,10 +33,10 @@ define void @floating_lits() { ; CHECK-NOFP-NOT: ldr {{d[0-9]+}}, ; CHECK-NOFP-NOT: fadd -; CHECK-LARGE: movz x[[LITADDR:[0-9]+]], #:abs_g3:[[CURLIT:.LCPI[0-9]+_[0-9]+]] -; CHECK-LARGE: movk x[[LITADDR]], #:abs_g2_nc:[[CURLIT]] +; CHECK-LARGE: movz x[[LITADDR:[0-9]+]], #:abs_g0_nc:[[CURLIT:.LCPI[0-9]+_[0-9]+]] ; CHECK-LARGE: movk x[[LITADDR]], #:abs_g1_nc:[[CURLIT]] -; CHECK-LARGE: movk x[[LITADDR]], #:abs_g0_nc:[[CURLIT]] +; CHECK-LARGE: movk x[[LITADDR]], #:abs_g2_nc:[[CURLIT]] +; CHECK-LARGE: movk x[[LITADDR]], #:abs_g3:[[CURLIT]] ; CHECK-LARGE: ldr {{d[0-9]+}}, [x[[LITADDR]]] ; CHECK-NOFP-LARGE-NOT: ldr {{d[0-9]+}}, diff --git a/test/CodeGen/AArch64/live-interval-analysis.mir b/test/CodeGen/AArch64/live-interval-analysis.mir new file mode 100644 index 0000000000000..d44300973566c --- /dev/null +++ b/test/CodeGen/AArch64/live-interval-analysis.mir @@ -0,0 +1,22 @@ +# RUN: llc -o /dev/null %s -mtriple=aarch64-darwin-ios -run-pass=liveintervals -debug-only=regalloc -precompute-phys-liveness 2>&1 | FileCheck %s +# REQUIRES: asserts +--- | + define void @reserved_reg_liveness() { ret void } +... +--- +# CHECK-LABEL: ********** INTERVALS ********** +# W29 is reserved, so we should only see dead defs +# CHECK-DAG: W29 [0B,0d:{{[0-9]+}})[32r,32d:{{[0-9]+}})[64r,64d:{{[0-9]+}}) +# For normal registers like x28 we should see the full intervals +# CHECK-DAG: W28 [0B,16r:{{[0-9]+}})[32r,48r:{{[0-9]+}})[48r,48d:{{[0-9]+}}) +# CHECK: # End machine code for function reserved_reg_liveness. +name: reserved_reg_liveness +tracksRegLiveness: true +body: | + bb.0: + liveins: %x28_fp + %6 : xseqpairsclass = COPY %x28_fp + %x28_fp = COPY %6 + %x28 = COPY %x28 + %fp = COPY %fp +... diff --git a/test/CodeGen/AArch64/load-combine-big-endian.ll b/test/CodeGen/AArch64/load-combine-big-endian.ll new file mode 100644 index 0000000000000..918ceaeb1b4fa --- /dev/null +++ b/test/CodeGen/AArch64/load-combine-big-endian.ll @@ -0,0 +1,584 @@ +; RUN: llc < %s -mtriple=arm64eb-unknown | FileCheck %s + +; i8* p; // p is 4 byte aligned +; ((i32) p[0] << 24) | ((i32) p[1] << 16) | ((i32) p[2] << 8) | (i32) p[3] +define i32 @load_i32_by_i8_big_endian(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_big_endian: +; CHECK: ldr w0, [x0] +; CHECK-NEXT: ret + %tmp = bitcast i32* %arg to i8* + %tmp1 = load i8, i8* %tmp, align 4 + %tmp2 = zext i8 %tmp1 to i32 + %tmp3 = shl nuw nsw i32 %tmp2, 24 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 16 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 2 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 8 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 3 + %tmp15 = load i8, i8* %tmp14, align 1 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = or i32 %tmp13, %tmp16 + ret i32 %tmp17 +} + +; i8* p; // p is 4 byte aligned +; ((i32) (((i16) p[0] << 8) | (i16) p[1]) << 16) | (i32) (((i16) p[3] << 8) | (i16) p[4]) +define i32 @load_i32_by_i16_by_i8_big_endian(i32* %arg) { +; CHECK-LABEL: load_i32_by_i16_by_i8_big_endian: +; CHECK: ldr w0, [x0] +; CHECK-NEXT: ret + %tmp = bitcast i32* %arg to i8* + %tmp1 = load i8, i8* %tmp, align 4 + %tmp2 = zext i8 %tmp1 to i16 + %tmp3 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp4 = load i8, i8* %tmp3, align 1 + %tmp5 = zext i8 %tmp4 to i16 + %tmp6 = shl nuw nsw i16 %tmp2, 8 + %tmp7 = or i16 %tmp6, %tmp5 + %tmp8 = getelementptr inbounds i8, i8* %tmp, i32 2 + %tmp9 = load i8, i8* %tmp8, align 1 + %tmp10 = zext i8 %tmp9 to i16 + %tmp11 = getelementptr inbounds i8, i8* %tmp, i32 3 + %tmp12 = load i8, i8* %tmp11, align 1 + %tmp13 = zext i8 %tmp12 to i16 + %tmp14 = shl nuw nsw i16 %tmp10, 8 + %tmp15 = or i16 %tmp14, %tmp13 + %tmp16 = zext i16 %tmp7 to i32 + %tmp17 = zext i16 %tmp15 to i32 + %tmp18 = shl nuw nsw i32 %tmp16, 16 + %tmp19 = or i32 %tmp18, %tmp17 + ret i32 %tmp19 +} + +; i16* p; // p is 4 byte aligned +; ((i32) p[0] << 16) | (i32) p[1] +define i32 @load_i32_by_i16(i32* %arg) { +; CHECK-LABEL: load_i32_by_i16: +; CHECK: ldr w0, [x0] +; CHECK-NEXT: ret + %tmp = bitcast i32* %arg to i16* + %tmp1 = load i16, i16* %tmp, align 4 + %tmp2 = zext i16 %tmp1 to i32 + %tmp3 = getelementptr inbounds i16, i16* %tmp, i32 1 + %tmp4 = load i16, i16* %tmp3, align 1 + %tmp5 = zext i16 %tmp4 to i32 + %tmp6 = shl nuw nsw i32 %tmp2, 16 + %tmp7 = or i32 %tmp6, %tmp5 + ret i32 %tmp7 +} + +; i16* p_16; // p_16 is 4 byte aligned +; i8* p_8 = (i8*) p_16; +; (i32) (p_16[0] << 16) | ((i32) p[2] << 8) | (i32) p[3] +define i32 @load_i32_by_i16_i8(i32* %arg) { +; CHECK-LABEL: load_i32_by_i16_i8: +; CHECK: ldr w0, [x0] +; CHECK-NEXT: ret + %tmp = bitcast i32* %arg to i16* + %tmp1 = bitcast i32* %arg to i8* + %tmp2 = load i16, i16* %tmp, align 4 + %tmp3 = zext i16 %tmp2 to i32 + %tmp4 = shl nuw nsw i32 %tmp3, 16 + %tmp5 = getelementptr inbounds i8, i8* %tmp1, i32 2 + %tmp6 = load i8, i8* %tmp5, align 1 + %tmp7 = zext i8 %tmp6 to i32 + %tmp8 = shl nuw nsw i32 %tmp7, 8 + %tmp9 = getelementptr inbounds i8, i8* %tmp1, i32 3 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = or i32 %tmp8, %tmp11 + %tmp13 = or i32 %tmp12, %tmp4 + ret i32 %tmp13 +} + +; i8* p; // p is 8 byte aligned +; (i64) p[0] | ((i64) p[1] << 8) | ((i64) p[2] << 16) | ((i64) p[3] << 24) | ((i64) p[4] << 32) | ((i64) p[5] << 40) | ((i64) p[6] << 48) | ((i64) p[7] << 56) +define i64 @load_i64_by_i8_bswap(i64* %arg) { +; CHECK-LABEL: load_i64_by_i8_bswap: +; CHECK: ldr x8, [x0] +; CHECK-NEXT: rev x0, x8 +; CHECK-NEXT: ret + %tmp = bitcast i64* %arg to i8* + %tmp1 = load i8, i8* %tmp, align 8 + %tmp2 = zext i8 %tmp1 to i64 + %tmp3 = getelementptr inbounds i8, i8* %tmp, i64 1 + %tmp4 = load i8, i8* %tmp3, align 1 + %tmp5 = zext i8 %tmp4 to i64 + %tmp6 = shl nuw nsw i64 %tmp5, 8 + %tmp7 = or i64 %tmp6, %tmp2 + %tmp8 = getelementptr inbounds i8, i8* %tmp, i64 2 + %tmp9 = load i8, i8* %tmp8, align 1 + %tmp10 = zext i8 %tmp9 to i64 + %tmp11 = shl nuw nsw i64 %tmp10, 16 + %tmp12 = or i64 %tmp7, %tmp11 + %tmp13 = getelementptr inbounds i8, i8* %tmp, i64 3 + %tmp14 = load i8, i8* %tmp13, align 1 + %tmp15 = zext i8 %tmp14 to i64 + %tmp16 = shl nuw nsw i64 %tmp15, 24 + %tmp17 = or i64 %tmp12, %tmp16 + %tmp18 = getelementptr inbounds i8, i8* %tmp, i64 4 + %tmp19 = load i8, i8* %tmp18, align 1 + %tmp20 = zext i8 %tmp19 to i64 + %tmp21 = shl nuw nsw i64 %tmp20, 32 + %tmp22 = or i64 %tmp17, %tmp21 + %tmp23 = getelementptr inbounds i8, i8* %tmp, i64 5 + %tmp24 = load i8, i8* %tmp23, align 1 + %tmp25 = zext i8 %tmp24 to i64 + %tmp26 = shl nuw nsw i64 %tmp25, 40 + %tmp27 = or i64 %tmp22, %tmp26 + %tmp28 = getelementptr inbounds i8, i8* %tmp, i64 6 + %tmp29 = load i8, i8* %tmp28, align 1 + %tmp30 = zext i8 %tmp29 to i64 + %tmp31 = shl nuw nsw i64 %tmp30, 48 + %tmp32 = or i64 %tmp27, %tmp31 + %tmp33 = getelementptr inbounds i8, i8* %tmp, i64 7 + %tmp34 = load i8, i8* %tmp33, align 1 + %tmp35 = zext i8 %tmp34 to i64 + %tmp36 = shl nuw i64 %tmp35, 56 + %tmp37 = or i64 %tmp32, %tmp36 + ret i64 %tmp37 +} + +; i8* p; // p is 8 byte aligned +; ((i64) p[0] << 56) | ((i64) p[1] << 48) | ((i64) p[2] << 40) | ((i64) p[3] << 32) | ((i64) p[4] << 24) | ((i64) p[5] << 16) | ((i64) p[6] << 8) | (i64) p[7] +define i64 @load_i64_by_i8(i64* %arg) { +; CHECK-LABEL: load_i64_by_i8: +; CHECK: ldr x0, [x0] +; CHECK-NEXT: ret + %tmp = bitcast i64* %arg to i8* + %tmp1 = load i8, i8* %tmp, align 8 + %tmp2 = zext i8 %tmp1 to i64 + %tmp3 = shl nuw i64 %tmp2, 56 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i64 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i64 + %tmp7 = shl nuw nsw i64 %tmp6, 48 + %tmp8 = or i64 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i64 2 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i64 + %tmp12 = shl nuw nsw i64 %tmp11, 40 + %tmp13 = or i64 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i64 3 + %tmp15 = load i8, i8* %tmp14, align 1 + %tmp16 = zext i8 %tmp15 to i64 + %tmp17 = shl nuw nsw i64 %tmp16, 32 + %tmp18 = or i64 %tmp13, %tmp17 + %tmp19 = getelementptr inbounds i8, i8* %tmp, i64 4 + %tmp20 = load i8, i8* %tmp19, align 1 + %tmp21 = zext i8 %tmp20 to i64 + %tmp22 = shl nuw nsw i64 %tmp21, 24 + %tmp23 = or i64 %tmp18, %tmp22 + %tmp24 = getelementptr inbounds i8, i8* %tmp, i64 5 + %tmp25 = load i8, i8* %tmp24, align 1 + %tmp26 = zext i8 %tmp25 to i64 + %tmp27 = shl nuw nsw i64 %tmp26, 16 + %tmp28 = or i64 %tmp23, %tmp27 + %tmp29 = getelementptr inbounds i8, i8* %tmp, i64 6 + %tmp30 = load i8, i8* %tmp29, align 1 + %tmp31 = zext i8 %tmp30 to i64 + %tmp32 = shl nuw nsw i64 %tmp31, 8 + %tmp33 = or i64 %tmp28, %tmp32 + %tmp34 = getelementptr inbounds i8, i8* %tmp, i64 7 + %tmp35 = load i8, i8* %tmp34, align 1 + %tmp36 = zext i8 %tmp35 to i64 + %tmp37 = or i64 %tmp33, %tmp36 + ret i64 %tmp37 +} + +; i8* p; // p[1] is 4 byte aligned +; (i32) p[1] | ((i32) p[2] << 8) | ((i32) p[3] << 16) | ((i32) p[4] << 24) +define i32 @load_i32_by_i8_nonzero_offset(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_nonzero_offset: +; CHECK: ldur w8, [x0, #1] +; CHECK-NEXT: rev w0, w8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp2 = load i8, i8* %tmp1, align 4 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 2 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 3 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 16 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 4 + %tmp15 = load i8, i8* %tmp14, align 1 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = shl nuw nsw i32 %tmp16, 24 + %tmp18 = or i32 %tmp13, %tmp17 + ret i32 %tmp18 +} + +; i8* p; // p[-4] is 4 byte aligned +; (i32) p[-4] | ((i32) p[-3] << 8) | ((i32) p[-2] << 16) | ((i32) p[-1] << 24) +define i32 @load_i32_by_i8_neg_offset(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_neg_offset: +; CHECK: ldur w8, [x0, #-4] +; CHECK-NEXT: rev w0, w8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 -4 + %tmp2 = load i8, i8* %tmp1, align 4 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 -3 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 -2 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 16 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 -1 + %tmp15 = load i8, i8* %tmp14, align 1 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = shl nuw nsw i32 %tmp16, 24 + %tmp18 = or i32 %tmp13, %tmp17 + ret i32 %tmp18 +} + +; i8* p; // p[1] is 4 byte aligned +; (i32) p[4] | ((i32) p[3] << 8) | ((i32) p[2] << 16) | ((i32) p[1] << 24) +define i32 @load_i32_by_i8_nonzero_offset_bswap(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_nonzero_offset_bswap: +; CHECK: ldur w0, [x0, #1] +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 4 + %tmp2 = load i8, i8* %tmp1, align 1 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 3 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 2 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 16 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp15 = load i8, i8* %tmp14, align 4 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = shl nuw nsw i32 %tmp16, 24 + %tmp18 = or i32 %tmp13, %tmp17 + ret i32 %tmp18 +} + +; i8* p; // p[-4] is 4 byte aligned +; (i32) p[-1] | ((i32) p[-2] << 8) | ((i32) p[-3] << 16) | ((i32) p[-4] << 24) +define i32 @load_i32_by_i8_neg_offset_bswap(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_neg_offset_bswap: +; CHECK: ldur w0, [x0, #-4] +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 -1 + %tmp2 = load i8, i8* %tmp1, align 1 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 -2 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 -3 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 16 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 -4 + %tmp15 = load i8, i8* %tmp14, align 4 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = shl nuw nsw i32 %tmp16, 24 + %tmp18 = or i32 %tmp13, %tmp17 + ret i32 %tmp18 +} + +declare i16 @llvm.bswap.i16(i16) + +; i16* p; // p is 4 byte aligned +; (i32) bswap(p[0]) | (i32) bswap(p[1] << 16) +define i32 @load_i32_by_bswap_i16(i32* %arg) { +; CHECK-LABEL: load_i32_by_bswap_i16: +; CHECK: ldr w8, [x0] +; CHECK-NEXT: rev w0, w8 +; CHECK-NEXT: ret + %tmp = bitcast i32* %arg to i16* + %tmp1 = load i16, i16* %tmp, align 4 + %tmp11 = call i16 @llvm.bswap.i16(i16 %tmp1) + %tmp2 = zext i16 %tmp11 to i32 + %tmp3 = getelementptr inbounds i16, i16* %tmp, i32 1 + %tmp4 = load i16, i16* %tmp3, align 1 + %tmp41 = call i16 @llvm.bswap.i16(i16 %tmp4) + %tmp5 = zext i16 %tmp41 to i32 + %tmp6 = shl nuw nsw i32 %tmp5, 16 + %tmp7 = or i32 %tmp6, %tmp2 + ret i32 %tmp7 +} + +; i16* p; // p is 4 byte aligned +; (i32) p[1] | (sext(p[0] << 16) to i32) +define i32 @load_i32_by_sext_i16(i32* %arg) { +; CHECK-LABEL: load_i32_by_sext_i16: +; CHECK: ldr w0, [x0] +; CHECK-NEXT: ret + %tmp = bitcast i32* %arg to i16* + %tmp1 = load i16, i16* %tmp, align 4 + %tmp2 = sext i16 %tmp1 to i32 + %tmp3 = getelementptr inbounds i16, i16* %tmp, i32 1 + %tmp4 = load i16, i16* %tmp3, align 1 + %tmp5 = zext i16 %tmp4 to i32 + %tmp6 = shl nuw nsw i32 %tmp2, 16 + %tmp7 = or i32 %tmp6, %tmp5 + ret i32 %tmp7 +} + +; i8* arg; i32 i; +; p = arg + 12; +; (i32) p[i] | ((i32) p[i + 1] << 8) | ((i32) p[i + 2] << 16) | ((i32) p[i + 3] << 24) +define i32 @load_i32_by_i8_base_offset_index(i8* %arg, i32 %i) { +; CHECK-LABEL: load_i32_by_i8_base_offset_index: +; CHECK: add x8, x0, w1, uxtw +; CHECK-NEXT: ldr w8, [x8, #12] +; CHECK-NEXT: rev w0, w8 +; CHECK-NEXT: ret + %tmp = add nuw nsw i32 %i, 3 + %tmp2 = add nuw nsw i32 %i, 2 + %tmp3 = add nuw nsw i32 %i, 1 + %tmp4 = getelementptr inbounds i8, i8* %arg, i64 12 + %tmp5 = zext i32 %i to i64 + %tmp6 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp5 + %tmp7 = load i8, i8* %tmp6, align 4 + %tmp8 = zext i8 %tmp7 to i32 + %tmp9 = zext i32 %tmp3 to i64 + %tmp10 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp9 + %tmp11 = load i8, i8* %tmp10, align 1 + %tmp12 = zext i8 %tmp11 to i32 + %tmp13 = shl nuw nsw i32 %tmp12, 8 + %tmp14 = or i32 %tmp13, %tmp8 + %tmp15 = zext i32 %tmp2 to i64 + %tmp16 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp15 + %tmp17 = load i8, i8* %tmp16, align 1 + %tmp18 = zext i8 %tmp17 to i32 + %tmp19 = shl nuw nsw i32 %tmp18, 16 + %tmp20 = or i32 %tmp14, %tmp19 + %tmp21 = zext i32 %tmp to i64 + %tmp22 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp21 + %tmp23 = load i8, i8* %tmp22, align 1 + %tmp24 = zext i8 %tmp23 to i32 + %tmp25 = shl nuw i32 %tmp24, 24 + %tmp26 = or i32 %tmp20, %tmp25 + ret i32 %tmp26 +} + +; i8* arg; i32 i; +; p = arg + 12; +; (i32) p[i + 1] | ((i32) p[i + 2] << 8) | ((i32) p[i + 3] << 16) | ((i32) p[i + 4] << 24) +define i32 @load_i32_by_i8_base_offset_index_2(i8* %arg, i32 %i) { +; CHECK-LABEL: load_i32_by_i8_base_offset_index_2: +; CHECK: add x8, x0, w1, uxtw +; CHECK-NEXT: ldur w8, [x8, #13] +; CHECK-NEXT: rev w0, w8 +; CHECK-NEXT: ret + %tmp = add nuw nsw i32 %i, 4 + %tmp2 = add nuw nsw i32 %i, 3 + %tmp3 = add nuw nsw i32 %i, 2 + %tmp4 = getelementptr inbounds i8, i8* %arg, i64 12 + %tmp5 = add nuw nsw i32 %i, 1 + %tmp27 = zext i32 %tmp5 to i64 + %tmp28 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp27 + %tmp29 = load i8, i8* %tmp28, align 4 + %tmp30 = zext i8 %tmp29 to i32 + %tmp31 = zext i32 %tmp3 to i64 + %tmp32 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp31 + %tmp33 = load i8, i8* %tmp32, align 1 + %tmp34 = zext i8 %tmp33 to i32 + %tmp35 = shl nuw nsw i32 %tmp34, 8 + %tmp36 = or i32 %tmp35, %tmp30 + %tmp37 = zext i32 %tmp2 to i64 + %tmp38 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp37 + %tmp39 = load i8, i8* %tmp38, align 1 + %tmp40 = zext i8 %tmp39 to i32 + %tmp41 = shl nuw nsw i32 %tmp40, 16 + %tmp42 = or i32 %tmp36, %tmp41 + %tmp43 = zext i32 %tmp to i64 + %tmp44 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp43 + %tmp45 = load i8, i8* %tmp44, align 1 + %tmp46 = zext i8 %tmp45 to i32 + %tmp47 = shl nuw i32 %tmp46, 24 + %tmp48 = or i32 %tmp42, %tmp47 + ret i32 %tmp48 +} +; i8* p; // p is 2 byte aligned +; (i32) p[0] | ((i32) p[1] << 8) +define i32 @zext_load_i32_by_i8(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8: +; CHECK: ldrb w8, [x0] +; CHECK-NEXT: ldrb w9, [x0, #1] +; CHECK-NEXT: bfi w8, w9, #8, #8 +; CHECK-NEXT: mov w0, w8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp2 = load i8, i8* %tmp1, align 2 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + ret i32 %tmp8 +} + +; i8* p; // p is 2 byte aligned +; ((i32) p[0] << 8) | ((i32) p[1] << 16) +define i32 @zext_load_i32_by_i8_shl_8(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8_shl_8: +; CHECK: ldrb w8, [x0] +; CHECK-NEXT: ldrb w9, [x0, #1] +; CHECK-NEXT: lsl w0, w8, #8 +; CHECK-NEXT: bfi w0, w9, #16, #8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp2 = load i8, i8* %tmp1, align 2 + %tmp3 = zext i8 %tmp2 to i32 + %tmp30 = shl nuw nsw i32 %tmp3, 8 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 16 + %tmp8 = or i32 %tmp7, %tmp30 + ret i32 %tmp8 +} + +; i8* p; // p is 2 byte aligned +; ((i32) p[0] << 16) | ((i32) p[1] << 24) +define i32 @zext_load_i32_by_i8_shl_16(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8_shl_16: +; CHECK: ldrb w8, [x0] +; CHECK-NEXT: ldrb w9, [x0, #1] +; CHECK-NEXT: lsl w0, w8, #16 +; CHECK-NEXT: bfi w0, w9, #24, #8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp2 = load i8, i8* %tmp1, align 2 + %tmp3 = zext i8 %tmp2 to i32 + %tmp30 = shl nuw nsw i32 %tmp3, 16 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 24 + %tmp8 = or i32 %tmp7, %tmp30 + ret i32 %tmp8 +} +; i8* p; // p is 2 byte aligned +; (i32) p[1] | ((i32) p[0] << 8) +define i32 @zext_load_i32_by_i8_bswap(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8_bswap: +; CHECK: ldrb w8, [x0, #1] +; CHECK-NEXT: ldrb w9, [x0] +; CHECK-NEXT: bfi w8, w9, #8, #8 +; CHECK-NEXT: mov w0, w8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp2 = load i8, i8* %tmp1, align 1 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp5 = load i8, i8* %tmp4, align 2 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + ret i32 %tmp8 +} + +; i8* p; // p is 2 byte aligned +; ((i32) p[1] << 8) | ((i32) p[0] << 16) +define i32 @zext_load_i32_by_i8_bswap_shl_8(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8_bswap_shl_8: +; CHECK: ldrb w8, [x0, #1] +; CHECK-NEXT: ldrb w9, [x0] +; CHECK-NEXT: lsl w0, w8, #8 +; CHECK-NEXT: bfi w0, w9, #16, #8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp2 = load i8, i8* %tmp1, align 1 + %tmp3 = zext i8 %tmp2 to i32 + %tmp30 = shl nuw nsw i32 %tmp3, 8 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp5 = load i8, i8* %tmp4, align 2 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 16 + %tmp8 = or i32 %tmp7, %tmp30 + ret i32 %tmp8 +} + +; i8* p; // p is 2 byte aligned +; ((i32) p[1] << 16) | ((i32) p[0] << 24) +define i32 @zext_load_i32_by_i8_bswap_shl_16(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8_bswap_shl_16: +; CHECK: ldrb w8, [x0, #1] +; CHECK-NEXT: ldrb w9, [x0] +; CHECK-NEXT: lsl w0, w8, #16 +; CHECK-NEXT: bfi w0, w9, #24, #8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp2 = load i8, i8* %tmp1, align 1 + %tmp3 = zext i8 %tmp2 to i32 + %tmp30 = shl nuw nsw i32 %tmp3, 16 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp5 = load i8, i8* %tmp4, align 2 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 24 + %tmp8 = or i32 %tmp7, %tmp30 + ret i32 %tmp8 +} + +; i8* p; +; i16* p1.i16 = (i16*) p; +; (p1.i16[0] << 8) | ((i16) p[2]) +; +; This is essentialy a i16 load from p[1], but we don't fold the pattern now +; because in the original DAG we don't have p[1] address available +define i16 @load_i16_from_nonzero_offset(i8* %p) { +; CHECK-LABEL: load_i16_from_nonzero_offset: +; CHECK: ldrh w8, [x0] +; CHECK-NEXT: ldrb w0, [x0, #2] +; CHECK-NEXT: bfi w0, w8, #8, #24 +; CHECK-NEXT: ret + + %p1.i16 = bitcast i8* %p to i16* + %p2.i8 = getelementptr i8, i8* %p, i64 2 + %v1 = load i16, i16* %p1.i16 + %v2.i8 = load i8, i8* %p2.i8 + %v2 = zext i8 %v2.i8 to i16 + %v1.shl = shl i16 %v1, 8 + %res = or i16 %v1.shl, %v2 + ret i16 %res +} diff --git a/test/CodeGen/AArch64/load-combine.ll b/test/CodeGen/AArch64/load-combine.ll new file mode 100644 index 0000000000000..f0ed40357f122 --- /dev/null +++ b/test/CodeGen/AArch64/load-combine.ll @@ -0,0 +1,548 @@ +; RUN: llc < %s -mtriple=arm64-unknown | FileCheck %s + +; i8* p; // p is 1 byte aligned +; (i32) p[0] | ((i32) p[1] << 8) | ((i32) p[2] << 16) | ((i32) p[3] << 24) +define i32 @load_i32_by_i8_unaligned(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_unaligned: +; CHECK: ldr w0, [x0] +; CHECK-NEXT: ret + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp2 = load i8, i8* %tmp, align 1 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 2 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 16 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 3 + %tmp15 = load i8, i8* %tmp14, align 1 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = shl nuw nsw i32 %tmp16, 24 + %tmp18 = or i32 %tmp13, %tmp17 + ret i32 %tmp18 +} + +; i8* p; // p is 4 byte aligned +; (i32) p[0] | ((i32) p[1] << 8) | ((i32) p[2] << 16) | ((i32) p[3] << 24) +define i32 @load_i32_by_i8_aligned(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_aligned: +; CHECK: ldr w0, [x0] +; CHECK-NEXT: ret + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp2 = load i8, i8* %tmp, align 4 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 2 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 16 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 3 + %tmp15 = load i8, i8* %tmp14, align 1 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = shl nuw nsw i32 %tmp16, 24 + %tmp18 = or i32 %tmp13, %tmp17 + ret i32 %tmp18 +} + +; i8* p; // p is 4 byte aligned +; ((i32) p[0] << 24) | ((i32) p[1] << 16) | ((i32) p[2] << 8) | (i32) p[3] +define i32 @load_i32_by_i8_bswap(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_bswap: +; CHECK: ldr w8, [x0] +; CHECK-NEXT: rev w0, w8 +; CHECK-NEXT: ret + %tmp = bitcast i32* %arg to i8* + %tmp1 = load i8, i8* %tmp, align 4 + %tmp2 = zext i8 %tmp1 to i32 + %tmp3 = shl nuw nsw i32 %tmp2, 24 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 16 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 2 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 8 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 3 + %tmp15 = load i8, i8* %tmp14, align 1 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = or i32 %tmp13, %tmp16 + ret i32 %tmp17 +} + +; i8* p; // p is 8 byte aligned +; (i64) p[0] | ((i64) p[1] << 8) | ((i64) p[2] << 16) | ((i64) p[3] << 24) | ((i64) p[4] << 32) | ((i64) p[5] << 40) | ((i64) p[6] << 48) | ((i64) p[7] << 56) +define i64 @load_i64_by_i8(i64* %arg) { +; CHECK-LABEL: load_i64_by_i8: +; CHECK: ldr x0, [x0] +; CHECK-NEXT: ret + %tmp = bitcast i64* %arg to i8* + %tmp1 = load i8, i8* %tmp, align 8 + %tmp2 = zext i8 %tmp1 to i64 + %tmp3 = getelementptr inbounds i8, i8* %tmp, i64 1 + %tmp4 = load i8, i8* %tmp3, align 1 + %tmp5 = zext i8 %tmp4 to i64 + %tmp6 = shl nuw nsw i64 %tmp5, 8 + %tmp7 = or i64 %tmp6, %tmp2 + %tmp8 = getelementptr inbounds i8, i8* %tmp, i64 2 + %tmp9 = load i8, i8* %tmp8, align 1 + %tmp10 = zext i8 %tmp9 to i64 + %tmp11 = shl nuw nsw i64 %tmp10, 16 + %tmp12 = or i64 %tmp7, %tmp11 + %tmp13 = getelementptr inbounds i8, i8* %tmp, i64 3 + %tmp14 = load i8, i8* %tmp13, align 1 + %tmp15 = zext i8 %tmp14 to i64 + %tmp16 = shl nuw nsw i64 %tmp15, 24 + %tmp17 = or i64 %tmp12, %tmp16 + %tmp18 = getelementptr inbounds i8, i8* %tmp, i64 4 + %tmp19 = load i8, i8* %tmp18, align 1 + %tmp20 = zext i8 %tmp19 to i64 + %tmp21 = shl nuw nsw i64 %tmp20, 32 + %tmp22 = or i64 %tmp17, %tmp21 + %tmp23 = getelementptr inbounds i8, i8* %tmp, i64 5 + %tmp24 = load i8, i8* %tmp23, align 1 + %tmp25 = zext i8 %tmp24 to i64 + %tmp26 = shl nuw nsw i64 %tmp25, 40 + %tmp27 = or i64 %tmp22, %tmp26 + %tmp28 = getelementptr inbounds i8, i8* %tmp, i64 6 + %tmp29 = load i8, i8* %tmp28, align 1 + %tmp30 = zext i8 %tmp29 to i64 + %tmp31 = shl nuw nsw i64 %tmp30, 48 + %tmp32 = or i64 %tmp27, %tmp31 + %tmp33 = getelementptr inbounds i8, i8* %tmp, i64 7 + %tmp34 = load i8, i8* %tmp33, align 1 + %tmp35 = zext i8 %tmp34 to i64 + %tmp36 = shl nuw i64 %tmp35, 56 + %tmp37 = or i64 %tmp32, %tmp36 + ret i64 %tmp37 +} + +; i8* p; // p is 8 byte aligned +; ((i64) p[0] << 56) | ((i64) p[1] << 48) | ((i64) p[2] << 40) | ((i64) p[3] << 32) | ((i64) p[4] << 24) | ((i64) p[5] << 16) | ((i64) p[6] << 8) | (i64) p[7] +define i64 @load_i64_by_i8_bswap(i64* %arg) { +; CHECK-LABEL: load_i64_by_i8_bswap: +; CHECK: ldr x8, [x0] +; CHECK-NEXT: rev x0, x8 +; CHECK-NEXT: ret + %tmp = bitcast i64* %arg to i8* + %tmp1 = load i8, i8* %tmp, align 8 + %tmp2 = zext i8 %tmp1 to i64 + %tmp3 = shl nuw i64 %tmp2, 56 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i64 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i64 + %tmp7 = shl nuw nsw i64 %tmp6, 48 + %tmp8 = or i64 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i64 2 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i64 + %tmp12 = shl nuw nsw i64 %tmp11, 40 + %tmp13 = or i64 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i64 3 + %tmp15 = load i8, i8* %tmp14, align 1 + %tmp16 = zext i8 %tmp15 to i64 + %tmp17 = shl nuw nsw i64 %tmp16, 32 + %tmp18 = or i64 %tmp13, %tmp17 + %tmp19 = getelementptr inbounds i8, i8* %tmp, i64 4 + %tmp20 = load i8, i8* %tmp19, align 1 + %tmp21 = zext i8 %tmp20 to i64 + %tmp22 = shl nuw nsw i64 %tmp21, 24 + %tmp23 = or i64 %tmp18, %tmp22 + %tmp24 = getelementptr inbounds i8, i8* %tmp, i64 5 + %tmp25 = load i8, i8* %tmp24, align 1 + %tmp26 = zext i8 %tmp25 to i64 + %tmp27 = shl nuw nsw i64 %tmp26, 16 + %tmp28 = or i64 %tmp23, %tmp27 + %tmp29 = getelementptr inbounds i8, i8* %tmp, i64 6 + %tmp30 = load i8, i8* %tmp29, align 1 + %tmp31 = zext i8 %tmp30 to i64 + %tmp32 = shl nuw nsw i64 %tmp31, 8 + %tmp33 = or i64 %tmp28, %tmp32 + %tmp34 = getelementptr inbounds i8, i8* %tmp, i64 7 + %tmp35 = load i8, i8* %tmp34, align 1 + %tmp36 = zext i8 %tmp35 to i64 + %tmp37 = or i64 %tmp33, %tmp36 + ret i64 %tmp37 +} + +; i8* p; // p[1] is 4 byte aligned +; (i32) p[1] | ((i32) p[2] << 8) | ((i32) p[3] << 16) | ((i32) p[4] << 24) +define i32 @load_i32_by_i8_nonzero_offset(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_nonzero_offset: +; CHECK: ldur w0, [x0, #1] +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp2 = load i8, i8* %tmp1, align 4 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 2 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 3 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 16 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 4 + %tmp15 = load i8, i8* %tmp14, align 1 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = shl nuw nsw i32 %tmp16, 24 + %tmp18 = or i32 %tmp13, %tmp17 + ret i32 %tmp18 +} + +; i8* p; // p[-4] is 4 byte aligned +; (i32) p[-4] | ((i32) p[-3] << 8) | ((i32) p[-2] << 16) | ((i32) p[-1] << 24) +define i32 @load_i32_by_i8_neg_offset(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_neg_offset: +; CHECK: ldur w0, [x0, #-4] +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 -4 + %tmp2 = load i8, i8* %tmp1, align 4 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 -3 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 -2 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 16 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 -1 + %tmp15 = load i8, i8* %tmp14, align 1 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = shl nuw nsw i32 %tmp16, 24 + %tmp18 = or i32 %tmp13, %tmp17 + ret i32 %tmp18 +} + +; i8* p; // p[1] is 4 byte aligned +; (i32) p[4] | ((i32) p[3] << 8) | ((i32) p[2] << 16) | ((i32) p[1] << 24) +define i32 @load_i32_by_i8_nonzero_offset_bswap(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_nonzero_offset_bswap: +; CHECK: ldur w8, [x0, #1] +; CHECK-NEXT: rev w0, w8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 4 + %tmp2 = load i8, i8* %tmp1, align 1 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 3 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 2 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 16 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp15 = load i8, i8* %tmp14, align 4 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = shl nuw nsw i32 %tmp16, 24 + %tmp18 = or i32 %tmp13, %tmp17 + ret i32 %tmp18 +} + +; i8* p; // p[-4] is 4 byte aligned +; (i32) p[-1] | ((i32) p[-2] << 8) | ((i32) p[-3] << 16) | ((i32) p[-4] << 24) +define i32 @load_i32_by_i8_neg_offset_bswap(i32* %arg) { +; CHECK-LABEL: load_i32_by_i8_neg_offset_bswap: +; CHECK: ldur w8, [x0, #-4] +; CHECK-NEXT: rev w0, w8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 -1 + %tmp2 = load i8, i8* %tmp1, align 1 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 -2 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 -3 + %tmp10 = load i8, i8* %tmp9, align 1 + %tmp11 = zext i8 %tmp10 to i32 + %tmp12 = shl nuw nsw i32 %tmp11, 16 + %tmp13 = or i32 %tmp8, %tmp12 + %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 -4 + %tmp15 = load i8, i8* %tmp14, align 4 + %tmp16 = zext i8 %tmp15 to i32 + %tmp17 = shl nuw nsw i32 %tmp16, 24 + %tmp18 = or i32 %tmp13, %tmp17 + ret i32 %tmp18 +} + +declare i16 @llvm.bswap.i16(i16) + +; i16* p; // p is 4 byte aligned +; (i32) bswap(p[1]) | (i32) bswap(p[0] << 16) +define i32 @load_i32_by_bswap_i16(i32* %arg) { +; CHECK-LABEL: load_i32_by_bswap_i16: +; CHECK: ldr w8, [x0] +; CHECK-NEXT: rev w0, w8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i16* + %tmp1 = load i16, i16* %tmp, align 4 + %tmp11 = call i16 @llvm.bswap.i16(i16 %tmp1) + %tmp2 = zext i16 %tmp11 to i32 + %tmp3 = getelementptr inbounds i16, i16* %tmp, i32 1 + %tmp4 = load i16, i16* %tmp3, align 1 + %tmp41 = call i16 @llvm.bswap.i16(i16 %tmp4) + %tmp5 = zext i16 %tmp41 to i32 + %tmp6 = shl nuw nsw i32 %tmp2, 16 + %tmp7 = or i32 %tmp6, %tmp5 + ret i32 %tmp7 +} + +; i16* p; // p is 4 byte aligned +; (i32) p[0] | (sext(p[1] << 16) to i32) +define i32 @load_i32_by_sext_i16(i32* %arg) { +; CHECK-LABEL: load_i32_by_sext_i16: +; CHECK: ldr w0, [x0] +; CHECK-NEXT: ret + %tmp = bitcast i32* %arg to i16* + %tmp1 = load i16, i16* %tmp, align 4 + %tmp2 = zext i16 %tmp1 to i32 + %tmp3 = getelementptr inbounds i16, i16* %tmp, i32 1 + %tmp4 = load i16, i16* %tmp3, align 1 + %tmp5 = sext i16 %tmp4 to i32 + %tmp6 = shl nuw nsw i32 %tmp5, 16 + %tmp7 = or i32 %tmp6, %tmp2 + ret i32 %tmp7 +} + +; i8* arg; i32 i; +; p = arg + 12; +; (i32) p[i] | ((i32) p[i + 1] << 8) | ((i32) p[i + 2] << 16) | ((i32) p[i + 3] << 24) +define i32 @load_i32_by_i8_base_offset_index(i8* %arg, i32 %i) { +; CHECK-LABEL: load_i32_by_i8_base_offset_index: +; CHECK: add x8, x0, w1, uxtw +; CHECK-NEXT: ldr w0, [x8, #12] +; CHECK-NEXT: ret + %tmp = add nuw nsw i32 %i, 3 + %tmp2 = add nuw nsw i32 %i, 2 + %tmp3 = add nuw nsw i32 %i, 1 + %tmp4 = getelementptr inbounds i8, i8* %arg, i64 12 + %tmp5 = zext i32 %i to i64 + %tmp6 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp5 + %tmp7 = load i8, i8* %tmp6, align 4 + %tmp8 = zext i8 %tmp7 to i32 + %tmp9 = zext i32 %tmp3 to i64 + %tmp10 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp9 + %tmp11 = load i8, i8* %tmp10, align 1 + %tmp12 = zext i8 %tmp11 to i32 + %tmp13 = shl nuw nsw i32 %tmp12, 8 + %tmp14 = or i32 %tmp13, %tmp8 + %tmp15 = zext i32 %tmp2 to i64 + %tmp16 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp15 + %tmp17 = load i8, i8* %tmp16, align 1 + %tmp18 = zext i8 %tmp17 to i32 + %tmp19 = shl nuw nsw i32 %tmp18, 16 + %tmp20 = or i32 %tmp14, %tmp19 + %tmp21 = zext i32 %tmp to i64 + %tmp22 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp21 + %tmp23 = load i8, i8* %tmp22, align 1 + %tmp24 = zext i8 %tmp23 to i32 + %tmp25 = shl nuw i32 %tmp24, 24 + %tmp26 = or i32 %tmp20, %tmp25 + ret i32 %tmp26 +} + +; i8* arg; i32 i; +; p = arg + 12; +; (i32) p[i + 1] | ((i32) p[i + 2] << 8) | ((i32) p[i + 3] << 16) | ((i32) p[i + 4] << 24) +define i32 @load_i32_by_i8_base_offset_index_2(i8* %arg, i32 %i) { +; CHECK-LABEL: load_i32_by_i8_base_offset_index_2: +; CHECK: add x8, x0, w1, uxtw +; CHECK-NEXT: ldur w0, [x8, #13] +; CHECK-NEXT: ret + %tmp = add nuw nsw i32 %i, 4 + %tmp2 = add nuw nsw i32 %i, 3 + %tmp3 = add nuw nsw i32 %i, 2 + %tmp4 = getelementptr inbounds i8, i8* %arg, i64 12 + %tmp5 = add nuw nsw i32 %i, 1 + %tmp27 = zext i32 %tmp5 to i64 + %tmp28 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp27 + %tmp29 = load i8, i8* %tmp28, align 4 + %tmp30 = zext i8 %tmp29 to i32 + %tmp31 = zext i32 %tmp3 to i64 + %tmp32 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp31 + %tmp33 = load i8, i8* %tmp32, align 1 + %tmp34 = zext i8 %tmp33 to i32 + %tmp35 = shl nuw nsw i32 %tmp34, 8 + %tmp36 = or i32 %tmp35, %tmp30 + %tmp37 = zext i32 %tmp2 to i64 + %tmp38 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp37 + %tmp39 = load i8, i8* %tmp38, align 1 + %tmp40 = zext i8 %tmp39 to i32 + %tmp41 = shl nuw nsw i32 %tmp40, 16 + %tmp42 = or i32 %tmp36, %tmp41 + %tmp43 = zext i32 %tmp to i64 + %tmp44 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp43 + %tmp45 = load i8, i8* %tmp44, align 1 + %tmp46 = zext i8 %tmp45 to i32 + %tmp47 = shl nuw i32 %tmp46, 24 + %tmp48 = or i32 %tmp42, %tmp47 + ret i32 %tmp48 +} + +; i8* p; // p is 2 byte aligned +; (i32) p[0] | ((i32) p[1] << 8) +define i32 @zext_load_i32_by_i8(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8: +; CHECK: ldrb w8, [x0] +; CHECK-NEXT: ldrb w9, [x0, #1] +; CHECK-NEXT: bfi w8, w9, #8, #8 +; CHECK-NEXT: mov w0, w8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp2 = load i8, i8* %tmp1, align 2 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + ret i32 %tmp8 +} + +; i8* p; // p is 2 byte aligned +; ((i32) p[0] << 8) | ((i32) p[1] << 16) +define i32 @zext_load_i32_by_i8_shl_8(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8_shl_8: +; CHECK: ldrb w8, [x0] +; CHECK-NEXT: ldrb w9, [x0, #1] +; CHECK-NEXT: lsl w0, w8, #8 +; CHECK-NEXT: bfi w0, w9, #16, #8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp2 = load i8, i8* %tmp1, align 2 + %tmp3 = zext i8 %tmp2 to i32 + %tmp30 = shl nuw nsw i32 %tmp3, 8 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 16 + %tmp8 = or i32 %tmp7, %tmp30 + ret i32 %tmp8 +} + +; i8* p; // p is 2 byte aligned +; ((i32) p[0] << 16) | ((i32) p[1] << 24) +define i32 @zext_load_i32_by_i8_shl_16(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8_shl_16: +; CHECK: ldrb w8, [x0] +; CHECK-NEXT: ldrb w9, [x0, #1] +; CHECK-NEXT: lsl w0, w8, #16 +; CHECK-NEXT: bfi w0, w9, #24, #8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp2 = load i8, i8* %tmp1, align 2 + %tmp3 = zext i8 %tmp2 to i32 + %tmp30 = shl nuw nsw i32 %tmp3, 16 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp5 = load i8, i8* %tmp4, align 1 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 24 + %tmp8 = or i32 %tmp7, %tmp30 + ret i32 %tmp8 +} +; i8* p; // p is 2 byte aligned +; (i32) p[1] | ((i32) p[0] << 8) +define i32 @zext_load_i32_by_i8_bswap(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8_bswap: +; CHECK: ldrb w8, [x0, #1] +; CHECK-NEXT: ldrb w9, [x0] +; CHECK-NEXT: bfi w8, w9, #8, #8 +; CHECK-NEXT: mov w0, w8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp2 = load i8, i8* %tmp1, align 1 + %tmp3 = zext i8 %tmp2 to i32 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp5 = load i8, i8* %tmp4, align 2 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 8 + %tmp8 = or i32 %tmp7, %tmp3 + ret i32 %tmp8 +} + +; i8* p; // p is 2 byte aligned +; ((i32) p[1] << 8) | ((i32) p[0] << 16) +define i32 @zext_load_i32_by_i8_bswap_shl_8(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8_bswap_shl_8: +; CHECK: ldrb w8, [x0, #1] +; CHECK-NEXT: ldrb w9, [x0] +; CHECK-NEXT: lsl w0, w8, #8 +; CHECK-NEXT: bfi w0, w9, #16, #8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp2 = load i8, i8* %tmp1, align 1 + %tmp3 = zext i8 %tmp2 to i32 + %tmp30 = shl nuw nsw i32 %tmp3, 8 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp5 = load i8, i8* %tmp4, align 2 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 16 + %tmp8 = or i32 %tmp7, %tmp30 + ret i32 %tmp8 +} + +; i8* p; // p is 2 byte aligned +; ((i32) p[1] << 16) | ((i32) p[0] << 24) +define i32 @zext_load_i32_by_i8_bswap_shl_16(i32* %arg) { +; CHECK-LABEL: zext_load_i32_by_i8_bswap_shl_16: +; CHECK: ldrb w8, [x0, #1] +; CHECK-NEXT: ldrb w9, [x0] +; CHECK-NEXT: lsl w0, w8, #16 +; CHECK-NEXT: bfi w0, w9, #24, #8 +; CHECK-NEXT: ret + + %tmp = bitcast i32* %arg to i8* + %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1 + %tmp2 = load i8, i8* %tmp1, align 1 + %tmp3 = zext i8 %tmp2 to i32 + %tmp30 = shl nuw nsw i32 %tmp3, 16 + %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 0 + %tmp5 = load i8, i8* %tmp4, align 2 + %tmp6 = zext i8 %tmp5 to i32 + %tmp7 = shl nuw nsw i32 %tmp6, 24 + %tmp8 = or i32 %tmp7, %tmp30 + ret i32 %tmp8 +} diff --git a/test/CodeGen/AArch64/machine-combiner-madd.ll b/test/CodeGen/AArch64/machine-combiner-madd.ll index ea3113789461b..4efe4e9cfb018 100644 --- a/test/CodeGen/AArch64/machine-combiner-madd.ll +++ b/test/CodeGen/AArch64/machine-combiner-madd.ll @@ -6,7 +6,7 @@ ; RUN: llc -mtriple=aarch64-linux-gnu -mcpu=exynos-m1 < %s | FileCheck %s ; RUN: llc -mtriple=aarch64-linux-gnu -mcpu=exynos-m2 < %s | FileCheck %s ; RUN: llc -mtriple=aarch64-linux-gnu -mcpu=kryo < %s | FileCheck %s -; RUN: llc -mtriple=aarch64-linux-gnu -mcpu=vulcan < %s | FileCheck %s +; RUN: llc -mtriple=aarch64-linux-gnu -mcpu=thunderx2t99 < %s | FileCheck %s ; Make sure that inst-combine fuses the multiply add in the addressing mode of ; the load. diff --git a/test/CodeGen/AArch64/machine-copy-remove.mir b/test/CodeGen/AArch64/machine-copy-remove.mir new file mode 100644 index 0000000000000..6f2d3a3009b02 --- /dev/null +++ b/test/CodeGen/AArch64/machine-copy-remove.mir @@ -0,0 +1,672 @@ +# RUN: llc -mtriple=aarch64--linux-gnu -run-pass=aarch64-copyelim %s -verify-machineinstrs -o - | FileCheck %s +--- +# Check that bb.0 COPY is seen through to allow the bb.1 COPY of XZR to be removed. +# CHECK-LABEL: name: test1 +# CHECK-NOT: COPY %xzr +name: test1 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: %x0, %x1 + + %x0 = COPY %x1 + CBNZX %x1, %bb.2 + + bb.1: + successors: %bb.3 + + %x0 = COPY %xzr + B %bb.3 + + bb.2: + successors: %bb.3 + liveins: %x1 + + %x0 = LDRXui %x1, 0 + + bb.3: + liveins: %x0 + + RET_ReallyLR implicit %x0 + +... +# Similar to test1, but with reversed COPY. +# CHECK-LABEL: name: test2 +# CHECK-NOT: COPY %xzr +name: test2 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: %x0, %x1 + + %x1 = COPY %x0 + CBNZX %x1, %bb.2 + + bb.1: + successors: %bb.3 + + %x0 = COPY %xzr + B %bb.3 + + bb.2: + successors: %bb.3 + liveins: %x1 + + %x0 = LDRXui %x1, 0 + + bb.3: + liveins: %x0 + + RET_ReallyLR implicit %x0 + +... +# Similar to test1, but with a clobber that prevents removal of the XZR COPY. +# CHECK-LABEL: name: test3 +# CHECK: COPY %xzr +name: test3 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: %x0, %x1, %x2 + + %x0 = COPY %x1 + %x1 = LDRXui %x1, 0 + CBNZX %x1, %bb.2 + + bb.1: + successors: %bb.3 + + %x0 = COPY %xzr + B %bb.3 + + bb.2: + successors: %bb.3 + liveins: %x1 + + %x0 = LDRXui %x1, 0 + + bb.3: + liveins: %x0 + + RET_ReallyLR implicit %x0 + +... +# Similar to test2, but with a clobber that prevents removal of the XZR COPY. +# CHECK-LABEL: name: test4 +# CHECK: COPY %xzr +name: test4 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: %x0, %x1, %x2 + + %x1 = COPY %x0 + %x1 = LDRXui %x1, 0 + CBNZX %x1, %bb.2 + + bb.1: + successors: %bb.3 + + %x0 = COPY %xzr + B %bb.3 + + bb.2: + successors: %bb.3 + liveins: %x1 + + %x0 = LDRXui %x1, 0 + + bb.3: + liveins: %x0 + + RET_ReallyLR implicit %x0 + +... +# Similar to test2, but with a clobber that prevents removal of the XZR COPY. +# CHECK-LABEL: name: test5 +# CHECK: COPY %xzr +name: test5 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: %x0, %x1, %x2 + + %x1 = COPY %x0 + %x0 = LDRXui %x1, 0 + CBNZX %x1, %bb.2 + + bb.1: + successors: %bb.3 + + %x0 = COPY %xzr + B %bb.3 + + bb.2: + successors: %bb.3 + liveins: %x1 + + %x0 = LDRXui %x1, 0 + + bb.3: + liveins: %x0 + + RET_ReallyLR implicit %x0 + +... +# Similar to test1, but with two levels of COPYs. +# CHECK-LABEL: name: test6 +# CHECK-NOT: COPY %xzr +name: test6 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: %x0, %x1, %x2 + + %x2 = COPY %x0 + %x1 = COPY %x2 + CBNZX %x1, %bb.2 + + bb.1: + successors: %bb.3 + + %x0 = COPY %xzr + B %bb.3 + + bb.2: + successors: %bb.3 + liveins: %x1 + + %x0 = LDRXui %x1, 0 + + bb.3: + liveins: %x0 + + RET_ReallyLR implicit %x0 + +... +# Similar to test1, but with two levels of COPYs and a clobber preventing COPY of XZR removal. +# CHECK-LABEL: name: test7 +# CHECK: COPY %xzr +name: test7 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: %x0, %x1, %x2 + + %x2 = COPY %x0 + %x0 = LDRXui %x1, 0 + %x1 = COPY %x2 + CBNZX %x1, %bb.2 + + bb.1: + successors: %bb.3 + + %x0 = COPY %xzr + B %bb.3 + + bb.2: + successors: %bb.3 + liveins: %x1 + + %x0 = LDRXui %x1, 0 + + bb.3: + liveins: %x0 + + RET_ReallyLR implicit %x0 + +... +# Check that the TargetRegs vector clobber update loop in +# AArch64RedundantCopyElimination::optimizeCopy works correctly. +# CHECK-LABEL: name: test8 +# CHECK: x0 = COPY %xzr +# CHECK: x1 = COPY %xzr +name: test8 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: %x0, %x1 + + %x1 = COPY %x0 + CBNZX %x1, %bb.2 + + bb.1: + successors: %bb.3 + liveins: %x0, %x2 + + %x0, %x1 = LDPXi %x2, 0 + %x0 = COPY %xzr + %x1 = COPY %xzr + B %bb.3 + + bb.2: + successors: %bb.3 + liveins: %x1 + + %x0 = LDRXui %x1, 0 + + bb.3: + liveins: %x0 + + RET_ReallyLR implicit %x0 + +... +# Check that copy isn't removed from a block with multiple predecessors. +# CHECK-LABEL: name: test9 +# CHECK: x0 = COPY %xzr +# CHECK-NEXT: B %bb.3 +name: test9 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: %x0, %x1 + + CBNZX %x0, %bb.2 + + bb.1: + successors: %bb.3 + liveins: %x0, %x2 + + %x0 = COPY %xzr + B %bb.3 + + bb.2: + successors: %bb.1, %bb.3 + liveins: %x1 + + %x0 = LDRXui %x1, 0 + + CBNZX %x1, %bb.1 + + bb.3: + liveins: %x0 + + RET_ReallyLR implicit %x0 + +... +# Eliminate redundant MOVi32imm 7 in bb.1 +# Note: 32-bit compare/32-bit move imm +# Kill marker should be removed from compare. +# CHECK-LABEL: name: test10 +# CHECK: SUBSWri %w0, 7, 0, implicit-def %nzcv +# CHECK: bb.1: +# CHECK-NOT: MOVi32imm +name: test10 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %w0, %x1 + + dead %wzr = SUBSWri killed %w0, 7, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w0 = MOVi32imm 7 + STRWui killed %w0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Eliminate redundant MOVi32imm 7 in bb.1 +# Note: 64-bit compare/32-bit move imm w/implicit def +# Kill marker should be removed from compare. +# CHECK-LABEL: name: test11 +# CHECK: SUBSXri %x0, 7, 0, implicit-def %nzcv +# CHECK: bb.1: +# CHECK-NOT: MOVi32imm +name: test11 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %x0, %x1 + + dead %xzr = SUBSXri killed %x0, 7, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w0 = MOVi32imm 7, implicit-def %x0 + STRXui killed %x0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Eliminate redundant MOVi32imm 7 in bb.1 +# Note: 64-bit compare/32-bit move imm +# Kill marker should be removed from compare. +# CHECK-LABEL: name: test12 +# CHECK: SUBSXri %x0, 7, 0, implicit-def %nzcv +# CHECK: bb.1: +# CHECK-NOT: MOVi32imm +name: test12 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %x0, %x1 + + dead %xzr = SUBSXri killed %x0, 7, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w0 = MOVi32imm 7 + STRWui killed %w0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Don't eliminate MOVi32imm 7 in bb.1 as we don't necessarily know the upper 32-bits. +# Note: 32-bit compare/32-bit move imm w/implicit def +# Kill marker should remain on compare. +# CHECK-LABEL: name: test13 +# CHECK: SUBSWri killed %w0, 7, 0, implicit-def %nzcv +# CHECK: bb.1: +# CHECK: MOVi32imm +name: test13 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %w0, %x1 + + dead %wzr = SUBSWri killed %w0, 7, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w0 = MOVi32imm 7, implicit-def %x0 + STRXui killed %x0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# We can't eliminate the MOVi32imm because of the clobbering LDRWui. +# CHECK-LABEL: name: test14 +# CHECK: bb.1: +# CHECK: MOVi32imm +name: test14 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %w0, %x1, %x2 + + dead %wzr = SUBSWri killed %w0, 7, 0, implicit-def %nzcv + %w0 = LDRWui %x1, 0 + STRWui killed %w0, killed %x2, 0 + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w0 = MOVi32imm 7 + STRWui killed %w0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# We can't eliminate the MOVi32imm because of the clobbering LDRWui. +# CHECK-LABEL: name: test15 +# CHECK: bb.1: +# CHECK: MOVi32imm +name: test15 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %w0, %x1, %x2 + + dead %wzr = SUBSWri killed %w0, 7, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1, %x2 + + %w0 = LDRWui %x1, 0 + STRWui killed %w0, killed %x2, 0 + %w0 = MOVi32imm 7 + STRWui killed %w0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Check that bb.0 COPY is seen through to allow the bb.1 MOVi32imm to be removed. +# CHECK-LABEL: name: test16 +# CHECK: bb.1: +# CHECK-NOT: MOVi32imm +name: test16 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %w0, %x1 + + dead %wzr = SUBSWri %w0, 7, 0, implicit-def %nzcv + %w2 = COPY %w0 + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w2 = MOVi32imm 7 + STRWui killed %w2, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Check that bb.1 MOVi32imm is not removed due to self clobbering compare. +# CHECK-LABEL: name: test17 +# CHECK: bb.1: +# CHECK: MOVi32imm +name: test17 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %w0, %x1 + + dead %w0 = SUBSWri killed %w0, 7, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w0 = MOVi32imm 7 + STRWui killed %w0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Make sure the MOVi64imm is not removed. In one version of this patch the +# MOVi64imm immediate was truncated to 32 bits and incorrectly matched because +# the low 32 bits of 4252017623040 are all zero. +# CHECK-LABEL: name: test18 +# CHECK: bb.1: +# CHECK: MOVi64imm +name: test18 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %x0, %x1 + + CBNZX killed %x0, %bb.2 + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %x0 = MOVi64imm 4252017623040 + STRXui killed %x0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Eliminate redundant MOVi32imm -1 in bb.1 +# Note: 32-bit compare/32-bit move imm +# Kill marker should be removed from compare. +# CHECK-LABEL: name: test19 +# CHECK: ADDSWri %w0, 1, 0, implicit-def %nzcv +# CHECK: bb.1: +# CHECK-NOT: MOVi32imm +name: test19 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %w0, %x1 + + dead %wzr = ADDSWri killed %w0, 1, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w0 = MOVi32imm -1 + STRWui killed %w0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Eliminate redundant MOVi64imm -1 in bb.1 +# Note: 64-bit compare/64-bit move imm +# Kill marker should be removed from compare. +# CHECK-LABEL: name: test20 +# CHECK: ADDSXri %x0, 1, 0, implicit-def %nzcv +# CHECK: bb.1: +# CHECK-NOT: MOVi64imm +name: test20 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1, %bb.2 + liveins: %x0, %x1 + + dead %xzr = ADDSXri killed %x0, 1, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %x0 = MOVi64imm -1 + STRXui killed %x0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Eliminate redundant MOVi32imm -1 in bb.1 +# Note: 64-bit compare/32-bit move imm +# Kill marker should be removed from compare. +# CHECK-LABEL: name: test21 +# CHECK: ADDSXri %x0, 1, 0, implicit-def %nzcv +# CHECK: bb.1: +# CHECK-NOT: MOVi32imm +name: test21 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %x0, %x1 + + dead %xzr = ADDSXri killed %x0, 1, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w0 = MOVi32imm -1 + STRWui killed %w0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Don't eliminate MOVi64imm -1 in bb.1 as we don't necessarily know the upper 32-bits. +# Note: 32-bit compare/64-bit move imm +# CHECK-LABEL: name: test22 +# CHECK: bb.1: +# CHECK: MOVi64imm +name: test22 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %w0, %x1 + + dead %wzr = ADDSWri killed %w0, 1, 0, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %x0 = MOVi64imm -1 + STRXui killed %x0, killed %x1, 0 + + bb.2: + RET_ReallyLR +... +# Eliminate redundant MOVi32imm 4096 in bb.1 when the compare has a shifted immediate. +# CHECK-LABEL: name: test23 +# CHECK: bb.1: +# CHECK-NOT: MOVi32imm +name: test23 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1, %bb.2 + liveins: %w0, %x1 + + dead %wzr = SUBSWri killed %w0, 1, 12, implicit-def %nzcv + Bcc 1, %bb.2, implicit killed %nzcv + B %bb.1 + + bb.1: + successors: %bb.2 + liveins: %x1 + + %w0 = MOVi32imm 4096 + STRWui killed %w0, killed %x1, 0 + + bb.2: + RET_ReallyLR diff --git a/test/CodeGen/AArch64/machine-outliner.ll b/test/CodeGen/AArch64/machine-outliner.ll new file mode 100644 index 0000000000000..b5094fe47508b --- /dev/null +++ b/test/CodeGen/AArch64/machine-outliner.ll @@ -0,0 +1,43 @@ +; RUN: llc -enable-machine-outliner -mtriple=aarch64-apple-darwin < %s | FileCheck %s + +define void @cat() #0 { +; CHECK-LABEL: _cat: +; CHECK: b l_OUTLINED_FUNCTION_0 +; CHECK-NOT: ret + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + %4 = alloca i32, align 4 + store i32 0, i32* %1, align 4 + store i32 1, i32* %2, align 4 + store i32 2, i32* %3, align 4 + store i32 3, i32* %4, align 4 + ret void +} + +define void @dog() #0 { +; CHECK-LABEL: _dog: +; CHECK: b l_OUTLINED_FUNCTION_0 +; CHECK-NOT: ret + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + %4 = alloca i32, align 4 + store i32 0, i32* %1, align 4 + store i32 1, i32* %2, align 4 + store i32 2, i32* %3, align 4 + store i32 3, i32* %4, align 4 + ret void +} + +; CHECK-LABEL: l_OUTLINED_FUNCTION_0: +; CHECK: orr w8, wzr, #0x1 +; CHECK-NEXT: stp w8, wzr, [sp, #8] +; CHECK-NEXT: orr w8, wzr, #0x2 +; CHECK-NEXT: str w8, [sp, #4] +; CHECK-NEXT: orr w8, wzr, #0x3 +; CHECK-NEXT: str w8, [sp], #16 +; CHECK-NEXT: ret + + +attributes #0 = { noredzone nounwind ssp uwtable "no-frame-pointer-elim"="false" "target-cpu"="cyclone" } diff --git a/test/CodeGen/AArch64/mature-mc-support.ll b/test/CodeGen/AArch64/mature-mc-support.ll index 276c54d2cc4e4..dbc027143f994 100644 --- a/test/CodeGen/AArch64/mature-mc-support.ll +++ b/test/CodeGen/AArch64/mature-mc-support.ll @@ -9,4 +9,4 @@ module asm " .this_directive_is_very_unlikely_to_exist" -; CHECK: LLVM ERROR: Error parsing inline asm +; CHECK: error: unknown directive diff --git a/test/CodeGen/AArch64/merge-store.ll b/test/CodeGen/AArch64/merge-store.ll index 1d0196ad521d6..1d26e4a42b176 100644 --- a/test/CodeGen/AArch64/merge-store.ll +++ b/test/CodeGen/AArch64/merge-store.ll @@ -4,8 +4,7 @@ @g0 = external global <3 x float>, align 16 @g1 = external global <3 x float>, align 4 -; CHECK: ldr s[[R0:[0-9]+]], {{\[}}[[R1:x[0-9]+]]{{\]}}, #4 -; CHECK: ld1{{\.?s?}} { v[[R0]]{{\.?s?}} }[1], {{\[}}[[R1]]{{\]}} +; CHECK: ldr q[[R0:[0-9]+]], {{\[}}[[R1:x[0-9]+]], :lo12:g0 ; CHECK: str d[[R0]] define void @blam() { diff --git a/test/CodeGen/AArch64/misched-fusion-aes.ll b/test/CodeGen/AArch64/misched-fusion-aes.ll new file mode 100644 index 0000000000000..f29dfb3a98021 --- /dev/null +++ b/test/CodeGen/AArch64/misched-fusion-aes.ll @@ -0,0 +1,207 @@ +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a57 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKA57 +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=exynos-m1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKM1 + +declare <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %d, <16 x i8> %k) +declare <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %d) +declare <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %d, <16 x i8> %k) +declare <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %d) + +define void @aesea(<16 x i8>* %a0, <16 x i8>* %b0, <16 x i8>* %c0, <16 x i8> %d, <16 x i8> %e) { + %d0 = load <16 x i8>, <16 x i8>* %a0 + %a1 = getelementptr inbounds <16 x i8>, <16 x i8>* %a0, i64 1 + %d1 = load <16 x i8>, <16 x i8>* %a1 + %a2 = getelementptr inbounds <16 x i8>, <16 x i8>* %a0, i64 2 + %d2 = load <16 x i8>, <16 x i8>* %a2 + %a3 = getelementptr inbounds <16 x i8>, <16 x i8>* %a0, i64 3 + %d3 = load <16 x i8>, <16 x i8>* %a3 + %k0 = load <16 x i8>, <16 x i8>* %b0 + %e00 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %d0, <16 x i8> %k0) + %f00 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e00) + %e01 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %d1, <16 x i8> %k0) + %f01 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e01) + %e02 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %d2, <16 x i8> %k0) + %f02 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e02) + %e03 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %d3, <16 x i8> %k0) + %f03 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e03) + %b1 = getelementptr inbounds <16 x i8>, <16 x i8>* %b0, i64 1 + %k1 = load <16 x i8>, <16 x i8>* %b1 + %e10 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f00, <16 x i8> %k1) + %f10 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e00) + %e11 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f01, <16 x i8> %k1) + %f11 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e01) + %e12 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f02, <16 x i8> %k1) + %f12 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e02) + %e13 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f03, <16 x i8> %k1) + %f13 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e03) + %b2 = getelementptr inbounds <16 x i8>, <16 x i8>* %b0, i64 2 + %k2 = load <16 x i8>, <16 x i8>* %b2 + %e20 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f10, <16 x i8> %k2) + %f20 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e10) + %e21 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f11, <16 x i8> %k2) + %f21 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e11) + %e22 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f12, <16 x i8> %k2) + %f22 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e12) + %e23 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f13, <16 x i8> %k2) + %f23 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e13) + %b3 = getelementptr inbounds <16 x i8>, <16 x i8>* %b0, i64 3 + %k3 = load <16 x i8>, <16 x i8>* %b3 + %e30 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f20, <16 x i8> %k3) + %f30 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e20) + %e31 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f21, <16 x i8> %k3) + %f31 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e21) + %e32 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f22, <16 x i8> %k3) + %f32 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e22) + %e33 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f23, <16 x i8> %k3) + %f33 = call <16 x i8> @llvm.aarch64.crypto.aesmc(<16 x i8> %e23) + %g0 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f30, <16 x i8> %d) + %h0 = xor <16 x i8> %g0, %e + %g1 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f31, <16 x i8> %d) + %h1 = xor <16 x i8> %g1, %e + %g2 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f32, <16 x i8> %d) + %h2 = xor <16 x i8> %g2, %e + %g3 = call <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %f33, <16 x i8> %d) + %h3 = xor <16 x i8> %g3, %e + store <16 x i8> %h0, <16 x i8>* %c0 + %c1 = getelementptr inbounds <16 x i8>, <16 x i8>* %c0, i64 1 + store <16 x i8> %h1, <16 x i8>* %c1 + %c2 = getelementptr inbounds <16 x i8>, <16 x i8>* %c0, i64 2 + store <16 x i8> %h2, <16 x i8>* %c2 + %c3 = getelementptr inbounds <16 x i8>, <16 x i8>* %c0, i64 3 + store <16 x i8> %h3, <16 x i8>* %c3 + ret void + +; CHECK-LABEL: aesea: +; CHECKA57: aese [[VA:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57: aese [[VB:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57: aese [[VC:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesmc {{v[0-7].16b}}, [[VC]] +; CHECKA57: aesmc {{v[0-7].16b}}, [[VA]] +; CHECKA57: aese [[VD:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesmc {{v[0-7].16b}}, [[VD]] +; CHECKA57: aesmc {{v[0-7].16b}}, [[VB]] +; CHECKA57: aese [[VE:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesmc {{v[0-7].16b}}, [[VE]] +; CHECKA57: aese [[VF:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesmc {{v[0-7].16b}}, [[VF]] +; CHECKA57: aese [[VG:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesmc {{v[0-7].16b}}, [[VG]] +; CHECKA57: aese [[VH:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesmc {{v[0-7].16b}}, [[VH]] +; CHECKM1: aese [[VA:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1: aesmc {{v[0-7].16b}}, [[VA]] +; CHECKM1: aese [[VB:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VB]] +; CHECKM1: aese {{v[0-7].16b}}, {{v[0-7].16b}} +; CHECKM1: aese [[VC:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VC]] +; CHECKM1: aese [[VD:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1: aesmc {{v[0-7].16b}}, [[VD]] +; CHECKM1: aese [[VE:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VE]] +; CHECKM1: aese [[VF:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VF]] +; CHECKM1: aese [[VG:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VG]] +; CHECKM1: aese [[VH:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VH]] +} + +define void @aesda(<16 x i8>* %a0, <16 x i8>* %b0, <16 x i8>* %c0, <16 x i8> %d, <16 x i8> %e) { + %d0 = load <16 x i8>, <16 x i8>* %a0 + %a1 = getelementptr inbounds <16 x i8>, <16 x i8>* %a0, i64 1 + %d1 = load <16 x i8>, <16 x i8>* %a1 + %a2 = getelementptr inbounds <16 x i8>, <16 x i8>* %a0, i64 2 + %d2 = load <16 x i8>, <16 x i8>* %a2 + %a3 = getelementptr inbounds <16 x i8>, <16 x i8>* %a0, i64 3 + %d3 = load <16 x i8>, <16 x i8>* %a3 + %k0 = load <16 x i8>, <16 x i8>* %b0 + %e00 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %d0, <16 x i8> %k0) + %f00 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e00) + %e01 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %d1, <16 x i8> %k0) + %f01 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e01) + %e02 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %d2, <16 x i8> %k0) + %f02 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e02) + %e03 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %d3, <16 x i8> %k0) + %f03 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e03) + %b1 = getelementptr inbounds <16 x i8>, <16 x i8>* %b0, i64 1 + %k1 = load <16 x i8>, <16 x i8>* %b1 + %e10 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f00, <16 x i8> %k1) + %f10 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e00) + %e11 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f01, <16 x i8> %k1) + %f11 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e01) + %e12 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f02, <16 x i8> %k1) + %f12 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e02) + %e13 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f03, <16 x i8> %k1) + %f13 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e03) + %b2 = getelementptr inbounds <16 x i8>, <16 x i8>* %b0, i64 2 + %k2 = load <16 x i8>, <16 x i8>* %b2 + %e20 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f10, <16 x i8> %k2) + %f20 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e10) + %e21 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f11, <16 x i8> %k2) + %f21 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e11) + %e22 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f12, <16 x i8> %k2) + %f22 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e12) + %e23 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f13, <16 x i8> %k2) + %f23 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e13) + %b3 = getelementptr inbounds <16 x i8>, <16 x i8>* %b0, i64 3 + %k3 = load <16 x i8>, <16 x i8>* %b3 + %e30 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f20, <16 x i8> %k3) + %f30 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e20) + %e31 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f21, <16 x i8> %k3) + %f31 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e21) + %e32 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f22, <16 x i8> %k3) + %f32 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e22) + %e33 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f23, <16 x i8> %k3) + %f33 = call <16 x i8> @llvm.aarch64.crypto.aesimc(<16 x i8> %e23) + %g0 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f30, <16 x i8> %d) + %h0 = xor <16 x i8> %g0, %e + %g1 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f31, <16 x i8> %d) + %h1 = xor <16 x i8> %g1, %e + %g2 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f32, <16 x i8> %d) + %h2 = xor <16 x i8> %g2, %e + %g3 = call <16 x i8> @llvm.aarch64.crypto.aesd(<16 x i8> %f33, <16 x i8> %d) + %h3 = xor <16 x i8> %g3, %e + store <16 x i8> %h0, <16 x i8>* %c0 + %c1 = getelementptr inbounds <16 x i8>, <16 x i8>* %c0, i64 1 + store <16 x i8> %h1, <16 x i8>* %c1 + %c2 = getelementptr inbounds <16 x i8>, <16 x i8>* %c0, i64 2 + store <16 x i8> %h2, <16 x i8>* %c2 + %c3 = getelementptr inbounds <16 x i8>, <16 x i8>* %c0, i64 3 + store <16 x i8> %h3, <16 x i8>* %c3 + ret void + +; CHECK-LABEL: aesda: +; CHECKA57: aesd [[VA:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57: aesd [[VB:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57: aesd [[VC:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesimc {{v[0-7].16b}}, [[VC]] +; CHECKA57: aesimc {{v[0-7].16b}}, [[VA]] +; CHECKA57: aesd [[VD:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesimc {{v[0-7].16b}}, [[VD]] +; CHECKA57: aesimc {{v[0-7].16b}}, [[VB]] +; CHECKA57: aesd [[VE:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesimc {{v[0-7].16b}}, [[VE]] +; CHECKA57: aesd [[VF:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesimc {{v[0-7].16b}}, [[VF]] +; CHECKA57: aesd [[VG:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesimc {{v[0-7].16b}}, [[VG]] +; CHECKA57: aesd [[VH:v[0-7].16b]], {{v[0-7].16b}} +; CHECKA57-NEXT: aesimc {{v[0-7].16b}}, [[VH]] +; CHECKM1: aesd [[VA:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1: aesimc {{v[0-7].16b}}, [[VA]] +; CHECKM1: aesd [[VB:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VB]] +; CHECKM1: aesd {{v[0-7].16b}}, {{v[0-7].16b}} +; CHECKM1: aesd [[VC:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VC]] +; CHECKM1: aesd [[VD:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1: aesimc {{v[0-7].16b}}, [[VD]] +; CHECKM1: aesd [[VE:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VE]] +; CHECKM1: aesd [[VF:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VF]] +; CHECKM1: aesd [[VG:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VG]] +; CHECKM1: aesd [[VH:v[0-7].16b]], {{v[0-7].16b}} +; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VH]] +} diff --git a/test/CodeGen/AArch64/misched-fusion-lit.ll b/test/CodeGen/AArch64/misched-fusion-lit.ll new file mode 100644 index 0000000000000..45aa67ef1d548 --- /dev/null +++ b/test/CodeGen/AArch64/misched-fusion-lit.ll @@ -0,0 +1,46 @@ +; RUN: llc %s -o - -mtriple=aarch64-unknown -mattr=-fuse-literals | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKDONT +; RUN: llc %s -o - -mtriple=aarch64-unknown -mattr=+fuse-literals | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSE +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a57 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSE + +@g = common local_unnamed_addr global i8* null, align 8 + +define i8* @litp(i32 %a, i32 %b) { +entry: + %add = add nsw i32 %b, %a + %idx.ext = sext i32 %add to i64 + %add.ptr = getelementptr i8, i8* bitcast (i8* (i32, i32)* @litp to i8*), i64 %idx.ext + store i8* %add.ptr, i8** @g, align 8 + ret i8* %add.ptr + +; CHECK-LABEL: litp: +; CHECK: adrp [[R:x[0-9]+]], litp +; CHECKDONT-NEXT: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}} +; CHECKFUSE-NEXT: add {{x[0-9]+}}, [[R]], :lo12:litp +} + +define i32 @liti(i32 %a, i32 %b) { +entry: + %add = add i32 %a, -262095121 + %add1 = add i32 %add, %b + ret i32 %add1 + +; CHECK-LABEL: liti: +; CHECK: mov [[R:w[0-9]+]], {{#[0-9]+}} +; CHECKDONT-NEXT: add {{w[0-9]+}}, {{w[0-9]+}}, {{w[0-9]+}} +; CHECKFUSE-NEXT: movk [[R]], {{#[0-9]+}}, lsl #16 +} + +; Function Attrs: norecurse nounwind readnone +define i64 @litl(i64 %a, i64 %b) { +entry: + %add = add i64 %a, 2208998440489107183 + %add1 = add i64 %add, %b + ret i64 %add1 + +; CHECK-LABEL: litl: +; CHECK: mov [[R:x[0-9]+]], {{#[0-9]+}} +; CHECK-NEXT: movk [[R]], {{#[0-9]+}}, lsl #16 +; CHECK: movk [[R]], {{#[0-9]+}}, lsl #32 +; CHECKDONT-NEXT: add {{x[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}} +; CHECKFUSE-NEXT: movk [[R]], {{#[0-9]+}}, lsl #48 +} diff --git a/test/CodeGen/AArch64/misched-fusion.ll b/test/CodeGen/AArch64/misched-fusion.ll index d5dd9c757dfd7..1d504a2f19316 100644 --- a/test/CodeGen/AArch64/misched-fusion.ll +++ b/test/CodeGen/AArch64/misched-fusion.ll @@ -1,22 +1,14 @@ ; RUN: llc -o - %s -mattr=+arith-cbz-fusion | FileCheck %s ; RUN: llc -o - %s -mcpu=cyclone | FileCheck %s -target triple = "arm64-apple-ios" +target triple = "aarch64-unknown" declare void @foobar(i32 %v0, i32 %v1) ; Make sure sub is scheduled in front of cbnz ; CHECK-LABEL: test_sub_cbz: -; CHECK: add w[[ADDRES:[0-9]+]], w1, #7 ; CHECK: sub w[[SUBRES:[0-9]+]], w0, #13 -; CHECK-NEXT: cbnz w[[SUBRES]], [[SKIPBLOCK:LBB[0-9_]+]] -; CHECK: mov [[REGTY:[x,w]]]0, [[REGTY]][[ADDRES]] -; CHECK: mov [[REGTY]]1, [[REGTY]][[SUBRES]] -; CHECK: bl _foobar -; CHECK: [[SKIPBLOCK]]: -; CHECK: mov [[REGTY]]0, [[REGTY]][[SUBRES]] -; CHECK: mov [[REGTY]]1, [[REGTY]][[ADDRES]] -; CHECK: bl _foobar +; CHECK-NEXT: cbnz w[[SUBRES]], {{.?LBB[0-9_]+}} define void @test_sub_cbz(i32 %a0, i32 %a1) { entry: ; except for the fusion opportunity the sub/add should be equal so the diff --git a/test/CodeGen/AArch64/movimm-wzr.mir b/test/CodeGen/AArch64/movimm-wzr.mir index 093f85bd9319c..60e9bfa03a96a 100644 --- a/test/CodeGen/AArch64/movimm-wzr.mir +++ b/test/CodeGen/AArch64/movimm-wzr.mir @@ -1,4 +1,4 @@ -# RUN: llc -run-pass=aarch64-expand-pseudo %s -o - 2>&1 | FileCheck %s +# RUN: llc -run-pass=aarch64-expand-pseudo %s -o - | FileCheck %s --- | ; ModuleID = 'simple.ll' diff --git a/test/CodeGen/AArch64/movw-shift-encoding.ll b/test/CodeGen/AArch64/movw-shift-encoding.ll index 178fccce333b0..673bd85bd1674 100644 --- a/test/CodeGen/AArch64/movw-shift-encoding.ll +++ b/test/CodeGen/AArch64/movw-shift-encoding.ll @@ -8,8 +8,8 @@ define i32* @get_var() { ret i32* @var -; CHECK: movz x0, #:abs_g3:var // encoding: [0bAAA00000,A,0b111AAAAA,0xd2] -; CHECK: movk x0, #:abs_g2_nc:var // encoding: [0bAAA00000,A,0b110AAAAA,0xf2] -; CHECK: movk x0, #:abs_g1_nc:var // encoding: [0bAAA00000,A,0b101AAAAA,0xf2] -; CHECK: movk x0, #:abs_g0_nc:var // encoding: [0bAAA00000,A,0b100AAAAA,0xf2] +; CHECK: movz x0, #:abs_g0_nc:var // encoding: [0bAAA00000,A,0b100AAAAA,0xd2] +; CHECK: movk x0, #:abs_g1_nc:var // encoding: [0bAAA00000,A,0b101AAAAA,0xf2] +; CHECK: movk x0, #:abs_g2_nc:var // encoding: [0bAAA00000,A,0b110AAAAA,0xf2] +; CHECK: movk x0, #:abs_g3:var // encoding: [0bAAA00000,A,0b111AAAAA,0xf2] } diff --git a/test/CodeGen/AArch64/neon-fma-FMF.ll b/test/CodeGen/AArch64/neon-fma-FMF.ll new file mode 100644 index 0000000000000..25beef6592b26 --- /dev/null +++ b/test/CodeGen/AArch64/neon-fma-FMF.ll @@ -0,0 +1,53 @@ +; RUN: llc < %s -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -mattr=+neon | FileCheck %s + +define <2 x float> @fma(<2 x float> %A, <2 x float> %B, <2 x float> %C) { +; CHECK-LABEL: fma: +; CHECK: fmla {{v[0-9]+}}.2s, {{v[0-9]+}}.2s, {{v[0-9]+}}.2s + %tmp1 = fmul contract <2 x float> %A, %B; + %tmp2 = fadd contract <2 x float> %C, %tmp1; + ret <2 x float> %tmp2 +} + +define <2 x float> @no_fma_1(<2 x float> %A, <2 x float> %B, <2 x float> %C) { +; CHECK-LABEL: no_fma_1: +; CHECK: fmul +; CHECK: fadd + %tmp1 = fmul contract <2 x float> %A, %B; + %tmp2 = fadd <2 x float> %C, %tmp1; + ret <2 x float> %tmp2 +} + +define <2 x float> @no_fma_2(<2 x float> %A, <2 x float> %B, <2 x float> %C) { +; CHECK-LABEL: no_fma_2: +; CHECK: fmul +; CHECK: fadd + %tmp1 = fmul <2 x float> %A, %B; + %tmp2 = fadd contract <2 x float> %C, %tmp1; + ret <2 x float> %tmp2 +} + +define <2 x float> @fma_sub(<2 x float> %A, <2 x float> %B, <2 x float> %C) { +; CHECK-LABEL: fma_sub: +; CHECK: fmls {{v[0-9]+}}.2s, {{v[0-9]+}}.2s, {{v[0-9]+}}.2s + %tmp1 = fmul contract <2 x float> %A, %B; + %tmp2 = fsub contract <2 x float> %C, %tmp1; + ret <2 x float> %tmp2 +} + +define <2 x float> @no_fma_sub_1(<2 x float> %A, <2 x float> %B, <2 x float> %C) { +; CHECK-LABEL: no_fma_sub_1: +; CHECK: fmul +; CHECK: fsub + %tmp1 = fmul contract <2 x float> %A, %B; + %tmp2 = fsub <2 x float> %C, %tmp1; + ret <2 x float> %tmp2 +} + +define <2 x float> @no_fma_sub_2(<2 x float> %A, <2 x float> %B, <2 x float> %C) { +; CHECK-LABEL: no_fma_sub_2: +; CHECK: fmul +; CHECK: fsub + %tmp1 = fmul <2 x float> %A, %B; + %tmp2 = fsub contract <2 x float> %C, %tmp1; + ret <2 x float> %tmp2 +} diff --git a/test/CodeGen/AArch64/optimize-cond-branch.ll b/test/CodeGen/AArch64/optimize-cond-branch.ll index 4e3ca6f16e78c..ab4ad5e2ce93d 100644 --- a/test/CodeGen/AArch64/optimize-cond-branch.ll +++ b/test/CodeGen/AArch64/optimize-cond-branch.ll @@ -11,7 +11,7 @@ target triple = "arm64--" ; ; CHECK-LABEL: func ; CHECK-NOT: and -; CHECK: tbnz +; CHECK: tbz define void @func() { %c0 = icmp sgt i64 0, 0 br i1 %c0, label %b1, label %b6 diff --git a/test/CodeGen/AArch64/pr27816.ll b/test/CodeGen/AArch64/pr27816.ll new file mode 100644 index 0000000000000..df15755cf3f5c --- /dev/null +++ b/test/CodeGen/AArch64/pr27816.ll @@ -0,0 +1,48 @@ +; RUN: llc %s -mtriple=aarch64 -o - | FileCheck %s + +%struct.A = type { i8, i8, i8, i8, i8, i8, i8, i8, i32 } + +; The existence of the final i32 value should not prevent the i8s from +; being merged. + +; CHECK-LABEL: @merge_const_store +; CHECK-NOT: strb +; CHECK: str x8, [x1] +; CHECK-NOT: strb +; CHECK: str wzr, [x1, #8] +; CHECK-NOT: strb +define void @merge_const_store(i32 %count, %struct.A* nocapture %p) { + %1 = icmp sgt i32 %count, 0 + br i1 %1, label %.lr.ph, label %._crit_edge +.lr.ph: + %i.02 = phi i32 [ %add, %.lr.ph ], [ 0, %0 ] + %.01 = phi %struct.A* [ %addr, %.lr.ph ], [ %p, %0 ] + %a2 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 0 + store i8 1, i8* %a2, align 1 + %a3 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 1 + store i8 2, i8* %a3, align 1 + %a4 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 2 + store i8 3, i8* %a4, align 1 + %a5 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 3 + store i8 4, i8* %a5, align 1 + %a6 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 4 + store i8 5, i8* %a6, align 1 + %a7 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 5 + store i8 6, i8* %a7, align 1 + %a8 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 6 + store i8 7, i8* %a8, align 1 + %a9 = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 7 + store i8 8, i8* %a9, align 1 + + ; + %addr_last = getelementptr inbounds %struct.A, %struct.A* %.01, i64 0, i32 8 + store i32 0, i32* %addr_last, align 4 + + + %add = add nsw i32 %i.02, 1 + %addr = getelementptr inbounds %struct.A, %struct.A* %.01, i64 1 + %exitcond = icmp eq i32 %add, %count + br i1 %exitcond, label %._crit_edge, label %.lr.ph +._crit_edge: + ret void +} diff --git a/test/CodeGen/AArch64/prefixdata.ll b/test/CodeGen/AArch64/prefixdata.ll new file mode 100644 index 0000000000000..f62734c16e529 --- /dev/null +++ b/test/CodeGen/AArch64/prefixdata.ll @@ -0,0 +1,29 @@ +; RUN: llc < %s -mtriple=aarch64-apple-darwin | FileCheck --check-prefix=MACHO %s +; RUN: llc < %s -mtriple=aarch64-pc-linux | FileCheck --check-prefix=ELF %s + +@i = linkonce_odr global i32 1 + +; MACHO: ltmp0: +; MACHO-NEXT: .long 1 +; MACHO-NEXT: .alt_entry _f +; MACHO-NEXT: _f: +; ELF: .type f,@function +; ELF-NEXT: .word 1 +; ELF-NEXT: // 0x1 +; ELF-NEXT: f: +define void @f() prefix i32 1 { + ret void +} + +; MACHO: ltmp1: +; MACHO-NEXT: .quad _i +; MACHO-NEXT: .alt_entry _g +; MACHO-NEXT: _g: +; ELF: .type g,@function +; ELF-NEXT: .xword i +; ELF-NEXT: g: +define void @g() prefix i32* @i { + ret void +} + +; MACHO: .subsections_via_symbols diff --git a/test/CodeGen/AArch64/regcoal-physreg.mir b/test/CodeGen/AArch64/regcoal-physreg.mir index c6133991171b8..813106366968d 100644 --- a/test/CodeGen/AArch64/regcoal-physreg.mir +++ b/test/CodeGen/AArch64/regcoal-physreg.mir @@ -1,5 +1,7 @@ # RUN: llc -mtriple=aarch64-apple-ios -run-pass=simple-register-coalescing %s -o - | FileCheck %s --- | + declare void @f2() + define void @func0() { ret void } define void @func1() { ret void } define void @func2() { ret void } @@ -8,36 +10,25 @@ # Check coalescing of COPYs from reserved physregs. # CHECK-LABEL: name: func0 name: func0 -registers: - - { id: 0, class: gpr32 } - - { id: 1, class: gpr64 } - - { id: 2, class: gpr64 } - - { id: 3, class: gpr32 } - - { id: 4, class: gpr64 } - - { id: 5, class: gpr32 } - - { id: 6, class: xseqpairsclass } - - { id: 7, class: gpr64 } - - { id: 8, class: gpr64sp } - - { id: 9, class: gpr64sp } body: | bb.0: ; We usually should not coalesce copies from allocatable physregs. ; CHECK: %0 = COPY %w7 ; CHECK: STRWui %0, %x1, 0 - %0 = COPY %w7 + %0 : gpr32 = COPY %w7 STRWui %0, %x1, 0 ; It is fine to coalesce copies from reserved physregs ; CHECK-NOT: COPY ; CHECK: STRXui %fp, %x1, 0 - %1 = COPY %fp + %1 : gpr64 = COPY %fp STRXui %1, %x1, 0 ; It is not fine to coalesce copies from reserved physregs when they are ; clobbered. ; CHECK: %2 = COPY %fp ; CHECK: STRXui %2, %x1, 0 - %2 = COPY %fp + %2 : gpr64 = COPY %fp %fp = SUBXri %fp, 4, 0 STRXui %2, %x1, 0 @@ -45,7 +36,7 @@ body: | ; clobbered. ; CHECK-NOT: COPY ; CHECK: STRWui %wzr, %x1 - %3 = COPY %wzr + %3 : gpr32 = COPY %wzr dead %wzr = SUBSWri %w1, 0, 0, implicit-def %nzcv STRWui %3, %x1, 0 @@ -53,13 +44,13 @@ body: | ; clobbered. ; CHECK-NOT: COPY ; CHECK: STRXui %xzr, %x1 - %4 = COPY %xzr + %4 : gpr64 = COPY %xzr dead %wzr = SUBSWri %w1, 0, 0, implicit-def %nzcv STRXui %4, %x1, 0 ; Coalescing COPYs into constant physregs. ; CHECK: %wzr = SUBSWri %w1, 0, 0 - %5 = SUBSWri %w1, 0, 0, implicit-def %nzcv + %5 : gpr32 = SUBSWri %w1, 0, 0, implicit-def %nzcv %wzr = COPY %5 ; Only coalesce when the source register is reserved as a whole (this is @@ -67,12 +58,24 @@ body: | ; of the non-reserved part). ; CHECK: %6 = COPY %x28_fp ; CHECK: HINT 0, implicit %6 - %6 = COPY %x28_fp + %6 : xseqpairsclass = COPY %x28_fp HINT 0, implicit %6 + ; It is not fine to coalesce copies from reserved physregs when they are + ; clobbered by the regmask on a call. + ; CHECK: %7 = COPY %x18 + ; CHECK: BL @f2, csr_aarch64_aapcs, implicit-def dead %lr, implicit %sp, implicit-def %sp + ; CHECK: STRXui %7, %x1, 0 + + ; Need a def of x18 so that it's not deduced as "constant". + %x18 = COPY %xzr + %7 : gpr64 = COPY %x18 + BL @f2, csr_aarch64_aapcs, implicit-def dead %lr, implicit %sp, implicit-def %sp + STRXui %7, %x1, 0 + ; This can be coalesced. ; CHECK: %fp = SUBXri %fp, 4, 0 - %8 = SUBXri %fp, 4, 0 + %8 : gpr64sp = SUBXri %fp, 4, 0 %fp = COPY %8 ; Cannot coalesce when there are reads of the physreg. @@ -80,7 +83,7 @@ body: | ; CHECK: %9 = SUBXri %fp, 8, 0 ; CHECK: STRXui %fp, %fp, 0 ; CHECK: %fp = COPY %9 - %9 = SUBXri %fp, 8, 0 + %9 : gpr64sp = SUBXri %fp, 8, 0 STRXui %fp, %fp, 0 %fp = COPY %9 ... @@ -88,8 +91,6 @@ body: | # Check coalescing of COPYs from reserved physregs. # CHECK-LABEL: name: func1 name: func1 -registers: - - { id: 0, class: gpr64sp } body: | bb.0: successors: %bb.1, %bb.2 @@ -99,7 +100,7 @@ body: | ; CHECK: %0 = SUBXri %fp, 12, 0 ; CHECK: CBZX undef %x0, %bb.1 ; CHECK: B %bb.2 - %0 = SUBXri %fp, 12, 0 + %0 : gpr64sp = SUBXri %fp, 12, 0 CBZX undef %x0, %bb.1 B %bb.2 @@ -114,8 +115,6 @@ body: | --- # CHECK-LABEL: name: func2 name: func2 -registers: - - { id: 0, class: gpr64sp } body: | bb.0: successors: %bb.1, %bb.2 @@ -123,7 +122,7 @@ body: | ; CHECK-NOT: COPY ; CHECK: CBZX undef %x0, %bb.1 ; CHECK-NEXT: B %bb.2 - %0 = COPY %fp + %0 : gpr64sp = COPY %fp CBZX undef %x0, %bb.1 B %bb.2 diff --git a/test/CodeGen/AArch64/regress-tblgen-chains.ll b/test/CodeGen/AArch64/regress-tblgen-chains.ll index 4bec512403c4a..24038cda50784 100644 --- a/test/CodeGen/AArch64/regress-tblgen-chains.ll +++ b/test/CodeGen/AArch64/regress-tblgen-chains.ll @@ -28,7 +28,7 @@ define i64 @test_chains() { ; CHECK: ldurb {{w[0-9]+}}, [x29, [[LOCADDR:#-?[0-9]+]]] ; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, #1 ; CHECK: sturb w[[STRVAL:[0-9]+]], [x29, [[LOCADDR]]] -; CHECK; and w0, w[[STRVAL]], #0xff +; CHECK: and w0, w[[STRVAL]], #0xff %ret.1 = load i8, i8* %locvar %ret.2 = zext i8 %ret.1 to i64 diff --git a/test/CodeGen/AArch64/remat.ll b/test/CodeGen/AArch64/remat.ll index 5081a9da34047..80a054beb2a52 100644 --- a/test/CodeGen/AArch64/remat.ll +++ b/test/CodeGen/AArch64/remat.ll @@ -8,7 +8,7 @@ ; RUN: llc -mtriple=aarch64-linux-gnuabi -mcpu=exynos-m3 -o - %s | FileCheck %s ; RUN: llc -mtriple=aarch64-linux-gnuabi -mcpu=falkor -o - %s | FileCheck %s ; RUN: llc -mtriple=aarch64-linux-gnuabi -mcpu=kryo -o - %s | FileCheck %s -; RUN: llc -mtriple=aarch64-linux-gnuabi -mcpu=vulcan -o - %s | FileCheck %s +; RUN: llc -mtriple=aarch64-linux-gnuabi -mcpu=thunderx2t99 -o - %s | FileCheck %s ; RUN: llc -mtriple=aarch64-linux-gnuabi -mattr=+custom-cheap-as-move -o - %s | FileCheck %s %X = type { i64, i64, i64 } diff --git a/test/CodeGen/AArch64/selectiondag-order.ll b/test/CodeGen/AArch64/selectiondag-order.ll new file mode 100644 index 0000000000000..9427906160fd0 --- /dev/null +++ b/test/CodeGen/AArch64/selectiondag-order.ll @@ -0,0 +1,96 @@ +; Check that debug intrinsics do not affect code generation. + +; RUN: llc < %s -mtriple=aarch64-unknown-unknown -mattr=+avx | FileCheck --check-prefix=AARCH64-CHECK %s + +define i64 @simulate(<2 x i32> %a) { +entry: + %rand = tail call i64 @lrand48() + br label %body + +body: ; preds = %body, %entry + %0 = phi <2 x i32> [ %add, %body ], [ zeroinitializer, %entry ] + %add = add <2 x i32> %0, %a + %rand1 = tail call i64 @lrand48() #3 + %cmp = icmp eq i64 %rand1, 0 + br i1 %cmp, label %end, label %body + +end: ; preds = %body + %c = bitcast <2 x i32> %add to i64 + %res = add i64 %rand, %c + ret i64 %res +} + +; AARCH64-CHECK: simulate: +; AARCH64-CHECK: movi d9, #0000000000000000 +; AARCH64-CHECK: bl lrand48 +; AARCH64-CHECK: mov x19, x0 +; AARCH64-CHECK: BB0_1: + + +define i64 @simulateWithDebugIntrinsic(<2 x i32> %a) local_unnamed_addr { +entry: + %rand = tail call i64 @lrand48() #3 + tail call void @llvm.dbg.value(metadata i64 %rand, i64 0, metadata !6, metadata !7), !dbg !8 + br label %body + +body: ; preds = %body, %entry + %0 = phi <2 x i32> [ %add, %body ], [ zeroinitializer, %entry ] + %add = add <2 x i32> %0, %a + %rand1 = tail call i64 @lrand48() #3 + %cmp = icmp eq i64 %rand1, 0 + br i1 %cmp, label %end, label %body + +end: ; preds = %body + %c = bitcast <2 x i32> %add to i64 + %res = add i64 %rand, %c + ret i64 %res +} + +; AARCH64-CHECK: simulateWithDebugIntrinsic +; AARCH64-CHECK: movi d9, #0000000000000000 +; AARCH64-CHECK: bl lrand48 +; AARCH64-CHECK: mov x19, x0 +; AARCH64-CHECK: BB1_1: + + +define i64 @simulateWithDbgDeclare(<2 x i32> %a) local_unnamed_addr { +entry: + %rand = tail call i64 @lrand48() #3 + tail call void @llvm.dbg.declare(metadata i64 %rand, metadata !6, metadata !7), !dbg !8 + br label %body + +body: ; preds = %body, %entry + %0 = phi <2 x i32> [ %add, %body ], [ zeroinitializer, %entry ] + %add = add <2 x i32> %0, %a + %rand1 = tail call i64 @lrand48() #3 + %cmp = icmp eq i64 %rand1, 0 + br i1 %cmp, label %end, label %body + +end: ; preds = %body + %c = bitcast <2 x i32> %add to i64 + %res = add i64 %rand, %c + ret i64 %res +} + +; AARCH64-CHECK: simulateWithDbgDeclare: +; AARCH64-CHECK: movi d9, #0000000000000000 +; AARCH64-CHECK: bl lrand48 +; AARCH64-CHECK: mov x19, x0 +; AARCH64-CHECK: BB2_1: + +declare i64 @lrand48() + +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!1} +!llvm.module.flags = !{!3, !4} + +!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, runtimeVersion: 0, emissionKind: FullDebug) +!2 = !DIFile(filename: "test.ll", directory: ".") +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = distinct !DISubprogram(name: "simulateWithDebugIntrinsic", scope: !2, file: !2, line: 64, isLocal: false, isDefinition: true, scopeLine: 65, unit: !1) +!6 = !DILocalVariable(name: "randv", scope: !5, file: !2, line: 69) +!7 = !DIExpression() +!8 = !DILocation(line: 132, column: 2, scope: !5) diff --git a/test/CodeGen/AArch64/stack-protector-target.ll b/test/CodeGen/AArch64/stack-protector-target.ll index d4d806289bff3..787e4a76ec01b 100644 --- a/test/CodeGen/AArch64/stack-protector-target.ll +++ b/test/CodeGen/AArch64/stack-protector-target.ll @@ -1,5 +1,7 @@ ; Test target-specific stack cookie location. ; RUN: llc -mtriple=aarch64-linux-android < %s -o - | FileCheck --check-prefix=ANDROID-AARCH64 %s +; RUN: llc -mtriple=aarch64-fuchsia < %s -o - | FileCheck --check-prefixes=FUCHSIA-AARCH64-COMMON,FUCHSIA-AARCH64-USER %s +; RUN: llc -mtriple=aarch64-fuchsia -code-model=kernel < %s -o - | FileCheck --check-prefixes=FUCHSIA-AARCH64-COMMON,FUCHSIA-AARCH64-KERNEL %s define void @_Z1fv() sspreq { entry: @@ -17,3 +19,11 @@ declare void @_Z7CapturePi(i32*) ; ANDROID-AARCH64: ldr [[C:.*]], {{\[}}[[A]], #40] ; ANDROID-AARCH64: ldr [[D:.*]], [sp, ; ANDROID-AARCH64: cmp [[C]], [[D]] + +; FUCHSIA-AARCH64-USER: mrs [[A:.*]], TPIDR_EL0 +; FUCHSIA-AARCH64-KERNEL: mrs [[A:.*]], TPIDR_EL1 +; FUCHSIA-AARCH64-COMMON: ldur [[B:.*]], {{\[}}[[A]], #-16] +; FUCHSIA-AARCH64-COMMON: str [[B]], [sp, +; FUCHSIA-AARCH64-COMMON: ldur [[C:.*]], {{\[}}[[A]], #-16] +; FUCHSIA-AARCH64-COMMON: ldr [[D:.*]], [sp, +; FUCHSIA-AARCH64-COMMON: cmp [[C]], [[D]] diff --git a/test/CodeGen/AArch64/stack_guard_remat.ll b/test/CodeGen/AArch64/stack_guard_remat.ll index d6bae62e5edcf..2b7b3485311ae 100644 --- a/test/CodeGen/AArch64/stack_guard_remat.ll +++ b/test/CodeGen/AArch64/stack_guard_remat.ll @@ -15,10 +15,10 @@ ; PIC-LINUX: ldr {{x[0-9]+}}, {{\[}}[[R1]]{{\]}} ; STATIC-LARGE: foo2 -; STATIC-LARGE: movz [[R0:x[0-9]+]], #:abs_g3:__stack_chk_guard -; STATIC-LARGE: movk [[R0]], #:abs_g2_nc:__stack_chk_guard +; STATIC-LARGE: movz [[R0:x[0-9]+]], #:abs_g0_nc:__stack_chk_guard ; STATIC-LARGE: movk [[R0]], #:abs_g1_nc:__stack_chk_guard -; STATIC-LARGE: movk [[R0]], #:abs_g0_nc:__stack_chk_guard +; STATIC-LARGE: movk [[R0]], #:abs_g2_nc:__stack_chk_guard +; STATIC-LARGE: movk [[R0]], #:abs_g3:__stack_chk_guard ; STATIC-LARGE: ldr {{x[0-9]+}}, {{\[}}[[R0]]{{\]}} ; STATIC-SMALL: foo2 @@ -29,20 +29,20 @@ define i32 @test_stack_guard_remat() #0 { entry: %a1 = alloca [256 x i32], align 4 %0 = bitcast [256 x i32]* %a1 to i8* - call void @llvm.lifetime.start(i64 1024, i8* %0) + call void @llvm.lifetime.start.p0i8(i64 1024, i8* %0) %arraydecay = getelementptr inbounds [256 x i32], [256 x i32]* %a1, i64 0, i64 0 call void @foo3(i32* %arraydecay) call void asm sideeffect "foo2", "~{w0},~{w1},~{w2},~{w3},~{w4},~{w5},~{w6},~{w7},~{w8},~{w9},~{w10},~{w11},~{w12},~{w13},~{w14},~{w15},~{w16},~{w17},~{w18},~{w19},~{w20},~{w21},~{w22},~{w23},~{w24},~{w25},~{w26},~{w27},~{w28},~{w29},~{w30}"() - call void @llvm.lifetime.end(i64 1024, i8* %0) + call void @llvm.lifetime.end.p0i8(i64 1024, i8* %0) ret i32 0 } ; Function Attrs: nounwind -declare void @llvm.lifetime.start(i64, i8* nocapture) +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) declare void @foo3(i32*) ; Function Attrs: nounwind -declare void @llvm.lifetime.end(i64, i8* nocapture) +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) attributes #0 = { nounwind sspstrong "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/test/CodeGen/AArch64/tail-dup-repeat-worklist.ll b/test/CodeGen/AArch64/tail-dup-repeat-worklist.ll deleted file mode 100644 index c2997c50f4d45..0000000000000 --- a/test/CodeGen/AArch64/tail-dup-repeat-worklist.ll +++ /dev/null @@ -1,69 +0,0 @@ -; RUN: llc -O3 -o - -verify-machineinstrs %s | FileCheck %s -target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" -target triple = "aarch64-unknown-linux-gnu" - -%struct.s1 = type { %struct.s3*, %struct.s1* } -%struct.s2 = type opaque -%struct.s3 = type { i32 } - -; Function Attrs: nounwind -define internal fastcc i32 @repeated_dup_worklist(%struct.s1** %pp1, %struct.s2* %p2, i32 %state, i1 %i1_1, i32 %i32_1) unnamed_addr #0 { -entry: - br label %while.cond.outer - -; The loop gets laid out: -; %while.cond.outer -; %(null) -; %(null) -; %dup2 -; and then %dup1 gets chosen as the next block. -; when dup2 is duplicated into dup1, %worklist could erroneously be placed on -; the worklist, because all of its current predecessors are now scheduled. -; However, after dup2 is tail-duplicated, %worklist can't be on the worklist -; because it now has unscheduled predecessors.q -; CHECK-LABEL: repeated_dup_worklist -; CHECK: // %entry -; CHECK: // %while.cond.outer -; first %(null) block -; CHECK: // in Loop: -; CHECK: ldr -; CHECK-NEXT: tbnz -; second %(null) block -; CHECK: // in Loop: -; CHECK: // %dup2 -; CHECK: // %worklist -; CHECK: // %if.then96.i -while.cond.outer: ; preds = %dup1, %entry - %progress.0.ph = phi i32 [ 0, %entry ], [ %progress.1, %dup1 ] - %inc77 = add nsw i32 %progress.0.ph, 1 - %cmp = icmp slt i32 %progress.0.ph, %i32_1 - br i1 %cmp, label %dup2, label %dup1 - -dup2: ; preds = %if.then96.i, %worklist, %while.cond.outer - %progress.1.ph = phi i32 [ 0, %while.cond.outer ], [ %progress.1, %if.then96.i ], [ %progress.1, %worklist ] - %.pr = load %struct.s1*, %struct.s1** %pp1, align 8 - br label %dup1 - -dup1: ; preds = %dup2, %while.cond.outer - %0 = phi %struct.s1* [ %.pr, %dup2 ], [ undef, %while.cond.outer ] - %progress.1 = phi i32 [ %progress.1.ph, %dup2 ], [ %inc77, %while.cond.outer ] - br i1 %i1_1, label %while.cond.outer, label %worklist - -worklist: ; preds = %dup1 - %snode94 = getelementptr inbounds %struct.s1, %struct.s1* %0, i64 0, i32 0 - %1 = load %struct.s3*, %struct.s3** %snode94, align 8 - %2 = getelementptr inbounds %struct.s3, %struct.s3* %1, i32 0, i32 0 - %3 = load i32, i32* %2, align 4 - %tobool95.i = icmp eq i32 %3, 0 - br i1 %tobool95.i, label %if.then96.i, label %dup2 - -if.then96.i: ; preds = %worklist - call fastcc void @free_s3(%struct.s2* %p2, %struct.s3* %1) #1 - br label %dup2 -} - -; Function Attrs: nounwind -declare fastcc void @free_s3(%struct.s2*, %struct.s3*) unnamed_addr #0 - -attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a57" "target-features"="+crc,+crypto,+neon" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind } diff --git a/test/CodeGen/AArch64/tailcall-string-rvo.ll b/test/CodeGen/AArch64/tailcall-string-rvo.ll new file mode 100644 index 0000000000000..bdc09235afd9c --- /dev/null +++ b/test/CodeGen/AArch64/tailcall-string-rvo.ll @@ -0,0 +1,47 @@ +; RUN: llc -relocation-model=static -verify-machineinstrs -O2 < %s | FileCheck %s + +; The call to function TestBar should be a tail call, when in C++ the string +; `ret` is RVO returned. +; string TestFoo() { +; string ret = undef; +; TestBar(&ret); // tail call optimized +; return ret; +; } + +target triple = "aarch64-linux-gnu" + +%class.basic_string.11.42.73 = type { %"class.__gnu_cxx::__versa_string.10.41.72" } +%"class.__gnu_cxx::__versa_string.10.41.72" = type { %"class.__gnu_cxx::__sso_string_base.9.40.71" } +%"class.__gnu_cxx::__sso_string_base.9.40.71" = type { %"struct.__gnu_cxx::__vstring_utility<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider.7.38.69", i64, %union.anon.8.39.70 } +%"struct.__gnu_cxx::__vstring_utility<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider.7.38.69" = type { i8* } +%union.anon.8.39.70 = type { i64, [8 x i8] } + +declare void @TestBaz(%class.basic_string.11.42.73* noalias sret %arg) + +define void @TestBar(%class.basic_string.11.42.73* noalias sret %arg) { +bb: + call void @TestBaz(%class.basic_string.11.42.73* noalias sret %arg) + ret void +} + +define void @TestFoo(%class.basic_string.11.42.73* noalias sret %arg) { +; CHECK-LABEL: TestFoo: +; CHECK: b TestBar +bb: + %tmp = getelementptr inbounds %class.basic_string.11.42.73, %class.basic_string.11.42.73* %arg, i64 0, i32 0, i32 0, i32 2 + %tmp1 = bitcast %class.basic_string.11.42.73* %arg to %union.anon.8.39.70** + store %union.anon.8.39.70* %tmp, %union.anon.8.39.70** %tmp1, align 8 + %tmp2 = bitcast %union.anon.8.39.70* %tmp to i8* + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp2, i8* nonnull undef, i64 13, i32 1, i1 false) + %tmp3 = getelementptr inbounds %class.basic_string.11.42.73, %class.basic_string.11.42.73* %arg, i64 0, i32 0, i32 0, i32 1 + store i64 13, i64* %tmp3, align 8 + %tmp4 = getelementptr inbounds %class.basic_string.11.42.73, %class.basic_string.11.42.73* %arg, i64 0, i32 0, i32 0, i32 2, i32 1, i64 5 + store i8 0, i8* %tmp4, align 1 + tail call void @TestBar(%class.basic_string.11.42.73* noalias sret %arg) + ret void +} + +; Function Attrs: argmemonly nounwind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0 + +attributes #0 = { argmemonly nounwind } diff --git a/test/CodeGen/AArch64/tbz-tbnz.ll b/test/CodeGen/AArch64/tbz-tbnz.ll index 0dd265c18ec76..7ef78ca52a249 100644 --- a/test/CodeGen/AArch64/tbz-tbnz.ll +++ b/test/CodeGen/AArch64/tbz-tbnz.ll @@ -10,7 +10,7 @@ entry: br i1 %cmp, label %if.then, label %if.end ; CHECK: sub [[CMP:w[0-9]+]], w0, #12 -; CHECK: tbz [[CMP]], #31 +; CHECK: tbnz [[CMP]], #31 if.then: call void @t() @@ -28,7 +28,7 @@ entry: br i1 %cmp, label %if.then, label %if.end ; CHECK: sub [[CMP:x[0-9]+]], x0, #12 -; CHECK: tbz [[CMP]], #63 +; CHECK: tbnz [[CMP]], #63 if.then: call void @t() @@ -118,7 +118,7 @@ entry: br i1 %cmp, label %if.then, label %if.end ; CHECK: sub [[CMP:w[0-9]+]], w0, #12 -; CHECK: tbz [[CMP]], #31 +; CHECK: tbnz [[CMP]], #31 if.then: call void @t() @@ -178,7 +178,7 @@ define void @test9(i64 %val1) { br i1 %tst, label %if.then, label %if.end ; CHECK-NOT: cmp -; CHECK: tbz x0, #63 +; CHECK: tbnz x0, #63 if.then: call void @t() @@ -194,7 +194,7 @@ define void @test10(i64 %val1) { br i1 %tst, label %if.then, label %if.end ; CHECK-NOT: cmp -; CHECK: tbz x0, #63 +; CHECK: tbnz x0, #63 if.then: call void @t() @@ -209,7 +209,7 @@ define void @test11(i64 %val1, i64* %ptr) { ; CHECK: ldr [[CMP:x[0-9]+]], [x1] ; CHECK-NOT: cmp -; CHECK: tbz [[CMP]], #63 +; CHECK: tbnz [[CMP]], #63 %val = load i64, i64* %ptr %tst = icmp slt i64 %val, 0 @@ -229,7 +229,7 @@ define void @test12(i64 %val1) { br i1 %tst, label %if.then, label %if.end ; CHECK-NOT: cmp -; CHECK: tbz x0, #63 +; CHECK: tbnz x0, #63 if.then: call void @t() @@ -247,7 +247,7 @@ define void @test13(i64 %val1, i64 %val2) { ; CHECK: orr [[CMP:x[0-9]+]], x0, x1 ; CHECK-NOT: cmp -; CHECK: tbz [[CMP]], #63 +; CHECK: tbnz [[CMP]], #63 if.then: call void @t() diff --git a/test/CodeGen/AArch64/thread-pointer.ll b/test/CodeGen/AArch64/thread-pointer.ll new file mode 100644 index 0000000000000..91585791a58e9 --- /dev/null +++ b/test/CodeGen/AArch64/thread-pointer.ll @@ -0,0 +1,60 @@ +; RUN: llc -mtriple=aarch64-linux-gnu -verify-machineinstrs -o - %s | FileCheck %s + +@x = thread_local local_unnamed_addr global i32 0, align 4 +@y = thread_local local_unnamed_addr global i32 0, align 4 + +; Machine LICM should hoist the mrs into the loop preheader. +; CHECK-LABEL: @test1 +; CHECK: BB#1: +; CHECK: mrs x[[BASE:[0-9]+]], TPIDR_EL0 +; CHECK: add x[[REG1:[0-9]+]], x[[BASE]], :tprel_hi12:x +; CHECK: add x[[REG2:[0-9]+]], x[[REG1]], :tprel_lo12_nc:x +; +; CHECK: .LBB0_2: +; CHECK: ldr w0, [x[[REG2]]] +; CHECK: bl bar +; CHECK: sub w[[REG3:[0-9]+]], w{{[0-9]+}}, #1 +; CHECK: cbnz w[[REG3]], .LBB0_2 + +define void @test1(i32 %n) local_unnamed_addr { +entry: + %cmp3 = icmp sgt i32 %n, 0 + br i1 %cmp3, label %bb1, label %bb2 + +bb1: + br label %for.body + +for.body: + %i.04 = phi i32 [ %inc, %for.body ], [ 0, %bb1 ] + %0 = load i32, i32* @x, align 4 + tail call void @bar(i32 %0) #2 + %inc = add nuw nsw i32 %i.04, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %bb2, label %for.body + +bb2: + ret void +} + +; Machine CSE should combine the the mrs between the load of %x and %y. +; CHECK-LABEL: @test2 +; CHECK: mrs x{{[0-9]+}}, TPIDR_EL0 +; CHECK-NOT: mrs x{{[0-9]+}}, TPIDR_EL0 +; CHECK: ret +define void @test2(i32 %c) local_unnamed_addr #0 { +entry: + %0 = load i32, i32* @x, align 4 + tail call void @bar(i32 %0) #2 + %cmp = icmp eq i32 %c, 0 + br i1 %cmp, label %if.end, label %if.then + +if.then: + %1 = load i32, i32* @y, align 4 + tail call void @bar(i32 %1) #2 + br label %if.end + +if.end: + ret void +} + +declare void @bar(i32) local_unnamed_addr diff --git a/test/CodeGen/AArch64/vector_merge_dep_check.ll b/test/CodeGen/AArch64/vector_merge_dep_check.ll index 9220947e8362b..e4e64ef8c8dbf 100644 --- a/test/CodeGen/AArch64/vector_merge_dep_check.ll +++ b/test/CodeGen/AArch64/vector_merge_dep_check.ll @@ -1,5 +1,4 @@ -; RUN: llc --combiner-alias-analysis=false < %s | FileCheck %s -; RUN: llc --combiner-alias-analysis=true < %s | FileCheck %s +; RUN: llc < %s | FileCheck %s ; This test checks that we do not merge stores together which have ; dependencies through their non-chain operands (e.g. one store is the diff --git a/test/CodeGen/AArch64/xray-tail-call-sled.ll b/test/CodeGen/AArch64/xray-tail-call-sled.ll new file mode 100644 index 0000000000000..6ada3ce8d551b --- /dev/null +++ b/test/CodeGen/AArch64/xray-tail-call-sled.ll @@ -0,0 +1,69 @@ +; RUN: llc -filetype=asm -o - -mtriple=aarch64-linux-gnu < %s | FileCheck %s
+
+define i32 @callee() nounwind noinline uwtable "function-instrument"="xray-always" {
+; CHECK: .p2align 2
+; CHECK-LABEL: .Lxray_sled_0:
+; CHECK-NEXT: b #32
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-LABEL: .Ltmp0:
+ ret i32 0
+; CHECK-NEXT: mov w0, wzr
+; CHECK-NEXT: .p2align 2
+; CHECK-LABEL: .Lxray_sled_1:
+; CHECK-NEXT: b #32
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-LABEL: .Ltmp1:
+; CHECK-NEXT: ret
+}
+; CHECK: .p2align 4
+; CHECK-NEXT: .xword .Lxray_synthetic_0
+; CHECK-NEXT: .section xray_instr_map,{{.*}}
+; CHECK-LABEL: Lxray_synthetic_0:
+; CHECK: .xword .Lxray_sled_0
+; CHECK: .xword .Lxray_sled_1
+
+define i32 @caller() nounwind noinline uwtable "function-instrument"="xray-always" {
+; CHECK: .p2align 2
+; CHECK-LABEL: .Lxray_sled_2:
+; CHECK-NEXT: b #32
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-LABEL: .Ltmp2:
+; CHECK: .p2align 2
+; CHECK-LABEL: .Lxray_sled_3:
+; CHECK-NEXT: b #32
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-NEXT: nop
+; CHECK-LABEL: .Ltmp3:
+ %retval = tail call i32 @callee()
+; CHECK: b callee
+ ret i32 %retval
+}
+; CHECK: .p2align 4
+; CHECK-NEXT: .xword .Lxray_synthetic_1
+; CHECK-NEXT: .section xray_instr_map,{{.*}}
+; CHECK-LABEL: Lxray_synthetic_1:
+; CHECK: .xword .Lxray_sled_2
+; CHECK: .xword .Lxray_sled_3
|