CVE-2024-7883
authorLLVM Packaging Team <pkg-llvm-team@lists.alioth.debian.org>
Thu, 25 Dec 2025 16:38:13 +0000 (17:38 +0100)
committerSylvestre Ledru <sylvestre@debian.org>
Thu, 25 Dec 2025 16:38:13 +0000 (17:38 +0100)
Gbp-Pq: Name CVE-2024-7883.diff

llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
llvm/test/CodeGen/ARM/cmse-clear-float-hard.ll
llvm/test/CodeGen/ARM/cmse-vlldm-no-reorder.mir

index df10613fcc7c9319c97fcca9adb2027eddc46f3e..71c0aa55afcf722b57692001f384ab2937f9ef15 100644 (file)
@@ -1426,6 +1426,7 @@ void ARMExpandPseudo::CMSESaveClearFPRegsV8(
   // Use ScratchRegs to store the fp regs
   std::vector<std::tuple<unsigned, unsigned, unsigned>> ClearedFPRegs;
   std::vector<unsigned> NonclearedFPRegs;
+  bool ReturnsFPReg = false;
   for (const MachineOperand &Op : MBBI->operands()) {
     if (Op.isReg() && Op.isUse()) {
       Register Reg = Op.getReg();
@@ -1460,14 +1461,51 @@ void ARMExpandPseudo::CMSESaveClearFPRegsV8(
           NonclearedFPRegs.push_back(Reg);
         }
       }
+    } else if (Op.isReg() && Op.isDef()) {
+      Register Reg = Op.getReg();
+      if (ARM::SPRRegClass.contains(Reg) || ARM::DPRRegClass.contains(Reg) ||
+          ARM::QPRRegClass.contains(Reg))
+        ReturnsFPReg = true;
     }
   }
 
-  bool passesFPReg = (!NonclearedFPRegs.empty() || !ClearedFPRegs.empty());
+  bool PassesFPReg = (!NonclearedFPRegs.empty() || !ClearedFPRegs.empty());
 
-  if (passesFPReg)
+  if (PassesFPReg || ReturnsFPReg)
     assert(STI->hasFPRegs() && "Subtarget needs fpregs");
 
+  // CVE-2024-7883
+  //
+  // The VLLDM/VLSTM instructions set up lazy state preservation, but they
+  // execute as NOPs if the FP register file is not considered to contain
+  // secure data, represented by the CONTROL_S.SFPA bit. This means that the
+  // state of CONTROL_S.SFPA must be the same when these two instructions are
+  // executed. That might not be the case if we haven't used any FP
+  // instructions before the VLSTM, so CONTROL_S.SFPA is clear, but do have one
+  // before the VLLDM, which sets it..
+  //
+  // If we can't prove that SFPA will be the same for the VLSTM and VLLDM, we
+  // execute a "vmov s0, s0" instruction before the VLSTM to ensure that
+  // CONTROL_S.SFPA is set for both.
+  //
+  // That can only happen for callees which take no FP arguments (or we'd have
+  // inserted a VMOV above) and which return values in FP regs (so that we need
+  // to use a VMOV to back-up the return value before the VLLDM). It also can't
+  // happen if the call is dominated by other existing floating-point
+  // instructions, but we don't currently check for that case.
+  //
+  // These conditions mean that we only emit this instruction when using the
+  // hard-float ABI, which means we can assume that FP instructions are
+  // available, and don't need to make it conditional like we do for the
+  // CVE-2021-35465 workaround.
+  if (ReturnsFPReg && !PassesFPReg) {
+    bool S0Dead = !LiveRegs.contains(ARM::S0);
+    BuildMI(MBB, MBBI, DL, TII->get(ARM::VMOVS))
+        .addReg(ARM::S0, RegState::Define | getDeadRegState(S0Dead))
+        .addReg(ARM::S0, getUndefRegState(S0Dead))
+        .add(predOps(ARMCC::AL));
+  }
+
   // Lazy store all fp registers to the stack.
   // This executes as NOP in the absence of floating-point support.
   MachineInstrBuilder VLSTM =
@@ -1528,7 +1566,7 @@ void ARMExpandPseudo::CMSESaveClearFPRegsV8(
   }
   // restore FPSCR from stack and clear bits 0-4, 7, 28-31
   // The other bits are program global according to the AAPCS
