diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -3621,8 +3621,62 @@ return; } -#ifndef NDEBUG const TargetRegisterInfo &TRI = getRegisterInfo(); + if ((AArch64::FPR128RegClass.contains(DestReg) && + AArch64::FPR64RegClass.contains(SrcReg))) { + DestReg = TRI.getSubReg(DestReg, AArch64::dsub); + BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + + if (AArch64::FPR64RegClass.contains(DestReg) && + AArch64::FPR128RegClass.contains(SrcReg)) { + SrcReg = TRI.getSubReg(SrcReg, AArch64::dsub); + BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + + if ((AArch64::FPR128RegClass.contains(DestReg) || + AArch64::FPR64RegClass.contains(DestReg)) && + AArch64::FPR32RegClass.contains(SrcReg)) { + DestReg = TRI.getSubReg(DestReg, AArch64::ssub); + BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + + if (AArch64::FPR32RegClass.contains(DestReg) && + (AArch64::FPR64RegClass.contains(SrcReg) || + AArch64::FPR128RegClass.contains(SrcReg))) { + SrcReg = TRI.getSubReg(SrcReg, AArch64::ssub); + BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + + if ((AArch64::FPR128RegClass.contains(DestReg) || + AArch64::FPR64RegClass.contains(DestReg) || + AArch64::FPR32RegClass.contains(DestReg)) && + AArch64::FPR16RegClass.contains(SrcReg)) { + DestReg = TRI.getSubReg(DestReg, AArch64::hsub); + BuildMI(MBB, I, DL, get(AArch64::FMOVHr), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + + if (AArch64::FPR16RegClass.contains(DestReg) && + (AArch64::FPR32RegClass.contains(SrcReg) || + AArch64::FPR64RegClass.contains(SrcReg) || + AArch64::FPR128RegClass.contains(SrcReg))) { + SrcReg = TRI.getSubReg(SrcReg, AArch64::hsub); + BuildMI(MBB, I, DL, get(AArch64::FMOVHr), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + +#ifndef NDEBUG errs() << TRI.getRegAsmName(DestReg) << " = COPY " << TRI.getRegAsmName(SrcReg) << "\n"; #endif diff --git a/llvm/test/CodeGen/AArch64/postrapseudos-fmov-fp-subreg.mir b/llvm/test/CodeGen/AArch64/postrapseudos-fmov-fp-subreg.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/postrapseudos-fmov-fp-subreg.mir @@ -0,0 +1,206 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc %s -run-pass=postrapseudos -mtriple=arm64-apple-ios -o - | FileCheck %s + +... +--- +name: fmov_q0_s0 +tracksRegLiveness: true +liveins: + - { reg: '$s0' } +body: | + bb.0: + liveins: $s0 + + ; CHECK-LABEL: name: fmov_q0_s0 + ; CHECK: liveins: $s0 + ; CHECK: $s0 = FMOVSr $s0, implicit killed $d0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $q0 = COPY renamable $s0, implicit killed $d0, implicit-def $q0 + RET_ReallyLR + +... +--- +name: fmov_d0_s0 +tracksRegLiveness: true +liveins: + - { reg: '$s0' } +body: | + bb.0: + liveins: $s0 + + ; CHECK-LABEL: name: fmov_d0_s0 + ; CHECK: liveins: $s0 + ; CHECK: $s0 = FMOVSr $s0, implicit killed $d0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $d0 = COPY renamable $s0, implicit killed $d0, implicit-def $q0 + RET_ReallyLR + +... +--- +name: fmov_h0_s0 +tracksRegLiveness: true +liveins: + - { reg: '$s0' } +body: | + bb.0: + liveins: $s0 + + ; CHECK-LABEL: name: fmov_h0_s0 + ; CHECK: liveins: $s0 + ; CHECK: $h0 = FMOVHr $h0, implicit killed $d0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $h0 = COPY renamable $s0, implicit killed $d0, implicit-def $q0 + RET_ReallyLR + +... +--- +name: fmov_q0_h0 +tracksRegLiveness: true +liveins: + - { reg: '$h0' } +body: | + bb.0: + liveins: $h0 + + ; CHECK-LABEL: name: fmov_q0_h0 + ; CHECK: liveins: $h0 + ; CHECK: $h0 = FMOVHr $h0, implicit killed $d0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $q0 = COPY renamable $h0, implicit killed $d0, implicit-def $q0 + RET_ReallyLR + +... +--- +name: fmov_d0_h0 +tracksRegLiveness: true +liveins: + - { reg: '$h0' } +body: | + bb.0: + liveins: $h0 + + ; CHECK-LABEL: name: fmov_d0_h0 + ; CHECK: liveins: $h0 + ; CHECK: $h0 = FMOVHr $h0, implicit killed $d0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $d0 = COPY renamable $h0, implicit killed $d0, implicit-def $q0 + RET_ReallyLR + +... +--- +name: fmov_s0_h0 +tracksRegLiveness: true +liveins: + - { reg: '$h0' } +body: | + bb.0: + liveins: $h0 + + ; CHECK-LABEL: name: fmov_s0_h0 + ; CHECK: liveins: $h0 + ; CHECK: $h0 = FMOVHr $h0, implicit killed $s0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $s0 = COPY renamable $h0, implicit killed $s0, implicit-def $q0 + RET_ReallyLR + +... +--- +name: fmov_q0_d0 +tracksRegLiveness: true +liveins: + - { reg: '$d0' } +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: fmov_q0_d0 + ; CHECK: liveins: $d0 + ; CHECK: $d0 = FMOVDr $d0, implicit killed $d0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $q0 = COPY renamable $d0, implicit killed $d0, implicit-def $q0 + RET_ReallyLR + +... +--- +name: fmov_h0_d0 +tracksRegLiveness: true +liveins: + - { reg: '$d0' } +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: fmov_h0_d0 + ; CHECK: liveins: $d0 + ; CHECK: $h0 = FMOVHr $h0, implicit killed $d0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $h0 = COPY renamable $d0, implicit killed $d0, implicit-def $q0 + RET_ReallyLR + +... +--- +name: fmov_s0_d0 +tracksRegLiveness: true +liveins: + - { reg: '$d0' } +body: | + bb.0: + liveins: $d0 + + ; CHECK-LABEL: name: fmov_s0_d0 + ; CHECK: liveins: $d0 + ; CHECK: $s0 = FMOVSr $s0, implicit killed $d0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $s0 = COPY renamable $d0, implicit killed $d0, implicit-def $q0 + RET_ReallyLR + +... +--- +name: fmov_d0_q0 +tracksRegLiveness: true +liveins: + - { reg: '$q0' } +body: | + bb.0: + liveins: $q0 + + ; CHECK-LABEL: name: fmov_d0_q0 + ; CHECK: liveins: $q0 + ; CHECK: $d0 = FMOVDr $d0, implicit killed $d0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $d0 = COPY renamable $q0, implicit killed $d0, implicit-def $q0 + RET_ReallyLR + +... +--- +name: fmov_h0_q0 +tracksRegLiveness: true +liveins: + - { reg: '$q0' } +body: | + bb.0: + liveins: $q0 + + ; CHECK-LABEL: name: fmov_h0_q0 + ; CHECK: liveins: $q0 + ; CHECK: $h0 = FMOVHr $h0, implicit killed $d0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $h0 = COPY renamable $q0, implicit killed $d0, implicit-def $q0 + RET_ReallyLR + +... +--- +name: fmov_s0_q0 +tracksRegLiveness: true +liveins: + - { reg: '$q0' } +body: | + bb.0: + liveins: $q0 + + ; CHECK-LABEL: name: fmov_s0_q0 + ; CHECK: liveins: $q0 + ; CHECK: $s0 = FMOVSr $s0, implicit killed $d0, implicit-def $q0 + ; CHECK: RET_ReallyLR + renamable $s0 = COPY renamable $q0, implicit killed $d0, implicit-def $q0 + RET_ReallyLR