# RUN: llc -mtriple=aarch64--linux-gnu -run-pass=aarch64-ldst-opt %s -verify-machineinstrs -o - | FileCheck %s --- name: promote-load-from-store tracksRegLiveness: true body: | bb.0: liveins: $w1, $x0, $lr STRWui killed $w1, $x0, 0 :: (store (s32)) CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 $w0 = LDRHHui killed $x0, 1 :: (load (s16)) RET $lr, implicit $w0 ... # Don't count transient instructions towards search limits. # CHECK-LABEL: name: promote-load-from-store # CHECK: STRWui $w1 # CHECK: UBFMWri killed $w1 --- name: store-pair tracksRegLiveness: true body: | bb.0: liveins: $w1, $x0, $lr STRWui $w1, $x0, 0 :: (store (s32)) CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 STRWui killed $w1, killed $x0, 1 :: (store (s32)) RET $lr ... # CHECK-LABEL: name: store-pair # CHECK: STPWi --- name: store-pair-clearkill0 tracksRegLiveness: true body: | bb.0: liveins: $w1, $x0, $lr STRWui $w1, $x0, 0 :: (store (s32)) $w2 = COPY $w1 $x3 = COPY $x0 STRWui killed $w1, killed $x0, 1 :: (store (s32)) RET $lr ... # When merging a lower store with an upper one, we must clear kill flags on # the lower store. # CHECK-LABEL: store-pair-clearkill0 # CHECK-NOT: STPWi $w1, killed $w1, $x0, 0 :: (store (s32)) # CHECK: STPWi $w1, $w1, $x0, 0 :: (store (s32)) # CHECK: $w2 = COPY $w1 # CHECK: RET $lr --- name: store-pair-clearkill1 tracksRegLiveness: true body: | bb.0: liveins: $x0, $lr $w1 = MOVi32imm 13 $w2 = MOVi32imm 7 STRWui $w1, $x0, 1 :: (store (s32)) $w2 = COPY killed $w1 STRWui killed $w2, $x0, 0 :: (store (s32)) $w1 = MOVi32imm 42 $w2 = MOVi32imm 7 STRWui $w1, $x0, 0 :: (store (s32)) $w2 = COPY killed $w1 STRWui killed $w2, killed $x0, 1 :: (store (s32)) RET $lr ... # When merging an upper store with a lower one, kill flags along the way need # to be removed; In this case the kill flag on $w1. # CHECK-LABEL: store-pair-clearkill1 # CHECK: $w1 = MOVi32imm # CHECK: $w2 = MOVi32imm # CHECK-NOT: $w2 = COPY killed $w1 # CHECK: $w2 = COPY $w1 # CHECK: STPWi killed $w2, $w1, $x0, 0 # CHECK: $w1 = MOVi32imm # CHECK: $w2 = MOVi32imm # CHECK-NOT: $w2 = COPY killed $w1 # CHECK: $w2 = COPY $w1 # CHECK: STPWi $w1, killed $w2, killed $x0, 0 --- name: store-load-clearkill tracksRegLiveness: true body: | bb.0: liveins: $w1 STRWui $w1, $sp, 0 :: (store (s32)) $wzr = COPY killed $w1 ; killing use of $w1 $w11 = LDRWui $sp, 0 :: (load (s32)) HINT 0, implicit $w11 ; some use of $w11 ... # When replaceing the load of a store-load pair with a copy the kill flags # along the way need to be cleared. # CHECK-LABEL: name: store-load-clearkill # CHECK: STRWui $w1, $sp, 0 :: (store (s32)) # CHECK-NOT: COPY killed $w1 # CHECK: $wzr = COPY $w1 # CHECK: $w11 = ORRWrs $wzr, $w1, 0 # CHECK: HINT 0, implicit $w11 --- name: promote-load-from-store-undef tracksRegLiveness: true body: | bb.0: liveins: $x0, $x2, $lr STRWui undef $w1, $x0, 0 :: (store (s32)) $w0 = LDRBBui $x0, 1 :: (load (s16)) STRHHui undef $w3, $x2, 0 :: (store (s32)) $w1 = LDRBBui $x2, 0 :: (load (s32)) RET $lr, implicit $w0 ... # CHECK-LABEL: name: promote-load-from-store-undef # CHECK: STRWui undef $w1 # CHECK: UBFMWri undef $w1 # CHECK: STRHHui undef $w3 # CHECK: ANDWri undef $w3 --- name: promote-load-from-store-trivial-kills tracksRegLiveness: true body: | bb.0: liveins: $x0, $lr STRXui $x0, $sp, 0 :: (store (s64)) STRXui killed $x0, $sp, 2 :: (store (s64)) $x0 = LDRXui $sp, 0 :: (load (s64)) BL &bar, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0, implicit-def $sp RET $lr ... # CHECK-LABEL: name: promote-load-from-store-trivial-kills # CHECK: STRXui $x0, $sp, 0 # CHECK: STRXui $x0, $sp, 2 # CHECK-NOT: LDRXui # CHECK-NOT: ORR # CHECK: BL &bar, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0, implicit-def $sp name: test_LDRBB body: | bb.0.entry: liveins: $x0, $x1 $w2 = LDRBBui $x0, 0 :: (load (s8)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 $w3 = LDRBBui $x1, 0 :: (load (s8)) ... # CHECK-LABEL: name: test_LDRBB # CHECK: LDRBBpost $x0, 1 # CHECK: LDRBBpre $x1, 1 name: test_LDRHH body: | bb.0.entry: liveins: $x0, $x1 $w2 = LDRHHui $x0, 0 :: (load (s16)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 $w3 = LDRHHui $x1, 0 :: (load (s16)) ... # CHECK-LABEL: name: test_LDRHH # CHECK: LDRHHpost $x0, 1 # CHECK: LDRHHpre $x1, 1 name: test_LDRW body: | bb.0.entry: liveins: $x0, $x1 $w2 = LDRWui $x0, 0 :: (load (s32)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 $w3 = LDRWui $x1, 0 :: (load (s32)) ... # CHECK-LABEL: name: test_LDRW # CHECK: LDRWpost $x0, 1 # CHECK: LDRWpre $x1, 1 name: test_LDRX body: | bb.0.entry: liveins: $x0, $x1 $x2 = LDRXui $x0, 0 :: (load (s64)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 $x3 = LDRXui $x1, 0 :: (load (s64)) ... # CHECK-LABEL: name: test_LDRX # CHECK: LDRXpost $x0, 1 # CHECK: LDRXpre $x1, 1 name: test_LDRB body: | bb.0.entry: liveins: $x0, $x1 $b0 = LDRBui $x0, 0 :: (load (s8)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 $b1 = LDRBui $x1, 0 :: (load (s8)) ... # CHECK-LABEL: name: test_LDRB # CHECK: LDRBpost $x0, 1 # CHECK: LDRBpre $x1, 1 name: test_LDRH body: | bb.0.entry: liveins: $x0, $x1 $h0 = LDRHui $x0, 0 :: (load (s16)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 $h1 = LDRHui $x1, 0 :: (load (s16)) ... # CHECK-LABEL: name: test_LDRH # CHECK: LDRHpost $x0, 1 # CHECK: LDRHpre $x1, 1 name: test_LDRS body: | bb.0.entry: liveins: $x0, $x1 $s0 = LDRSui $x0, 0 :: (load (s32)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 $s1 = LDRSui $x1, 0 :: (load (s32)) ... # CHECK-LABEL: name: test_LDRS # CHECK: LDRSpost $x0, 1 # CHECK: LDRSpre $x1, 1 name: test_LDRD body: | bb.0.entry: liveins: $x0, $x1 $d0 = LDRDui $x0, 0 :: (load (s64)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 $d1 = LDRDui $x1, 0 :: (load (s64)) ... # CHECK-LABEL: name: test_LDRD # CHECK: LDRDpost $x0, 1 # CHECK: LDRDpre $x1, 1 name: test_LDRQ body: | bb.0.entry: liveins: $x0, $x1 $q0 = LDRQui $x0, 0 :: (load (s128)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 $q1 = LDRQui $x1, 0 :: (load (s128)) ... # CHECK-LABEL: name: test_LDRQ # CHECK: LDRQpost $x0, 1 # CHECK: LDRQpre $x1, 1 name: test_STRBB body: | bb.0.entry: liveins: $x0, $x1, $w2, $w3 STRBBui $w2, $x0, 0 :: (store (s8)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 STRBBui $w3, $x1, 0 :: (store (s8)) ... # CHECK-LABEL: name: test_STRBB # CHECK: STRBBpost $w2, $x0, 1 # CHECK: STRBBpre $w3, $x1, 1 name: test_STRHH body: | bb.0.entry: liveins: $x0, $x1, $w2, $w3 STRHHui $w2, $x0, 0 :: (store (s16)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 STRHHui $w3, $x1, 0 :: (store (s16)) ... # CHECK-LABEL: name: test_STRHH # CHECK: STRHHpost $w2, $x0, 1 # CHECK: STRHHpre $w3, $x1, 1 name: test_STRW body: | bb.0.entry: liveins: $x0, $x1, $w2, $w3 STRWui $w2, $x0, 0 :: (store (s32)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 STRWui $w3, $x1, 0 :: (store (s32)) ... # CHECK-LABEL: name: test_STRW # CHECK: STRWpost $w2, $x0, 1 # CHECK: STRWpre $w3, $x1, 1 name: test_STRX body: | bb.0.entry: liveins: $x0, $x1, $x2, $x3 STRXui $x2, $x0, 0 :: (store (s64)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 STRXui $x3, $x1, 0 :: (store (s64)) ... # CHECK-LABEL: name: test_STRX # CHECK: STRXpost $x2, $x0, 1 # CHECK: STRXpre $x3, $x1, 1 name: test_STRB body: | bb.0.entry: liveins: $x0, $x1, $b0, $b1 STRBui $b0, $x0, 0 :: (store (s8)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 STRBui $b1, $x1, 0 :: (store (s8)) ... # CHECK-LABEL: name: test_STRB # CHECK: STRBpost $b0, $x0, 1 # CHECK: STRBpre $b1, $x1, 1 name: test_STRH body: | bb.0.entry: liveins: $x0, $x1, $h0, $h1 STRHui $h0, $x0, 0 :: (store (s16)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 STRHui $h1, $x1, 0 :: (store (s16)) ... # CHECK-LABEL: name: test_STRH # CHECK: STRHpost $h0, $x0, 1 # CHECK: STRHpre $h1, $x1, 1 name: test_STRS body: | bb.0.entry: liveins: $x0, $x1, $s0, $s1 STRSui $s0, $x0, 0 :: (store (s32)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 STRSui $s1, $x1, 0 :: (store (s32)) ... # CHECK-LABEL: name: test_STRS # CHECK: STRSpost $s0, $x0, 1 # CHECK: STRSpre $s1, $x1, 1 name: test_STRD body: | bb.0.entry: liveins: $x0, $x1, $d0, $d1 STRDui $d0, $x0, 0 :: (store (s64)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 STRDui $d1, $x1, 0 :: (store (s64)) ... # CHECK-LABEL: name: test_STRD # CHECK: STRDpost $d0, $x0, 1 # CHECK: STRDpre $d1, $x1, 1 name: test_STRQ body: | bb.0.entry: liveins: $x0, $x1, $q0, $q1 STRQui $q0, $x0, 0 :: (store (s128)) $x0 = ADDXri $x0, 1, 0 $x1 = ADDXri $x1, 1, 0 STRQui $q1, $x1, 0 :: (store (s128)) ... # CHECK-LABEL: name: test_STRQ # CHECK: STRQpost $q0, $x0, 1 # CHECK: STRQpre $q1, $x1, 1