# RUN: llc -o /dev/null %s -mtriple=aarch64-apple-ios -run-pass=aarch64-collect-loh -debug-only=aarch64-collect-loh 2>&1 | FileCheck %s # RUN: llc -debugify-and-strip-all-safe -o /dev/null %s -mtriple=aarch64-apple-ios -run-pass=aarch64-collect-loh -debug-only=aarch64-collect-loh 2>&1 | FileCheck %s # REQUIRES: asserts --- | define void @func0() { ret void } declare void @extfunc() @g0 = external global i32 @g1 = external global i32 @g2 = external global i32 @g3 = external global i32 @g4 = external global i32 @g5 = external global i32 ... --- # Check various LOH variants. Remember that the algorithms walks the basic # blocks backwards. # CHECK-LABEL: ********** AArch64 Collect LOH ********** # CHECK-LABEL: Looking in function func0 name: func0 tracksRegLiveness: true body: | bb.0: ; CHECK: Adding MCLOH_AdrpAdrp: ; CHECK-NEXT: $x1 = ADRP target-flags(aarch64-page) @g3 ; CHECK-NEXT: $x1 = ADRP target-flags(aarch64-page) @g4 ; CHECK-NEXT: Adding MCLOH_AdrpAdrp: ; CHECK-NEXT: $x1 = ADRP target-flags(aarch64-page) @g2 ; CHECK-NEXT: $x1 = ADRP target-flags(aarch64-page) @g3 ; CHECK-NEXT: Adding MCLOH_AdrpAdrp: ; CHECK-NEXT: $x0 = ADRP target-flags(aarch64-page) @g0 ; CHECK-NEXT: $x0 = ADRP target-flags(aarch64-page) @g1 $x0 = ADRP target-flags(aarch64-page) @g0 $x0 = ADRP target-flags(aarch64-page) @g1 $x1 = ADRP target-flags(aarch64-page) @g2 $x1 = ADRP target-flags(aarch64-page) @g3 $x1 = ADRP target-flags(aarch64-page) @g4 bb.1: ; CHECK-NEXT: Adding MCLOH_AdrpAdd: ; CHECK-NEXT: $x20 = ADRP target-flags(aarch64-page) @g0 ; CHECK-NEXT: $x3 = ADDXri $x20, target-flags(aarch64-pageoff) @g0 ; CHECK-NEXT: Adding MCLOH_AdrpAdd: ; CHECK-NEXT: $x1 = ADRP target-flags(aarch64-page) @g0 ; CHECK-NEXT: $x1 = ADDXri $x1, target-flags(aarch64-pageoff) @g0 $x1 = ADRP target-flags(aarch64-page) @g0 $x9 = SUBXri undef $x11, 5, 0 ; should not affect MCLOH formation $x1 = ADDXri $x1, target-flags(aarch64-pageoff) @g0, 0 $x20 = ADRP target-flags(aarch64-page) @g0 BL @extfunc, csr_aarch64_aapcs ; should not clobber X20 $x3 = ADDXri $x20, target-flags(aarch64-pageoff) @g0, 0 bb.2: ; CHECK-NOT: MCLOH_AdrpAdd $x9 = ADRP target-flags(aarch64-page) @g0 BL @extfunc, csr_aarch64_aapcs ; clobbers x9 ; Verification requires the use of 'undef' in front of the clobbered $x9 $x9 = ADDXri undef $x9, target-flags(aarch64-pageoff) @g0, 0 bb.3: ; CHECK-NOT: MCLOH_AdrpAdd $x10 = ADRP target-flags(aarch64-page) @g0 HINT 0, implicit def $x10 ; clobbers x10 $x10 = ADDXri $x10, target-flags(aarch64-pageoff) @g0, 0 bb.4: ; Cannot produce a LOH for multiple users ; CHECK-NOT: MCLOH_AdrpAdd $x10 = ADRP target-flags(aarch64-page) @g0 HINT 0, implicit def $x10 ; clobbers x10 $x11 = ADDXri $x10, target-flags(aarch64-pageoff) @g0, 0 $x12 = ADDXri $x10, target-flags(aarch64-pageoff) @g0, 0 bb.5: ; CHECK-NEXT: Adding MCLOH_AdrpLdr: ; CHECK-NEXT: $x5 = ADRP target-flags(aarch64-page) @g2 ; CHECK-NEXT: $s6 = LDRSui $x5, target-flags(aarch64-pageoff) @g2 ; CHECK-NEXT: Adding MCLOH_AdrpLdr: ; CHECK-NEXT: $x4 = ADRP target-flags(aarch64-page) @g2 ; CHECK-NEXT: $x4 = LDRXui $x4, target-flags(aarch64-pageoff) @g2 $x4 = ADRP target-flags(aarch64-page) @g2 $x4 = LDRXui $x4, target-flags(aarch64-pageoff) @g2 $x5 = ADRP target-flags(aarch64-page) @g2 $s6 = LDRSui $x5, target-flags(aarch64-pageoff) @g2 bb.6: ; CHECK-NEXT: Adding MCLOH_AdrpLdrGot: ; CHECK-NEXT: $x5 = ADRP target-flags(aarch64-page, aarch64-got) @g2 ; CHECK-NEXT: $x6 = LDRXui $x5, target-flags(aarch64-pageoff, aarch64-got) @g2 ; CHECK-NEXT: Adding MCLOH_AdrpLdrGot: ; CHECK-NEXT: $x4 = ADRP target-flags(aarch64-page, aarch64-got) @g2 ; CHECK-NEXT: $x4 = LDRXui $x4, target-flags(aarch64-pageoff, aarch64-got) @g2 $x4 = ADRP target-flags(aarch64-page, aarch64-got) @g2 $x4 = LDRXui $x4, target-flags(aarch64-pageoff, aarch64-got) @g2 $x5 = ADRP target-flags(aarch64-page, aarch64-got) @g2 $x6 = LDRXui $x5, target-flags(aarch64-pageoff, aarch64-got) @g2 bb.7: ; CHECK-NOT: Adding MCLOH_AdrpLdrGot: ; Loading a float value from a GOT table makes no sense so this should not ; produce an LOH. $x11 = ADRP target-flags(aarch64-page, aarch64-got) @g5 $s11 = LDRSui $x11, target-flags(aarch64-pageoff, aarch64-got) @g5 bb.8: ; CHECK-NEXT: Adding MCLOH_AdrpAddLdr: ; CHECK-NEXT: $x7 = ADRP target-flags(aarch64-page) @g3 ; CHECK-NEXT: $x8 = ADDXri $x7, target-flags(aarch64-pageoff) @g3 ; CHECK-NEXT: $d1 = LDRDui $x8, 8 $x7 = ADRP target-flags(aarch64-page) @g3 $x8 = ADDXri $x7, target-flags(aarch64-pageoff) @g3, 0 $d1 = LDRDui $x8, 8 bb.9: ; CHECK-NEXT: Adding MCLOH_AdrpAdd: ; CHECK-NEXT: $x3 = ADRP target-flags(aarch64-page) @g3 ; CHECK-NEXT: $x3 = ADDXri $x3, target-flags(aarch64-pageoff) @g3 ; CHECK-NEXT: Adding MCLOH_AdrpAdd: ; CHECK-NEXT: $x5 = ADRP target-flags(aarch64-page) @g3 ; CHECK-NEXT: $x2 = ADDXri $x5, target-flags(aarch64-pageoff) @g3 ; CHECK-NEXT: Adding MCLOH_AdrpAddStr: ; CHECK-NEXT: $x1 = ADRP target-flags(aarch64-page) @g3 ; CHECK-NEXT: $x1 = ADDXri $x1, target-flags(aarch64-pageoff) @g3 ; CHECK-NEXT: STRXui $xzr, $x1, 16 $x1 = ADRP target-flags(aarch64-page) @g3 $x1 = ADDXri $x1, target-flags(aarch64-pageoff) @g3, 0 STRXui $xzr, $x1, 16 ; This sequence should just produce an AdrpAdd (not AdrpAddStr) $x5 = ADRP target-flags(aarch64-page) @g3 $x2 = ADDXri $x5, target-flags(aarch64-pageoff) @g3, 0 STRXui $x2, undef $x11, 16 ; This sequence should just produce an AdrpAdd (not AdrpAddStr) $x3 = ADRP target-flags(aarch64-page) @g3 $x3 = ADDXri $x3, target-flags(aarch64-pageoff) @g3, 0 STRXui $x3, $x3, 16 bb.10: ; CHECK-NEXT: Adding MCLOH_AdrpLdr: ; CHECK-NEXT: $x2 = ADRP target-flags(aarch64-page) @g3 ; CHECK-NEXT: $x2 = LDRXui $x2, target-flags(aarch64-pageoff) @g3 ; CHECK-NEXT: Adding MCLOH_AdrpLdrGotLdr: ; CHECK-NEXT: $x1 = ADRP target-flags(aarch64-page, aarch64-got) @g4 ; CHECK-NEXT: $x1 = LDRXui $x1, target-flags(aarch64-pageoff, aarch64-got) @g4 ; CHECK-NEXT: $x1 = LDRXui $x1, 24 $x1 = ADRP target-flags(aarch64-page, aarch64-got) @g4 $x1 = LDRXui $x1, target-flags(aarch64-pageoff, aarch64-got) @g4 $x1 = LDRXui $x1, 24 ; Should just produce a MCLOH_AdrpLdr (not MCLOH_AdrpLdrGotLdr) $x2 = ADRP target-flags(aarch64-page) @g3 $x2 = LDRXui $x2, target-flags(aarch64-pageoff) @g3 $x2 = LDRXui $x2, 24 bb.11: ; CHECK-NEXT: Adding MCLOH_AdrpLdr ; CHECK-NEXT: $x5 = ADRP target-flags(aarch64-page) @g1 ; CHECK-NEXT: $x5 = LDRXui $x5, target-flags(aarch64-pageoff) @g1 ; CHECK-NEXT: Adding MCLOH_AdrpLdrGotStr: ; CHECK-NEXT: $x1 = ADRP target-flags(aarch64-page, aarch64-got) @g4 ; CHECK-NEXT: $x1 = LDRXui $x1, target-flags(aarch64-pageoff, aarch64-got) @g4 ; CHECK-NEXT: STRXui $xzr, $x1, 32 $x1 = ADRP target-flags(aarch64-page, aarch64-got) @g4 $x1 = LDRXui $x1, target-flags(aarch64-pageoff, aarch64-got) @g4 STRXui $xzr, $x1, 32 ; Should just produce a MCLOH_AdrpLdr (not MCLOH_AdrpLdrGotStr) $x5 = ADRP target-flags(aarch64-page) @g1 $x5 = LDRXui $x5, target-flags(aarch64-pageoff) @g1 STRXui undef $x11, $x5, 32 bb.12: ; CHECK-NOT: MCLOH_AdrpAdrp ; CHECK: Adding MCLOH_AdrpAddLdr ; $x9 = ADRP @g4 ; $x9 = ADDXri $x9, @g4 ; $x5 = LDRXui $x9, 0 $x9 = ADRP target-flags(aarch64-page, aarch64-got) @g4 $x9 = ADDXri $x9, target-flags(aarch64-pageoff, aarch64-got) @g4, 0 $x5 = LDRXui $x9, 0 $x9 = ADRP target-flags(aarch64-page, aarch64-got) @g5 bb.13: ; Cannot produce a LOH for multiple users ; CHECK-NOT: MCLOH_AdrpAdd $x10 = ADRP target-flags(aarch64-page) @g0 $x11 = ADDXri $x10, target-flags(aarch64-pageoff) @g0, 0 B %bb.14 bb.14: liveins: $x10 $x12 = ADDXri $x10, target-flags(aarch64-pageoff) @g0, 0 bb.15: ; Should not produce a LOH when reg is clobbered by bundled regmask ; CHECK-NOT: MCLOH_AdrpAdrp $x8 = ADRP target-flags(aarch64-page) @g0 BUNDLE { BL @extfunc, csr_aarch64_aapcs } $x8 = ADRP target-flags(aarch64-page) @g1 ...