# 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: liveins: $x0, $x1 $x0 = COPY $x1 CBNZX $x1, %bb.2 bb.1: $x0 = COPY $xzr B %bb.3 bb.2: 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: liveins: $x0, $x1 $x1 = COPY $x0 CBNZX $x1, %bb.2 bb.1: $x0 = COPY $xzr B %bb.3 bb.2: 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: liveins: $x0, $x1, $x2 $x0 = COPY $x1 $x1 = LDRXui $x1, 0 CBNZX $x1, %bb.2 bb.1: $x0 = COPY $xzr B %bb.3 bb.2: 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: liveins: $x0, $x1, $x2 $x1 = COPY $x0 $x1 = LDRXui $x1, 0 CBNZX $x1, %bb.2 bb.1: $x0 = COPY $xzr B %bb.3 bb.2: 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: liveins: $x0, $x1, $x2 $x1 = COPY $x0 $x0 = LDRXui $x1, 0 CBNZX $x1, %bb.2 bb.1: $x0 = COPY $xzr B %bb.3 bb.2: 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: liveins: $x0, $x1, $x2 $x2 = COPY $x0 $x1 = COPY $x2 CBNZX $x1, %bb.2 bb.1: $x0 = COPY $xzr B %bb.3 bb.2: 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: liveins: $x0, $x1, $x2 $x2 = COPY $x0 $x0 = LDRXui $x1, 0 $x1 = COPY $x2 CBNZX $x1, %bb.2 bb.1: $x0 = COPY $xzr B %bb.3 bb.2: 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: liveins: $x0, $x1, $x2 $x1 = COPY $x0 CBNZX $x1, %bb.2 bb.1: liveins: $x0, $x2 $x0, $x1 = LDPXi $x2, 0 $x0 = COPY $xzr $x1 = COPY $xzr B %bb.3 bb.2: 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: liveins: $x0, $x1 CBNZX $x0, %bb.2 bb.1: liveins: $x0 $x0 = COPY $xzr B %bb.3 bb.2: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: liveins: $x0, $x1 CBNZX killed $x0, %bb.2 B %bb.1 bb.1: 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: 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: 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: 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: liveins: $x1 $x0 = MOVi64imm -1 STRXui killed $x0, killed $x1, 0 bb.2: RET_ReallyLR ... # Don't eliminate redundant MOVi32imm -1 in bb.1: the upper bits are nonzero. # Note: 64-bit compare/32-bit move imm # Kill marker should be removed from compare. # CHECK-LABEL: name: test21 # CHECK: ADDSXri killed $x0, 1, 0, implicit-def $nzcv # CHECK: bb.1: # CHECK: MOVi32imm name: test21 tracksRegLiveness: true body: | bb.0.entry: 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: 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: 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: 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: 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: liveins: $x1 $w0 = MOVi32imm 4096 STRWui killed $w0, killed $x1, 0 bb.2: RET_ReallyLR