-  if (passesFPReg) {
+  if (PassesFPReg) {
     BuildMI(MBB, MBBI, DL, TII->get(ARM::tLDRspi), SpareReg)
         .addReg(ARM::SP)
         .addImm(0x10)
index 606859db0a0ea8eb3aff7c2ae0470a7e342cdd0a..f97fc51a0c4575057ed9448675cb05822ea37b2b 100644 (file)
@@ -187,7 +187,7 @@ define float @f2(ptr nocapture %fptr) #2 {
 ; CHECK-8M-NEXT:    bic r0, r0, #1
 ; CHECK-8M-NEXT:    sub sp, #136
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlstm sp
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    ldr r1, [sp, #64]
 ; CHECK-8M-NEXT:    bic r1, r1, #159
@@ -207,7 +207,7 @@ define float @f2(ptr nocapture %fptr) #2 {
 ; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-NEXT:    blxns r0
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlldm sp
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    add sp, #136
 ; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -245,7 +245,7 @@ define double @d2(ptr nocapture %fptr) #2 {
 ; CHECK-8M-LE-NEXT:    bic r0, r0, #1
 ; CHECK-8M-LE-NEXT:    sub sp, #136
 ; CHECK-8M-LE-NEXT:    vmov r11, r12, d0
-; CHECK-8M-LE-NEXT:    vlstm sp
+; CHECK-8M-LE-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-LE-NEXT:    vmov d0, r11, r12
 ; CHECK-8M-LE-NEXT:    ldr r1, [sp, #64]
 ; CHECK-8M-LE-NEXT:    bic r1, r1, #159
@@ -264,7 +264,7 @@ define double @d2(ptr nocapture %fptr) #2 {
 ; CHECK-8M-LE-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-LE-NEXT:    blxns r0
 ; CHECK-8M-LE-NEXT:    vmov r11, r12, d0
-; CHECK-8M-LE-NEXT:    vlldm sp
+; CHECK-8M-LE-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-LE-NEXT:    vmov d0, r11, r12
 ; CHECK-8M-LE-NEXT:    add sp, #136
 ; CHECK-8M-LE-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -283,7 +283,7 @@ define double @d2(ptr nocapture %fptr) #2 {
 ; CHECK-8M-BE-NEXT:    bic r0, r0, #1
 ; CHECK-8M-BE-NEXT:    sub sp, #136
 ; CHECK-8M-BE-NEXT:    vmov r11, r12, d0
-; CHECK-8M-BE-NEXT:    vlstm sp
+; CHECK-8M-BE-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-BE-NEXT:    vmov d0, r11, r12
 ; CHECK-8M-BE-NEXT:    ldr r1, [sp, #64]
 ; CHECK-8M-BE-NEXT:    bic r1, r1, #159
@@ -302,7 +302,7 @@ define double @d2(ptr nocapture %fptr) #2 {
 ; CHECK-8M-BE-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-BE-NEXT:    blxns r0
 ; CHECK-8M-BE-NEXT:    vmov r11, r12, d0
-; CHECK-8M-BE-NEXT:    vlldm sp
+; CHECK-8M-BE-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-BE-NEXT:    vmov d0, r11, r12
 ; CHECK-8M-BE-NEXT:    add sp, #136
 ; CHECK-8M-BE-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -368,7 +368,7 @@ define float @f3(ptr nocapture %fptr) #4 {
 ; CHECK-8M-NEXT:    bic r0, r0, #1
 ; CHECK-8M-NEXT:    sub sp, #136
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlstm sp
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    ldr r1, [sp, #64]
 ; CHECK-8M-NEXT:    bic r1, r1, #159
@@ -388,7 +388,7 @@ define float @f3(ptr nocapture %fptr) #4 {
 ; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-NEXT:    blxns r0
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlldm sp
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    add sp, #136
 ; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -426,7 +426,7 @@ define double @d3(ptr nocapture %fptr) #4 {
 ; CHECK-8M-LE-NEXT:    bic r0, r0, #1
 ; CHECK-8M-LE-NEXT:    sub sp, #136
 ; CHECK-8M-LE-NEXT:    vmov r11, r12, d0
-; CHECK-8M-LE-NEXT:    vlstm sp
+; CHECK-8M-LE-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-LE-NEXT:    vmov d0, r11, r12
 ; CHECK-8M-LE-NEXT:    ldr r1, [sp, #64]
 ; CHECK-8M-LE-NEXT:    bic r1, r1, #159
@@ -445,7 +445,7 @@ define double @d3(ptr nocapture %fptr) #4 {
 ; CHECK-8M-LE-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-LE-NEXT:    blxns r0
 ; CHECK-8M-LE-NEXT:    vmov r11, r12, d0
-; CHECK-8M-LE-NEXT:    vlldm sp
+; CHECK-8M-LE-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-LE-NEXT:    vmov d0, r11, r12
 ; CHECK-8M-LE-NEXT:    add sp, #136
 ; CHECK-8M-LE-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -464,7 +464,7 @@ define double @d3(ptr nocapture %fptr) #4 {
 ; CHECK-8M-BE-NEXT:    bic r0, r0, #1
 ; CHECK-8M-BE-NEXT:    sub sp, #136
 ; CHECK-8M-BE-NEXT:    vmov r11, r12, d0
-; CHECK-8M-BE-NEXT:    vlstm sp
+; CHECK-8M-BE-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-BE-NEXT:    vmov d0, r11, r12
 ; CHECK-8M-BE-NEXT:    ldr r1, [sp, #64]
 ; CHECK-8M-BE-NEXT:    bic r1, r1, #159
@@ -483,7 +483,7 @@ define double @d3(ptr nocapture %fptr) #4 {
 ; CHECK-8M-BE-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-BE-NEXT:    blxns r0
 ; CHECK-8M-BE-NEXT:    vmov r11, r12, d0
-; CHECK-8M-BE-NEXT:    vlldm sp
+; CHECK-8M-BE-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-BE-NEXT:    vmov d0, r11, r12
 ; CHECK-8M-BE-NEXT:    add sp, #136
 ; CHECK-8M-BE-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -547,8 +547,9 @@ define float @f4(ptr nocapture %fptr) #6 {
 ; CHECK-8M-NEXT:    push.w {r4, r5, r6, r7, r8, r9, r10, r11}
 ; CHECK-8M-NEXT:    bic r0, r0, #1
 ; CHECK-8M-NEXT:    sub sp, #136
-; CHECK-8M-NEXT:    vlstm sp
+; CHECK-8M-NEXT:    vmov.f32 s0, s0
 ; CHECK-8M-NEXT:    mov r1, r0
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    mov r2, r0
 ; CHECK-8M-NEXT:    mov r3, r0
 ; CHECK-8M-NEXT:    mov r4, r0
@@ -563,7 +564,7 @@ define float @f4(ptr nocapture %fptr) #6 {
 ; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-NEXT:    blxns r0
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlldm sp
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    add sp, #136
 ; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -598,8 +599,9 @@ define double @d4(ptr nocapture %fptr) #6 {
 ; CHECK-8M-NEXT:    push.w {r4, r5, r6, r7, r8, r9, r10, r11}
 ; CHECK-8M-NEXT:    bic r0, r0, #1
 ; CHECK-8M-NEXT:    sub sp, #136
-; CHECK-8M-NEXT:    vlstm sp
+; CHECK-8M-NEXT:    vmov.f32 s0, s0
 ; CHECK-8M-NEXT:    mov r1, r0
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    mov r2, r0
 ; CHECK-8M-NEXT:    mov r3, r0
 ; CHECK-8M-NEXT:    mov r4, r0
@@ -614,7 +616,7 @@ define double @d4(ptr nocapture %fptr) #6 {
 ; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-NEXT:    blxns r0
 ; CHECK-8M-NEXT:    vmov r11, r12, d0
-; CHECK-8M-NEXT:    vlldm sp
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov d0, r11, r12
 ; CHECK-8M-NEXT:    add sp, #136
 ; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -649,7 +651,7 @@ define void @fd(ptr %f, float %a, double %b) #8 {
 ; CHECK-8M-NEXT:    vmov r12, s0
 ; CHECK-8M-NEXT:    mov r2, r0
 ; CHECK-8M-NEXT:    vmov r10, r11, d1
-; CHECK-8M-NEXT:    vlstm sp
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    vmov d1, r10, r11
 ; CHECK-8M-NEXT:    ldr r1, [sp, #64]
@@ -666,7 +668,7 @@ define void @fd(ptr %f, float %a, double %b) #8 {
 ; CHECK-8M-NEXT:    mov r9, r0
 ; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-NEXT:    blxns r0
-; CHECK-8M-NEXT:    vlldm sp
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    add sp, #136
 ; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
 ; CHECK-8M-NEXT:    pop {r7, pc}
@@ -708,7 +710,7 @@ define void @fdff(ptr %f, float %a, double %b, float %c, float %d) #8 {
 ; CHECK-8M-NEXT:    vmov r9, s1
 ; CHECK-8M-NEXT:    mov r4, r0
 ; CHECK-8M-NEXT:    vmov r8, s4
-; CHECK-8M-NEXT:    vlstm sp
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    vmov d1, r10, r11
 ; CHECK-8M-NEXT:    vmov s1, r9
@@ -723,7 +725,7 @@ define void @fdff(ptr %f, float %a, double %b, float %c, float %d) #8 {
 ; CHECK-8M-NEXT:    mov r7, r0
 ; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-NEXT:    blxns r0
-; CHECK-8M-NEXT:    vlldm sp
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    add sp, #136
 ; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
 ; CHECK-8M-NEXT:    pop {r7, pc}
@@ -765,7 +767,7 @@ define void @fidififid(ptr %fu, float %a, i32 %b, double %c, i32 %d, float %e, i
 ; CHECK-8M-NEXT:    vmov r8, s1
 ; CHECK-8M-NEXT:    vmov r7, s4
 ; CHECK-8M-NEXT:    vmov r5, r6, d3
-; CHECK-8M-NEXT:    vlstm sp
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r11
 ; CHECK-8M-NEXT:    vmov d1, r9, r10
 ; CHECK-8M-NEXT:    vmov s1, r8
@@ -778,7 +780,7 @@ define void @fidififid(ptr %fu, float %a, i32 %b, double %c, i32 %d, float %e, i
 ; CHECK-8M-NEXT:    mov r4, r12
 ; CHECK-8M-NEXT:    msr apsr_nzcvqg, r12
 ; CHECK-8M-NEXT:    blxns r12
-; CHECK-8M-NEXT:    vlldm sp
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    add sp, #136
 ; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
 ; CHECK-8M-NEXT:    pop {r7, pc}
@@ -897,7 +899,7 @@ define half @h2(ptr nocapture %hptr) nounwind {
 ; CHECK-8M-NEXT:    bic r0, r0, #1
 ; CHECK-8M-NEXT:    sub sp, #136
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlstm sp
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    ldr r1, [sp, #64]
 ; CHECK-8M-NEXT:    bic r1, r1, #159
@@ -917,7 +919,7 @@ define half @h2(ptr nocapture %hptr) nounwind {
 ; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-NEXT:    blxns r0
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlldm sp
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    add sp, #136
 ; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -976,7 +978,7 @@ define half @h3(ptr nocapture %hptr) nounwind {
 ; CHECK-8M-NEXT:    bic r0, r0, #1
 ; CHECK-8M-NEXT:    sub sp, #136
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlstm sp
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    ldr r1, [sp, #64]
 ; CHECK-8M-NEXT:    bic r1, r1, #159
@@ -996,7 +998,7 @@ define half @h3(ptr nocapture %hptr) nounwind {
 ; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-NEXT:    blxns r0
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlldm sp
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    add sp, #136
 ; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -1053,8 +1055,9 @@ define half @h4(ptr nocapture %hptr) nounwind {
 ; CHECK-8M-NEXT:    push.w {r4, r5, r6, r7, r8, r9, r10, r11}
 ; CHECK-8M-NEXT:    bic r0, r0, #1
 ; CHECK-8M-NEXT:    sub sp, #136
-; CHECK-8M-NEXT:    vlstm sp
+; CHECK-8M-NEXT:    vmov.f32 s0, s0
 ; CHECK-8M-NEXT:    mov r1, r0
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    mov r2, r0
 ; CHECK-8M-NEXT:    mov r3, r0
 ; CHECK-8M-NEXT:    mov r4, r0
@@ -1069,7 +1072,7 @@ define half @h4(ptr nocapture %hptr) nounwind {
 ; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-NEXT:    blxns r0
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlldm sp
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    add sp, #136
 ; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -1176,7 +1179,7 @@ define half @h1_arg(ptr nocapture %hptr, half %harg) nounwind {
 ; CHECK-8M-NEXT:    bic r0, r0, #1
 ; CHECK-8M-NEXT:    sub sp, #136
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlstm sp
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    ldr r1, [sp, #64]
 ; CHECK-8M-NEXT:    bic r1, r1, #159
@@ -1196,7 +1199,7 @@ define half @h1_arg(ptr nocapture %hptr, half %harg) nounwind {
 ; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
 ; CHECK-8M-NEXT:    blxns r0
 ; CHECK-8M-NEXT:    vmov r12, s0
-; CHECK-8M-NEXT:    vlldm sp
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
 ; CHECK-8M-NEXT:    vmov s0, r12
 ; CHECK-8M-NEXT:    add sp, #136
 ; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
@@ -1241,3 +1244,100 @@ entry:
   ret half %call
 }
 
+define float @float_return_undef_arg(ptr nocapture %fptr) #6 {
+; CHECK-8M-LABEL: float_return_undef_arg:
+; CHECK-8M:       @ %bb.0: @ %entry
+; CHECK-8M-NEXT:    push {r7, lr}
+; CHECK-8M-NEXT:    push.w {r4, r5, r6, r7, r8, r9, r10, r11}
+; CHECK-8M-NEXT:    bic r0, r0, #1
+; CHECK-8M-NEXT:    sub sp, #136
+; CHECK-8M-NEXT:    vmov.f32 s0, s0
+; CHECK-8M-NEXT:    mov r1, r0
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
+; CHECK-8M-NEXT:    mov r2, r0
+; CHECK-8M-NEXT:    mov r3, r0
+; CHECK-8M-NEXT:    mov r4, r0
+; CHECK-8M-NEXT:    mov r5, r0
+; CHECK-8M-NEXT:    mov r6, r0
+; CHECK-8M-NEXT:    mov r7, r0
+; CHECK-8M-NEXT:    mov r8, r0
+; CHECK-8M-NEXT:    mov r9, r0
+; CHECK-8M-NEXT:    mov r10, r0
+; CHECK-8M-NEXT:    mov r11, r0
+; CHECK-8M-NEXT:    mov r12, r0
+; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
+; CHECK-8M-NEXT:    blxns r0
+; CHECK-8M-NEXT:    vmov r12, s0
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
+; CHECK-8M-NEXT:    vmov s0, r12
+; CHECK-8M-NEXT:    add sp, #136
+; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
+; CHECK-8M-NEXT:    pop {r7, pc}
+;
+; CHECK-81M-LABEL: float_return_undef_arg:
+; CHECK-81M:       @ %bb.0: @ %entry
+; CHECK-81M-NEXT:    push {r7, lr}
+; CHECK-81M-NEXT:    push.w {r4, r5, r6, r7, r8, r9, r10, r11}
+; CHECK-81M-NEXT:    bic r0, r0, #1
+; CHECK-81M-NEXT:    vpush {s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}
+; CHECK-81M-NEXT:    vscclrm {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, vpr}
+; CHECK-81M-NEXT:    vstr fpcxts, [sp, #-8]!
+; CHECK-81M-NEXT:    clrm {r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, apsr}
+; CHECK-81M-NEXT:    blxns r0
+; CHECK-81M-NEXT:    vldr fpcxts, [sp], #8
+; CHECK-81M-NEXT:    vpop {s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}
+; CHECK-81M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
+; CHECK-81M-NEXT:    pop {r7, pc}
+entry:
+  %call = call float %fptr(i32 undef) #7
+  ret float %call
+}
+
+define float @float_return_poison_arg(ptr nocapture %fptr) #6 {
+; CHECK-8M-LABEL: float_return_poison_arg:
+; CHECK-8M:       @ %bb.0: @ %entry
+; CHECK-8M-NEXT:    push {r7, lr}
+; CHECK-8M-NEXT:    push.w {r4, r5, r6, r7, r8, r9, r10, r11}
+; CHECK-8M-NEXT:    bic r0, r0, #1
+; CHECK-8M-NEXT:    sub sp, #136
+; CHECK-8M-NEXT:    vmov.f32 s0, s0
+; CHECK-8M-NEXT:    mov r1, r0
+; CHECK-8M-NEXT:    vlstm sp, {d0 - d15}
+; CHECK-8M-NEXT:    mov r2, r0
+; CHECK-8M-NEXT:    mov r3, r0
+; CHECK-8M-NEXT:    mov r4, r0
+; CHECK-8M-NEXT:    mov r5, r0
+; CHECK-8M-NEXT:    mov r6, r0
+; CHECK-8M-NEXT:    mov r7, r0
+; CHECK-8M-NEXT:    mov r8, r0
+; CHECK-8M-NEXT:    mov r9, r0
+; CHECK-8M-NEXT:    mov r10, r0
+; CHECK-8M-NEXT:    mov r11, r0
+; CHECK-8M-NEXT:    mov r12, r0
+; CHECK-8M-NEXT:    msr apsr_nzcvqg, r0
+; CHECK-8M-NEXT:    blxns r0
+; CHECK-8M-NEXT:    vmov r12, s0
+; CHECK-8M-NEXT:    vlldm sp, {d0 - d15}
+; CHECK-8M-NEXT:    vmov s0, r12
+; CHECK-8M-NEXT:    add sp, #136
+; CHECK-8M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
+; CHECK-8M-NEXT:    pop {r7, pc}
+;
+; CHECK-81M-LABEL: float_return_poison_arg:
+; CHECK-81M:       @ %bb.0: @ %entry
+; CHECK-81M-NEXT:    push {r7, lr}
+; CHECK-81M-NEXT:    push.w {r4, r5, r6, r7, r8, r9, r10, r11}
+; CHECK-81M-NEXT:    bic r0, r0, #1
+; CHECK-81M-NEXT:    vpush {s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}
+; CHECK-81M-NEXT:    vscclrm {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, vpr}
+; CHECK-81M-NEXT:    vstr fpcxts, [sp, #-8]!
+; CHECK-81M-NEXT:    clrm {r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, apsr}
+; CHECK-81M-NEXT:    blxns r0
+; CHECK-81M-NEXT:    vldr fpcxts, [sp], #8
+; CHECK-81M-NEXT:    vpop {s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}
+; CHECK-81M-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
+; CHECK-81M-NEXT:    pop {r7, pc}
+entry:
+  %call = call float %fptr(i32 poison) #7
+  ret float %call
+}
index 3d49fee8fdaf436127bab066a4aa0327b87e0670..29429fd5a23eb1552af72b5d96e753b9b4bf1b44 100644 (file)
@@ -89,6 +89,7 @@ body:             |
 # CHECK: $sp = t2STMDB_UPD $sp, 14 /* CC::al */, $noreg, $r4, $r5, $r6, undef $r7, $r8, $r9, $r10, $r11
 # CHECK-NEXT:  $r0 = t2BICri $r0, 1, 14 /* CC::al */, $noreg, $noreg
 # CHECK-NEXT:  $sp = tSUBspi $sp, 34, 14 /* CC::al */, $noreg
+# CHECK-NEXT:  dead $s0 = VMOVS undef $s0, 14 /* CC::al */, $noreg
 # CHECK-NEXT:  VLSTM $sp, 14 /* CC::al */, $noreg, 0, implicit-def $vpr, implicit-def $fpscr, implicit-def $fpscr_nzcv, implicit undef $vpr, implicit undef $fpscr, implicit undef $fpscr_nzcv, implicit undef $d0, implicit undef $d1, implicit undef $d2, implicit undef $d3, implicit undef $d4, implicit undef $d5, implicit undef $d6, implicit undef $d7, implicit $d8, implicit $d9, implicit $d10, implicit $d11, implicit $d12, implicit $d13, implicit $d14, implicit $d15
 # CHECK-NEXT:  $r1 = tMOVr $r0, 14 /* CC::al */, $noreg
 # CHECK-NEXT:  $r2 = tMOVr $r0, 14 /* CC::al */, $noreg