Index: lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp =================================================================== --- lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -897,9 +897,13 @@ case AArch64::MOVi64imm: return expandMOVImm(MBB, MBBI, 64); case AArch64::RET_ReallyLR: { + // Hiding the LR use with RET_ReallyLR may lead to extra kills in the + // function and missing live-ins. We are fine in practice because LSR + // handling ensures the register value is restored before RET, but we have + // need the undef flag here to appease the MachineVerifier liveness checks. MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::RET)) - .addReg(AArch64::LR); + .addReg(AArch64::LR, RegState::Undef); transferImpOps(MI, MIB, MIB); MI.eraseFromParent(); return true; Index: lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp =================================================================== --- lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp +++ lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp @@ -767,6 +767,7 @@ // Remove the load, if the destination register of the loads is the same // register for stored value. if (StRt == LdRt && LoadSize == 8) { + StoreI->clearRegisterKills(StRt, TRI); DEBUG(dbgs() << "Remove load instruction:\n "); DEBUG(LoadI->print(dbgs())); DEBUG(dbgs() << "\n"); @@ -831,6 +832,8 @@ .addImm(Imms); } } + StoreI->clearRegisterKills(StRt, TRI); + (void)BitExtMI; DEBUG(dbgs() << "Promoting load by replacing :\n "); Index: lib/Target/AArch64/AArch64RegisterInfo.h =================================================================== --- lib/Target/AArch64/AArch64RegisterInfo.h +++ lib/Target/AArch64/AArch64RegisterInfo.h @@ -95,6 +95,10 @@ unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override; + + bool trackLivenessAfterRegAlloc(const MachineFunction&) const override { + return true; + } }; } // end namespace llvm Index: test/CodeGen/AArch64/ldst-opt-dbg-limit.mir =================================================================== --- test/CodeGen/AArch64/ldst-opt-dbg-limit.mir +++ test/CodeGen/AArch64/ldst-opt-dbg-limit.mir @@ -28,7 +28,7 @@ name: promote-load-from-store alignment: 2 exposesReturnsTwice: false -tracksRegLiveness: false +tracksRegLiveness: true liveins: - { reg: '%x0' } - { reg: '%w1' } @@ -48,7 +48,7 @@ hasMustTailInVarArgFunc: false body: | bb.0 (%ir-block.0): - liveins: %w1, %x0 + liveins: %w1, %x0, %lr STRWui killed %w1, %x0, 0 :: (store 4 into %ir.dst) CFI_INSTRUCTION 0 @@ -76,13 +76,13 @@ ... # CHECK-LABEL: name: promote-load-from-store -# CHECK: STRWui killed %w1 +# CHECK: STRWui %w1 # CHECK: UBFMWri %w1 --- name: store-pair alignment: 2 exposesReturnsTwice: false -tracksRegLiveness: false +tracksRegLiveness: true liveins: - { reg: '%x0' } - { reg: '%w1' } @@ -102,7 +102,7 @@ hasMustTailInVarArgFunc: false body: | bb.0 (%ir-block.0): - liveins: %w1, %x0 + liveins: %w1, %x0, %lr STRWui %w1, %x0, 0 :: (store 4 into %ir.dst01) CFI_INSTRUCTION 0 @@ -125,7 +125,7 @@ CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 - STRWui killed %w1, killed %x0, 1 :: (store 4 into %ir.dst1) + STRWui %w1, %x0, 1 :: (store 4 into %ir.dst1) RET %lr ... Index: test/CodeGen/AArch64/loh.mir =================================================================== --- test/CodeGen/AArch64/loh.mir +++ test/CodeGen/AArch64/loh.mir @@ -18,6 +18,7 @@ # CHECK-LABEL: ********** AArch64 Collect LOH ********** # CHECK-LABEL: Looking in function func0 name: func0 +tracksRegLiveness: true body: | bb.0: ; CHECK: Adding MCLOH_AdrpAdrp: @@ -43,7 +44,7 @@ ; CHECK-NEXT: %X1 = ADRP ; CHECK-NEXT: %X1 = ADDXri %X1, %x1 = ADRP target-flags(aarch64-page) @g0 - %x9 = SUBXri %x11, 5, 0 ; should not affect MCLOH formation + %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 @@ -53,19 +54,20 @@ ; CHECK-NOT: MCLOH_AdrpAdd %x9 = ADRP target-flags(aarch64-page) @g0 BL @extfunc, csr_aarch64_aapcs ; clobbers x9 - %x9 = ADDXri %x9, target-flags(aarch64-pageoff) @g0, 0 + ; Liveness verification forces me to use 'undef' in front of %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 dead %x10 ; clobbers x10 + 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 dead %x10 ; clobbers x10 + 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 @@ -95,9 +97,10 @@ bb.7: ; CHECK-NOT: Adding MCLOH_AdrpLdrGot: - ; This sequence makes no sense and should not produce a LdrGot + ; 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 %x4, target-flags(aarch64-pageoff, aarch64-got) @g5 + %s11 = LDRSui %x11, target-flags(aarch64-pageoff, aarch64-got) @g5 bb.8: ; CHECK-NEXT: Adding MCLOH_AdrpAddLdr: @@ -118,15 +121,15 @@ ; CHECK-NEXT: Adding MCLOH_AdrpAddStr: ; CHECK-NEXT: %X1 = ADRP ; CHECK-NEXT: %X1 = ADDXri %X1, - ; CHECK-NEXT: STRXui %X2, %X1, 16 + ; CHECK-NEXT: STRXui %XZR, %X1, 16 %x1 = ADRP target-flags(aarch64-page) @g3 %x1 = ADDXri %x1, target-flags(aarch64-pageoff) @g3, 0 - STRXui %x2, %x1, 16 + 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, %x11, 16 + STRXui %x2, undef %x11, 16 ; This sequence should just produce an AdrpAdd (not AdrpAddStr) %x3 = ADRP target-flags(aarch64-page) @g3 @@ -156,21 +159,20 @@ ; CHECK-NEXT: Adding MCLOH_AdrpLdrGotStr: ; CHECK-NEXT: %X1 = ADRP ; CHECK-NEXT: %X1 = LDRXui %X1, - ; CHECK-NEXT: STRXui %X4, %X1, 32 + ; 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 %x4, %x1, 32 + 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 %x11, %x5, 32 + STRXui undef %x11, %x5, 32 bb.12: successors: %bb.13 ; Cannot produce a LOH for multiple users ; CHECK-NOT: MCLOH_AdrpAdd %x10 = ADRP target-flags(aarch64-page) @g0 - HINT 0, implicit def dead %x10 ; clobbers x10 %x11 = ADDXri %x10, target-flags(aarch64-pageoff) @g0, 0 B %bb.13 Index: test/CodeGen/AArch64/movimm-wzr.mir =================================================================== --- test/CodeGen/AArch64/movimm-wzr.mir +++ test/CodeGen/AArch64/movimm-wzr.mir @@ -39,4 +39,4 @@ ... # CHECK: bb.0 -# CHECK-NEXT: RET %lr +# CHECK-NEXT: RET undef %lr