Index: llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h +++ llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h @@ -807,6 +807,14 @@ return getReservedRegs().test(PhysReg); } + /// Returns true when the given register unit is considered reserved. + /// + /// Register units are considered reserved when for at least one of their + /// root registers, the root register and all super registers are reserved. + /// This currently iterates the register hierarchy and may be slower than + /// expected. + bool isReservedRegUnit(unsigned Unit) const; + /// isAllocatable - Returns true when PhysReg belongs to an allocatable /// register class and it hasn't been reserved. /// Index: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp =================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -269,8 +269,9 @@ // may share super-registers. That's OK because createDeadDefs() is // idempotent. It is very rare for a register unit to have multiple roots, so // uniquing super-registers is probably not worthwhile. - bool IsReserved = true; + bool IsReserved = false; for (MCRegUnitRootIterator Root(Unit, TRI); Root.isValid(); ++Root) { + bool IsRootReserved = true; for (MCSuperRegIterator Super(*Root, TRI, /*IncludeSelf=*/true); Super.isValid(); ++Super) { unsigned Reg = *Super; @@ -279,9 +280,12 @@ // A register unit is considered reserved if all its roots and all their // super registers are reserved. if (!MRI->isReserved(Reg)) - IsReserved = false; + IsRootReserved = false; } + IsReserved |= IsRootReserved; } + assert(IsReserved == MRI->isReservedRegUnit(Unit) && + "reserved computation mismatch"); // Now extend LR to reach all uses. // Ignore uses of reserved registers. We only track defs of those. @@ -924,7 +928,7 @@ // kill flags. This is wasteful. Eventually, LiveVariables will strip all kill // flags, and postRA passes will use a live register utility instead. LiveRange *getRegUnitLI(unsigned Unit) { - if (UpdateFlags) + if (UpdateFlags && !MRI.isReservedRegUnit(Unit)) return &LIS.getRegUnit(Unit); return LIS.getCachedRegUnit(Unit); } Index: llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp +++ llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp @@ -601,3 +601,21 @@ UpdatedCSRs.push_back(0); IsUpdatedCSRsInitialized = true; } + +bool MachineRegisterInfo::isReservedRegUnit(unsigned Unit) const { + const TargetRegisterInfo *TRI = getTargetRegisterInfo(); + for (MCRegUnitRootIterator Root(Unit, TRI); Root.isValid(); ++Root) { + bool IsRootReserved = true; + for (MCSuperRegIterator Super(*Root, TRI, /*IncludeSelf=*/true); + Super.isValid(); ++Super) { + unsigned Reg = *Super; + if (!isReserved(Reg)) { + IsRootReserved = false; + break; + } + } + if (IsRootReserved) + return true; + } + return false; +} Index: llvm/trunk/lib/CodeGen/MachineVerifier.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineVerifier.cpp +++ llvm/trunk/lib/CodeGen/MachineVerifier.cpp @@ -1333,6 +1333,8 @@ // Check the cached regunit intervals. if (TargetRegisterInfo::isPhysicalRegister(Reg) && !isReserved(Reg)) { for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) { + if (MRI->isReservedRegUnit(*Units)) + continue; if (const LiveRange *LR = LiveInts->getCachedRegUnit(*Units)) checkLivenessAtUse(MO, MONum, UseIdx, *LR, *Units); } Index: llvm/trunk/test/CodeGen/ARM/no-fpscr-liveness.ll =================================================================== --- llvm/trunk/test/CodeGen/ARM/no-fpscr-liveness.ll +++ llvm/trunk/test/CodeGen/ARM/no-fpscr-liveness.ll @@ -0,0 +1,49 @@ +; RUN: llc -o - %s | FileCheck %s +; Make sure we do not try to compute liveness for FPSCR which in this case +; is read before being written to (this is fine because becase FPSCR is +; reserved). +target triple = "thumbv7s-apple-ios" + +%struct.wibble = type { double } + +@global = common global i32 0, align 4 +@global.1 = common global i32 0, align 4 + +; CHECK-LABEL: eggs: +; CHECK: sub sp, #8 +; VMRS instruction comes before any other instruction writing FPSCR: +; CHECK-NEXT: vmrs r0, fpscr +; ... +; CHECK: add sp, #8 +; CHECK: bx lr +define i32 @eggs(double* nocapture readnone %arg) { +bb: + %tmp = alloca %struct.wibble, align 4 + %tmp1 = bitcast %struct.wibble* %tmp to i8* + %tmp2 = tail call i32 @llvm.flt.rounds() + %tmp3 = ptrtoint %struct.wibble* %tmp to i32 + %tmp4 = sitofp i32 %tmp3 to double + %tmp5 = fmul double %tmp4, 0x0123456789ABCDEF + %tmp6 = fptosi double %tmp5 to i32 + %tmp7 = fcmp une double %tmp5, 0.000000e+00 + %tmp8 = sitofp i32 %tmp6 to double + %tmp9 = fcmp une double %tmp5, %tmp8 + %tmp10 = and i1 %tmp7, %tmp9 + %tmp11 = sext i1 %tmp10 to i32 + %tmp12 = add nsw i32 %tmp11, %tmp6 + store i32 %tmp12, i32* @global, align 4 + %tmp13 = icmp ne i32 %tmp12, 0 + %tmp14 = icmp ne i32 %tmp2, 0 + %tmp15 = and i1 %tmp14, %tmp13 + br i1 %tmp15, label %bb16, label %bb18 + +bb16: ; preds = %bb + %tmp17 = load i32, i32* @global.1, align 4 + br label %bb18 + +bb18: ; preds = %bb16, %bb + ret i32 undef +} + +declare i32 @llvm.flt.rounds() +declare i32 @zot(...)