Index: lib/CodeGen/ShrinkWrap.cpp =================================================================== --- lib/CodeGen/ShrinkWrap.cpp +++ lib/CodeGen/ShrinkWrap.cpp @@ -264,6 +264,14 @@ LLVM_DEBUG(dbgs() << "Frame instruction: " << MI << '\n'); return true; } + + if (MI.isPseudo() && !MI.isMetaInstruction() + && MI.getFlag(MachineInstr::FrameSetup)) { + LLVM_DEBUG(dbgs() << "Pseudo-instruction which uses stack: " + << MI << '\n'); + return true; + } + for (const MachineOperand &MO : MI.operands()) { bool UseOrDefCSR = false; if (MO.isReg()) { Index: lib/Target/Mips/MipsSEFrameLowering.cpp =================================================================== --- lib/Target/Mips/MipsSEFrameLowering.cpp +++ lib/Target/Mips/MipsSEFrameLowering.cpp @@ -299,8 +299,11 @@ // register). Unfortunately, we have to make this decision before register // allocation so for now we use a spill/reload sequence for all // double-precision values in regardless of being an odd/even register. - if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || - (FP64 && !Subtarget.useOddSPReg())) { + // + // For the cases that should be covered here MipsSEISelDAGToDAG adds + // FrameSetup flag, so other passes (like ShrinkWrapping) are aware that stack + // is used. + if (I->getFlag(MachineInstr::FrameSetup)) { unsigned DstReg = I->getOperand(0).getReg(); unsigned LoReg = I->getOperand(1).getReg(); unsigned HiReg = I->getOperand(2).getReg(); @@ -360,9 +363,11 @@ // register). Unfortunately, we have to make this decision before register // allocation so for now we use a spill/reload sequence for all // double-precision values in regardless of being an odd/even register. - - if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || - (FP64 && !Subtarget.useOddSPReg())) { + // + // For the cases that should be covered here MipsSEISelDAGToDAG adds + // FrameSetup flag, so other passes (like ShrinkWrapping) are aware that stack + // is used. + if (I->getFlag(MachineInstr::FrameSetup)) { unsigned DstReg = I->getOperand(0).getReg(); unsigned SrcReg = Op1.getReg(); unsigned N = Op2.getImm(); Index: lib/Target/Mips/MipsSEISelDAGToDAG.cpp =================================================================== --- lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -238,6 +238,18 @@ case Mips::WRDSP: addDSPCtrlRegOperands(true, MI, MF); break; + case Mips::BuildPairF64_64: + case Mips::ExtractElementF64_64: + if (!Subtarget->useOddSPReg()) { + MI.setFlag(MachineInstr::MIFlag::FrameSetup); + break; + } + // fallthrough + case Mips::BuildPairF64: + case Mips::ExtractElementF64: + if (Subtarget->isABI_FPXX() && !Subtarget->hasMTHC1()) + MI.setFlag(MachineInstr::MIFlag::FrameSetup); + break; default: replaceUsesWithZeroReg(MRI, MI); } Index: test/CodeGen/Mips/shrink-wrap-buildpairf64-extractelementf64.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/shrink-wrap-buildpairf64-extractelementf64.ll @@ -0,0 +1,197 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py + +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32 \ +; RUN: -mattr=+fpxx -enable-shrink-wrap=true | \ +; RUN: FileCheck %s -check-prefix=NO-SHRINK-WRAP-FPXX + +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r6 \ +; RUN: -mattr=+fp64,+nooddspreg -enable-shrink-wrap=true | \ +; RUN: FileCheck %s -check-prefix=NO-SHRINK-WRAP-FP64 + +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r2 \ +; RUN: -mattr=+fpxx -enable-shrink-wrap=true | \ +; RUN: FileCheck %s -check-prefix=SHRINK-WRAP + +; When BuildPairF64{_64}, ExtractElementF64{_64} are expanded into instructions +; that use $sp, check that shrink-wrapping doesn't move prologue setup after +; them. + +@gdbl = external global double, align 8 +declare float @llvm.copysign.f32(float, float) +declare i32 @foo(double) + +define i32 @testExtractElementF64(i32 signext %v1) { +; NO-SHRINK-WRAP-FPXX-LABEL: testExtractElementF64: +; NO-SHRINK-WRAP-FPXX: # %bb.0: # %entry +; NO-SHRINK-WRAP-FPXX-NEXT: addiu $sp, $sp, -32 +; NO-SHRINK-WRAP-FPXX-NEXT: .cfi_def_cfa_offset 32 +; NO-SHRINK-WRAP-FPXX-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill +; NO-SHRINK-WRAP-FPXX-NEXT: .cfi_offset 31, -4 +; NO-SHRINK-WRAP-FPXX-NEXT: lui $1, %hi(gdbl) +; NO-SHRINK-WRAP-FPXX-NEXT: ldc1 $f12, %lo(gdbl)($1) +; NO-SHRINK-WRAP-FPXX-NEXT: sdc1 $f12, 16($sp) +; NO-SHRINK-WRAP-FPXX-NEXT: lw $1, 16($sp) +; NO-SHRINK-WRAP-FPXX-NEXT: lui $2, 32768 +; NO-SHRINK-WRAP-FPXX-NEXT: and $1, $1, $2 +; NO-SHRINK-WRAP-FPXX-NEXT: lui $2, 16256 +; NO-SHRINK-WRAP-FPXX-NEXT: or $1, $1, $2 +; NO-SHRINK-WRAP-FPXX-NEXT: mtc1 $1, $f0 +; NO-SHRINK-WRAP-FPXX-NEXT: mtc1 $zero, $f1 +; NO-SHRINK-WRAP-FPXX-NEXT: c.eq.s $f0, $f1 +; NO-SHRINK-WRAP-FPXX-NEXT: bc1f $BB0_2 +; NO-SHRINK-WRAP-FPXX-NEXT: addiu $2, $zero, -1 +; NO-SHRINK-WRAP-FPXX-NEXT: # %bb.1: # %if.end +; NO-SHRINK-WRAP-FPXX-NEXT: jal foo +; NO-SHRINK-WRAP-FPXX-NEXT: nop +; NO-SHRINK-WRAP-FPXX-NEXT: $BB0_2: # %return +; NO-SHRINK-WRAP-FPXX-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload +; NO-SHRINK-WRAP-FPXX-NEXT: jr $ra +; NO-SHRINK-WRAP-FPXX-NEXT: addiu $sp, $sp, 32 +; +; NO-SHRINK-WRAP-FP64-LABEL: testExtractElementF64: +; NO-SHRINK-WRAP-FP64: # %bb.0: # %entry +; NO-SHRINK-WRAP-FP64-NEXT: addiu $sp, $sp, -32 +; NO-SHRINK-WRAP-FP64-NEXT: .cfi_def_cfa_offset 32 +; NO-SHRINK-WRAP-FP64-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill +; NO-SHRINK-WRAP-FP64-NEXT: .cfi_offset 31, -4 +; NO-SHRINK-WRAP-FP64-NEXT: lui $1, %hi(gdbl) +; NO-SHRINK-WRAP-FP64-NEXT: ldc1 $f12, %lo(gdbl)($1) +; NO-SHRINK-WRAP-FP64-NEXT: sdc1 $f12, 16($sp) +; NO-SHRINK-WRAP-FP64-NEXT: lw $1, 16($sp) +; NO-SHRINK-WRAP-FP64-NEXT: ext $1, $1, 31, 1 +; NO-SHRINK-WRAP-FP64-NEXT: lui $2, 16256 +; NO-SHRINK-WRAP-FP64-NEXT: ins $2, $1, 31, 1 +; NO-SHRINK-WRAP-FP64-NEXT: mtc1 $2, $f0 +; NO-SHRINK-WRAP-FP64-NEXT: mtc1 $zero, $f2 +; NO-SHRINK-WRAP-FP64-NEXT: cmp.eq.s $f0, $f0, $f2 +; NO-SHRINK-WRAP-FP64-NEXT: mfc1 $1, $f0 +; NO-SHRINK-WRAP-FP64-NEXT: not $1, $1 +; NO-SHRINK-WRAP-FP64-NEXT: andi $1, $1, 1 +; NO-SHRINK-WRAP-FP64-NEXT: bnez $1, $BB0_2 +; NO-SHRINK-WRAP-FP64-NEXT: addiu $2, $zero, -1 +; NO-SHRINK-WRAP-FP64-NEXT: # %bb.1: # %if.end +; NO-SHRINK-WRAP-FP64-NEXT: jal foo +; NO-SHRINK-WRAP-FP64-NEXT: nop +; NO-SHRINK-WRAP-FP64-NEXT: $BB0_2: # %return +; NO-SHRINK-WRAP-FP64-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload +; NO-SHRINK-WRAP-FP64-NEXT: jr $ra +; NO-SHRINK-WRAP-FP64-NEXT: addiu $sp, $sp, 32 +; +; SHRINK-WRAP-LABEL: testExtractElementF64: +; SHRINK-WRAP: # %bb.0: # %entry +; SHRINK-WRAP-NEXT: lui $1, %hi(gdbl) +; SHRINK-WRAP-NEXT: ldc1 $f12, %lo(gdbl)($1) +; SHRINK-WRAP-NEXT: mfhc1 $1, $f12 +; SHRINK-WRAP-NEXT: ext $1, $1, 31, 1 +; SHRINK-WRAP-NEXT: lui $2, 16256 +; SHRINK-WRAP-NEXT: ins $2, $1, 31, 1 +; SHRINK-WRAP-NEXT: mtc1 $2, $f0 +; SHRINK-WRAP-NEXT: mtc1 $zero, $f1 +; SHRINK-WRAP-NEXT: c.eq.s $f0, $f1 +; SHRINK-WRAP-NEXT: bc1t $BB0_2 +; SHRINK-WRAP-NEXT: addiu $2, $zero, -1 +; SHRINK-WRAP-NEXT: # %bb.1: # %return +; SHRINK-WRAP-NEXT: jr $ra +; SHRINK-WRAP-NEXT: nop +; SHRINK-WRAP-NEXT: $BB0_2: # %if.end +; SHRINK-WRAP-NEXT: addiu $sp, $sp, -24 +; SHRINK-WRAP-NEXT: .cfi_def_cfa_offset 24 +; SHRINK-WRAP-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill +; SHRINK-WRAP-NEXT: .cfi_offset 31, -4 +; SHRINK-WRAP-NEXT: jal foo +; SHRINK-WRAP-NEXT: nop +; SHRINK-WRAP-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload +; SHRINK-WRAP-NEXT: jr $ra +; SHRINK-WRAP-NEXT: addiu $sp, $sp, 24 +entry: + %0 = load double, double* @gdbl, align 8 + %conv = fptrunc double %0 to float + %1 = tail call float @llvm.copysign.f32(float 1.000000e+00, float %conv) + %tobool = fcmp une float %1, 0.000000e+00 + br i1 %tobool, label %return, label %if.end + +if.end: + %call = tail call i32 @foo(double %0) + br label %return + +return: + %retval.0 = phi i32 [ %call, %if.end ], [ -1, %entry ] + ret i32 %retval.0 +} + +define i32 @testBuildPairFP64(double %d1) { +; NO-SHRINK-WRAP-FPXX-LABEL: testBuildPairFP64: +; NO-SHRINK-WRAP-FPXX: # %bb.0: # %entry +; NO-SHRINK-WRAP-FPXX-NEXT: addiu $sp, $sp, -32 +; NO-SHRINK-WRAP-FPXX-NEXT: .cfi_def_cfa_offset 32 +; NO-SHRINK-WRAP-FPXX-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill +; NO-SHRINK-WRAP-FPXX-NEXT: .cfi_offset 31, -4 +; NO-SHRINK-WRAP-FPXX-NEXT: sw $zero, 16($sp) +; NO-SHRINK-WRAP-FPXX-NEXT: sw $zero, 20($sp) +; NO-SHRINK-WRAP-FPXX-NEXT: ldc1 $f0, 16($sp) +; NO-SHRINK-WRAP-FPXX-NEXT: c.eq.d $f12, $f0 +; NO-SHRINK-WRAP-FPXX-NEXT: bc1f $BB1_2 +; NO-SHRINK-WRAP-FPXX-NEXT: addiu $2, $zero, 0 +; NO-SHRINK-WRAP-FPXX-NEXT: # %bb.1: # %if.end +; NO-SHRINK-WRAP-FPXX-NEXT: jal foo +; NO-SHRINK-WRAP-FPXX-NEXT: nop +; NO-SHRINK-WRAP-FPXX-NEXT: $BB1_2: # %return +; NO-SHRINK-WRAP-FPXX-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload +; NO-SHRINK-WRAP-FPXX-NEXT: jr $ra +; NO-SHRINK-WRAP-FPXX-NEXT: addiu $sp, $sp, 32 +; +; NO-SHRINK-WRAP-FP64-LABEL: testBuildPairFP64: +; NO-SHRINK-WRAP-FP64: # %bb.0: # %entry +; NO-SHRINK-WRAP-FP64-NEXT: addiu $sp, $sp, -32 +; NO-SHRINK-WRAP-FP64-NEXT: .cfi_def_cfa_offset 32 +; NO-SHRINK-WRAP-FP64-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill +; NO-SHRINK-WRAP-FP64-NEXT: .cfi_offset 31, -4 +; NO-SHRINK-WRAP-FP64-NEXT: sw $zero, 16($sp) +; NO-SHRINK-WRAP-FP64-NEXT: sw $zero, 20($sp) +; NO-SHRINK-WRAP-FP64-NEXT: ldc1 $f0, 16($sp) +; NO-SHRINK-WRAP-FP64-NEXT: cmp.eq.d $f0, $f12, $f0 +; NO-SHRINK-WRAP-FP64-NEXT: mfc1 $1, $f0 +; NO-SHRINK-WRAP-FP64-NEXT: not $1, $1 +; NO-SHRINK-WRAP-FP64-NEXT: andi $1, $1, 1 +; NO-SHRINK-WRAP-FP64-NEXT: bnez $1, $BB1_2 +; NO-SHRINK-WRAP-FP64-NEXT: addiu $2, $zero, 0 +; NO-SHRINK-WRAP-FP64-NEXT: # %bb.1: # %if.end +; NO-SHRINK-WRAP-FP64-NEXT: jal foo +; NO-SHRINK-WRAP-FP64-NEXT: nop +; NO-SHRINK-WRAP-FP64-NEXT: $BB1_2: # %return +; NO-SHRINK-WRAP-FP64-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload +; NO-SHRINK-WRAP-FP64-NEXT: jr $ra +; NO-SHRINK-WRAP-FP64-NEXT: addiu $sp, $sp, 32 +; +; SHRINK-WRAP-LABEL: testBuildPairFP64: +; SHRINK-WRAP: # %bb.0: # %entry +; SHRINK-WRAP-NEXT: mtc1 $zero, $f0 +; SHRINK-WRAP-NEXT: mthc1 $zero, $f0 +; SHRINK-WRAP-NEXT: c.eq.d $f12, $f0 +; SHRINK-WRAP-NEXT: bc1t $BB1_2 +; SHRINK-WRAP-NEXT: addiu $2, $zero, 0 +; SHRINK-WRAP-NEXT: # %bb.1: # %return +; SHRINK-WRAP-NEXT: jr $ra +; SHRINK-WRAP-NEXT: nop +; SHRINK-WRAP-NEXT: $BB1_2: # %if.end +; SHRINK-WRAP-NEXT: addiu $sp, $sp, -24 +; SHRINK-WRAP-NEXT: .cfi_def_cfa_offset 24 +; SHRINK-WRAP-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill +; SHRINK-WRAP-NEXT: .cfi_offset 31, -4 +; SHRINK-WRAP-NEXT: jal foo +; SHRINK-WRAP-NEXT: nop +; SHRINK-WRAP-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload +; SHRINK-WRAP-NEXT: jr $ra +; SHRINK-WRAP-NEXT: addiu $sp, $sp, 24 +entry: + %tobool = fcmp une double %d1, 0.000000e+00 + br i1 %tobool, label %return, label %if.end + +if.end: + %call = tail call i32 @foo(double %d1) + br label %return + +return: + %retval.0 = phi i32 [ %call, %if.end ], [ 0, %entry ] + ret i32 %retval.0 +}