diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h @@ -1342,14 +1342,21 @@ SmallPtrSet &BlocksToExplore, DbgValue &LiveIn); - /// For the given block and live-outs feeding into it, try to find a - /// machine location where all the variable values join together. - /// \returns Value ID of a machine PHI if an appropriate one is available. - Optional - pickVPHILoc(const MachineBasicBlock &MBB, const DebugVariable &Var, + /// For the given block and live-outs feeding into it, try to find + /// machine locations for each debug operand where all the values feeding + /// into that operand join together. + /// \returns true if a joined location was found for every value that needed + /// to be joined. + bool + pickVPHILoc(SmallVectorImpl &OutValues, const MachineBasicBlock &MBB, const LiveIdxT &LiveOuts, FuncValueTable &MOutLocs, const SmallVectorImpl &BlockOrders); + Optional pickOperandPHILoc( + unsigned DbgOpIdx, const MachineBasicBlock &MBB, const LiveIdxT &LiveOuts, + FuncValueTable &MOutLocs, + const SmallVectorImpl &BlockOrders); + /// Take collections of DBG_VALUE instructions stored in TTracker, and /// install them into their output blocks. Preserves a stable order of /// DBG_VALUEs produced (which would otherwise cause nondeterminism) through diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp @@ -2419,33 +2419,104 @@ IDF.calculate(PHIBlocks); } -Optional InstrRefBasedLDV::pickVPHILoc( - const MachineBasicBlock &MBB, const DebugVariable &Var, +bool InstrRefBasedLDV::pickVPHILoc( + SmallVectorImpl &OutValues, const MachineBasicBlock &MBB, const LiveIdxT &LiveOuts, FuncValueTable &MOutLocs, const SmallVectorImpl &BlockOrders) { - // Collect a set of locations from predecessor where its live-out value can - // be found. - SmallVector, 8> Locs; - SmallVector Properties; - unsigned NumLocs = MTracker->getNumLocs(); // No predecessors means no PHIs. if (BlockOrders.empty()) - return None; + return false; - for (const auto *p : BlockOrders) { - unsigned ThisBBNum = p->getNumber(); + // All the location operands that do not already agree need to be joined, + // track the indices of each such location operand here. + SmallDenseSet LocOpsToJoin; + + auto FirstValueIt = LiveOuts.find(BlockOrders[0]); + if (FirstValueIt == LiveOuts.end()) + return false; + const DbgValue &FirstValue = *FirstValueIt->second; + + for (const auto p : BlockOrders) { auto OutValIt = LiveOuts.find(p); if (OutValIt == LiveOuts.end()) // If we have a predecessor not in scope, we'll never find a PHI position. - return None; + return false; const DbgValue &OutVal = *OutValIt->second; - if (OutVal.getDbgOpID(0).isConst() || OutVal.Kind == DbgValue::NoVal) - // Consts and no-values cannot have locations we can join on. - return None; + // No-values cannot have locations we can join on. + if (OutVal.Kind == DbgValue::NoVal) + return false; - Properties.push_back(&OutVal.Properties); + // For unjoined VPHIs where we don't know the location, we definitely + // can't find a join loc unless the VPHI is a backedge. + if (OutVal.isUnjoinedPHI() && OutVal.BlockNo != MBB.getNumber()) + return false; + + if (FirstValue.Properties != OutVal.Properties) + return false; + + for (unsigned Idx = 0; Idx < FirstValue.getLocationOpCount(); ++Idx) { + // An unjoined PHI has no defined locations, and so a shared location must + // be found for every operand. + if (OutVal.isUnjoinedPHI()) { + LocOpsToJoin.insert(Idx); + continue; + } + DbgOpID FirstValOp = FirstValue.getDbgOpID(Idx); + DbgOpID OutValOp = OutVal.getDbgOpID(Idx); + if (FirstValOp != OutValOp) { + // We can never join constant ops - the ops must either both be equal + // constant ops or non-const ops. + if (FirstValOp.isConst() || OutValOp.isConst()) + return false; + else + LocOpsToJoin.insert(Idx); + } + } + } + + SmallVector NewDbgOps; + + for (unsigned Idx = 0; Idx < FirstValue.getLocationOpCount(); ++Idx) { + // If this op doesn't need to be joined because the values agree, use that + // already-agreed value. + if (!LocOpsToJoin.contains(Idx)) { + NewDbgOps.push_back(FirstValue.getDbgOpID(Idx)); + continue; + } + + Optional JoinedOpLoc = + pickOperandPHILoc(Idx, MBB, LiveOuts, MOutLocs, BlockOrders); + + if (!JoinedOpLoc) + return false; + + NewDbgOps.push_back(DbgOpStore.insert(*JoinedOpLoc)); + } + + OutValues.append(NewDbgOps); + return true; +} + +Optional InstrRefBasedLDV::pickOperandPHILoc( + unsigned DbgOpIdx, const MachineBasicBlock &MBB, const LiveIdxT &LiveOuts, + FuncValueTable &MOutLocs, + const SmallVectorImpl &BlockOrders) { + + // Collect a set of locations from predecessor where its live-out value can + // be found. + SmallVector, 8> Locs; + unsigned NumLocs = MTracker->getNumLocs(); + + for (const auto p : BlockOrders) { + unsigned ThisBBNum = p->getNumber(); + auto OutValIt = LiveOuts.find(p); + assert(OutValIt != LiveOuts.end()); + const DbgValue &OutVal = *OutValIt->second; + DbgOpID OutValOpID = OutVal.getDbgOpID(DbgOpIdx); + DbgOp OutValOp = DbgOpStore.find(OutValOpID); + assert(!OutValOp.IsConst); // Create new empty vector of locations. Locs.resize(Locs.size() + 1); @@ -2454,8 +2525,8 @@ // present. Do the same for VPHIs where we know the VPHI value. if (OutVal.Kind == DbgValue::Def || (OutVal.Kind == DbgValue::VPHI && OutVal.BlockNo != MBB.getNumber() && - !OutVal.getDbgOpID(0).isUndef())) { - ValueIDNum ValToLookFor = DbgOpStore.find(OutVal.getDbgOpID(0)).ID; + !OutValOp.isUndef())) { + ValueIDNum ValToLookFor = OutValOp.ID; // Search the live-outs of the predecessor for the specified value. for (unsigned int I = 0; I < NumLocs; ++I) { if (MOutLocs[ThisBBNum][I] == ValToLookFor) @@ -2463,11 +2534,6 @@ } } else { assert(OutVal.Kind == DbgValue::VPHI); - // For VPHIs where we don't know the location, we definitely can't find - // a join loc. - if (OutVal.BlockNo != MBB.getNumber()) - return None; - // Otherwise: this is a VPHI on a backedge feeding back into itself, i.e. // a value that's live-through the whole loop. (It has to be a backedge, // because a block can't dominate itself). We can accept as a PHI location @@ -2481,17 +2547,9 @@ } } } - // We should have found locations for all predecessors, or returned. assert(Locs.size() == BlockOrders.size()); - // Check that all properties are the same. We can't pick a location if they're - // not. - const DbgValueProperties *Properties0 = Properties[0]; - for (const auto *Prop : Properties) - if (*Prop != *Properties0) - return None; - // Starting with the first set of locations, take the intersection with // subsequent sets. SmallVector CandidateLocs = Locs[0]; @@ -2582,7 +2640,7 @@ // Scan for variable values that can never be resolved: if they have // different DIExpressions, different indirectness, or are mixed constants / // non-constants. - for (auto &V : Values) { + for (const auto &V : Values) { if (V.second->Properties != FirstVal.Properties) return false; if (V.second->Kind == DbgValue::NoVal) @@ -2847,13 +2905,13 @@ // eliminated and transitions from VPHI-with-location to // live-through-value. As a result, the selected location of any VPHI // might change, so we need to re-compute it on each iteration. - Optional ValueNum = - pickVPHILoc(*MBB, Var, LiveOutIdx, MOutLocs, Preds); + SmallVector JoinedOps; - if (ValueNum) { - DbgOpID ValueID = DbgOpStore.insert(*ValueNum); - InLocsChanged |= LiveIn->getDbgOpID(0) != ValueID; - LiveIn->setDbgOpIDs(ValueID); + if (pickVPHILoc(JoinedOps, *MBB, LiveOutIdx, MOutLocs, Preds)) { + bool NewLocPicked = !equal(LiveIn->getDbgOpIDs(), JoinedOps); + InLocsChanged |= NewLocPicked; + if (NewLocPicked) + LiveIn->setDbgOpIDs(JoinedOps); } } diff --git a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp --- a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp +++ b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp @@ -198,11 +198,12 @@ LDV->placeMLocPHIs(MF, AllBlocks, MInLocs, MLocTransfer); } - Optional - pickVPHILoc(const MachineBasicBlock &MBB, const DebugVariable &Var, - const InstrRefBasedLDV::LiveIdxT &LiveOuts, FuncValueTable &MOutLocs, + bool + pickVPHILoc(SmallVectorImpl &OutValues, const MachineBasicBlock &MBB, + const InstrRefBasedLDV::LiveIdxT &LiveOuts, + FuncValueTable &MOutLocs, const SmallVectorImpl &BlockOrders) { - return LDV->pickVPHILoc(MBB, Var, LiveOuts, MOutLocs, BlockOrders); + return LDV->pickVPHILoc(OutValues, MBB, LiveOuts, MOutLocs, BlockOrders); } bool vlocJoin(MachineBasicBlock &MBB, InstrRefBasedLDV::LiveIdxT &VLOCOutLocs, @@ -1805,13 +1806,20 @@ ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc); ValueIDNum RspPHIInBlk2(Br2Blk, 0, RspLoc); ValueIDNum RspPHIInBlk3(RetBlk, 0, RspLoc); + ValueIDNum RaxPHIInBlk3(RetBlk, 0, RaxLoc); DbgOpID LiveInRspID = addValueDbgOp(LiveInRsp); DbgOpID LiveInRaxID = addValueDbgOp(LiveInRax); DbgOpID RspPHIInBlk2ID = addValueDbgOp(RspPHIInBlk2); - addValueDbgOp(RspPHIInBlk3); + DbgOpID RspPHIInBlk3ID = addValueDbgOp(RspPHIInBlk3); + DbgOpID RaxPHIInBlk3ID = addValueDbgOp(RaxPHIInBlk3); + DbgOpID ConstZeroID = addConstDbgOp(MachineOperand::CreateImm(0)); DebugVariable Var(FuncVariable, None, nullptr); DbgValueProperties EmptyProps(EmptyExpr, false, false); + DIExpression *TwoOpExpr = + DIExpression::get(Ctx, {dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, + 1, dwarf::DW_OP_plus}); + DbgValueProperties TwoOpProps(TwoOpExpr, false, true); SmallVector VLiveOuts; VLiveOuts.resize(4, DbgValue(EmptyProps, DbgValue::Undef)); InstrRefBasedLDV::LiveIdxT VLiveOutIdx; @@ -1828,42 +1836,51 @@ MOutLocs[1][0] = LiveInRsp; MOutLocs[2][0] = LiveInRax; - Optional Result; + bool Result; + SmallVector OutValues; // Simple case: join two distinct values on entry to the block. VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[2] = DbgValue(LiveInRaxID, EmptyProps); - Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); // Should have picked a PHI in $rsp in block 3. EXPECT_TRUE(Result); if (Result) { - EXPECT_EQ(*Result, RspPHIInBlk3); + EXPECT_EQ(OutValues[0], RspPHIInBlk3ID); } // If the incoming values are swapped between blocks, we should not // successfully join. The CFG merge would select the right values, but in // the wrong conditions. std::swap(VLiveOuts[1], VLiveOuts[2]); - Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); // Swap back, std::swap(VLiveOuts[1], VLiveOuts[2]); // Setting one of these to being a constant should prohibit merging. - VLiveOuts[1].setDbgOpIDs(addConstDbgOp(MachineOperand::CreateImm(0))); - Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); + VLiveOuts[1].setDbgOpIDs(ConstZeroID); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); - // Seeing both to being a constant -> still prohibit, it shouldn't become - // a value in the register file anywhere. + // Setting both to being identical constants should result in a valid join + // with a constant value. VLiveOuts[2] = VLiveOuts[1]; - Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); - EXPECT_FALSE(Result); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); + EXPECT_TRUE(Result); + if (Result) { + EXPECT_EQ(OutValues[0], ConstZeroID); + } // NoVals shouldn't join with anything else. VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::NoVal); - Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); // We might merge in another VPHI in such a join. Present pickVPHILoc with @@ -1872,7 +1889,8 @@ // found in the register file -- we can't subsequently find a PHI here. VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); - Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); // However, if we know the value of the incoming VPHI, we can search for its @@ -1882,31 +1900,80 @@ VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI); VLiveOuts[2].setDbgOpIDs(RspPHIInBlk2ID); // Set location where PHI happens. - Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); EXPECT_TRUE(Result); if (Result) { - EXPECT_EQ(*Result, RspPHIInBlk3); + EXPECT_EQ(OutValues[0], RspPHIInBlk3ID); } // If that value isn't available from that block, don't join. MOutLocs[2][0] = LiveInRsp; - Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); // Check that we don't pick values when the properties disagree, for example // different indirectness or DIExpression. + MOutLocs[2][0] = LiveInRax; DIExpression *NewExpr = DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4); DbgValueProperties PropsWithExpr(NewExpr, false, false); VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[2] = DbgValue(LiveInRspID, PropsWithExpr); - Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); DbgValueProperties PropsWithIndirect(EmptyExpr, true, false); VLiveOuts[1] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[2] = DbgValue(LiveInRspID, PropsWithIndirect); - Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); + EXPECT_FALSE(Result); + + // When we have operands with values [A, B] and [B, A], we do not necessarily + // pick identical join locations for each operand if the locations of those + // values differ between incoming basic blocks. + MOutLocs[1][0] = LiveInRsp; + MOutLocs[2][0] = LiveInRax; + MOutLocs[1][1] = LiveInRax; + MOutLocs[2][1] = LiveInRsp; + DbgOpID Locs0[] = {LiveInRspID, LiveInRaxID}; + DbgOpID Locs1[] = {LiveInRaxID, LiveInRspID}; + VLiveOuts[1] = DbgValue(Locs0, TwoOpProps); + VLiveOuts[2] = DbgValue(Locs1, TwoOpProps); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); + // Should have picked PHIs in block 3. + EXPECT_TRUE(Result); + if (Result) { + EXPECT_EQ(OutValues[0], RspPHIInBlk3ID); + EXPECT_EQ(OutValues[1], RaxPHIInBlk3ID); + } + + // When joining identical constants for an operand, we should simply keep that + // constant while joining the remaining operands as normal. + DbgOpID Locs2[] = {LiveInRspID, ConstZeroID}; + DbgOpID Locs3[] = {LiveInRaxID, ConstZeroID}; + VLiveOuts[1] = DbgValue(Locs2, TwoOpProps); + VLiveOuts[2] = DbgValue(Locs3, TwoOpProps); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); + EXPECT_TRUE(Result); + if (Result) { + EXPECT_EQ(OutValues[0], RspPHIInBlk3ID); + EXPECT_EQ(OutValues[1], ConstZeroID); + } + + // If the debug values have different constants for the same operand, they + // cannot be joined. + DbgOpID ConstOneID = addConstDbgOp(MachineOperand::CreateImm(1)); + DbgOpID Locs4[] = {LiveInRaxID, ConstOneID}; + VLiveOuts[1] = DbgValue(Locs0, TwoOpProps); + VLiveOuts[2] = DbgValue(Locs2, TwoOpProps); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB3, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); } @@ -1938,11 +2005,15 @@ ValueIDNum RaxPHIInBlk1(LoopBlk, 0, RaxLoc); DbgOpID LiveInRspID = addValueDbgOp(LiveInRsp); DbgOpID LiveInRaxID = addValueDbgOp(LiveInRax); - addValueDbgOp(RspPHIInBlk1); - addValueDbgOp(RaxPHIInBlk1); + DbgOpID RspPHIInBlk1ID = addValueDbgOp(RspPHIInBlk1); + DbgOpID RaxPHIInBlk1ID = addValueDbgOp(RaxPHIInBlk1); DebugVariable Var(FuncVariable, None, nullptr); DbgValueProperties EmptyProps(EmptyExpr, false, false); + DIExpression *TwoOpExpr = + DIExpression::get(Ctx, {dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, + 1, dwarf::DW_OP_plus}); + DbgValueProperties TwoOpProps(TwoOpExpr, false, true); SmallVector VLiveOuts; VLiveOuts.resize(3, DbgValue(EmptyProps, DbgValue::Undef)); InstrRefBasedLDV::LiveIdxT VLiveOutIdx; @@ -1958,21 +2029,24 @@ MOutLocs[0][0] = LiveInRsp; MOutLocs[1][0] = LiveInRax; - Optional Result; + bool Result; + SmallVector OutValues; // See that we can merge as normal on a backedge. VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(LiveInRaxID, EmptyProps); - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); // Should have picked a PHI in $rsp in block 1. EXPECT_TRUE(Result); if (Result) { - EXPECT_EQ(*Result, RspPHIInBlk1); + EXPECT_EQ(OutValues[0], RspPHIInBlk1ID); } // And that, if the desired values aren't available, we don't merge. MOutLocs[1][0] = LiveInRsp; - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); // Test the backedge behaviour: PHIs that feed back into themselves can @@ -1986,16 +2060,35 @@ VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); // Crucially, a VPHI originating in this block: VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); EXPECT_TRUE(Result); if (Result) { - EXPECT_EQ(*Result, RaxPHIInBlk1); + EXPECT_EQ(OutValues[0], RaxPHIInBlk1ID); + } + + // Test that we can also find a location when joining a backedge PHI with + // a variadic debug value. + MOutLocs[1][0] = RspPHIInBlk1; + MOutLocs[0][1] = LiveInRax; + DbgOpID Locs0[] = {LiveInRspID, LiveInRaxID}; + VLiveOuts[0] = DbgValue(Locs0, TwoOpProps); + // Crucially, a VPHI originating in this block: + VLiveOuts[1] = DbgValue(1, TwoOpProps, DbgValue::VPHI); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); + EXPECT_TRUE(Result); + if (Result) { + EXPECT_EQ(OutValues[0], RspPHIInBlk1ID); + EXPECT_EQ(OutValues[1], RaxPHIInBlk1ID); } // Merging should not be permitted if there's a usable PHI on the backedge, // but it's in the wrong place. (Overwrite $rax). MOutLocs[1][1] = LiveInRax; - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); // Additionally, if the VPHI coming back on the loop backedge isn't from @@ -2003,7 +2096,8 @@ MOutLocs[1][1] = RaxPHIInBlk1; VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(0, EmptyProps, DbgValue::VPHI); - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); } @@ -2045,9 +2139,9 @@ DbgOpID LiveInRspID = addValueDbgOp(LiveInRsp); DbgOpID LiveInRaxID = addValueDbgOp(LiveInRax); DbgOpID LiveInRbxID = addValueDbgOp(LiveInRbx); - addValueDbgOp(RspPHIInBlk1); + DbgOpID RspPHIInBlk1ID = addValueDbgOp(RspPHIInBlk1); addValueDbgOp(RaxPHIInBlk1); - addValueDbgOp(RbxPHIInBlk1); + DbgOpID RbxPHIInBlk1ID = addValueDbgOp(RbxPHIInBlk1); DebugVariable Var(FuncVariable, None, nullptr); DbgValueProperties EmptyProps(EmptyExpr, false, false); @@ -2071,24 +2165,27 @@ MOutLocs[1][0] = LiveInRax; MOutLocs[2][0] = LiveInRbx; - Optional Result; + bool Result; + SmallVector OutValues; // See that we can merge as normal on a backedge. VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(LiveInRaxID, EmptyProps); VLiveOuts[2] = DbgValue(LiveInRbxID, EmptyProps); - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); // Should have picked a PHI in $rsp in block 1. EXPECT_TRUE(Result); if (Result) { - EXPECT_EQ(*Result, RspPHIInBlk1); + EXPECT_EQ(OutValues[0], RspPHIInBlk1ID); } // Check too that permuting the live-out locations prevents merging MOutLocs[0][0] = LiveInRax; MOutLocs[1][0] = LiveInRbx; MOutLocs[2][0] = LiveInRsp; - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); MOutLocs[0][0] = LiveInRsp; @@ -2098,7 +2195,8 @@ // Feeding a PHI back on one backedge shouldn't merge (block 1 self backedge // wants LiveInRax). MOutLocs[1][0] = RspPHIInBlk1; - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); // If the variables value on that edge is a VPHI feeding into itself, that's @@ -2106,10 +2204,11 @@ VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); VLiveOuts[2] = DbgValue(LiveInRbxID, EmptyProps); - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); EXPECT_TRUE(Result); if (Result) { - EXPECT_EQ(*Result, RspPHIInBlk1); + EXPECT_EQ(OutValues[0], RspPHIInBlk1ID); } // Likewise: the other backedge being a VPHI from block 1 should be accepted. @@ -2117,17 +2216,19 @@ VLiveOuts[0] = DbgValue(LiveInRspID, EmptyProps); VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI); VLiveOuts[2] = DbgValue(1, EmptyProps, DbgValue::VPHI); - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); EXPECT_TRUE(Result); if (Result) { - EXPECT_EQ(*Result, RspPHIInBlk1); + EXPECT_EQ(OutValues[0], RspPHIInBlk1ID); } // Here's where it becomes tricky: we should not merge if there are two // _distinct_ backedge PHIs. We can't have a PHI that happens in both rsp // and rax for example. We can only pick one location as the live-in. MOutLocs[2][0] = RaxPHIInBlk1; - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); // The above test sources correct machine-PHI-value from two places. Now @@ -2138,7 +2239,8 @@ MOutLocs[1][0] = RspPHIInBlk1; MOutLocs[2][0] = LiveInRsp; MOutLocs[2][1] = RspPHIInBlk1; - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); EXPECT_FALSE(Result); // Scatter various PHI values across the available locations. Only rbx (loc 2) @@ -2151,10 +2253,11 @@ MOutLocs[2][0] = LiveInRsp; MOutLocs[2][1] = RspPHIInBlk1; MOutLocs[2][2] = RbxPHIInBlk1; - Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds); + OutValues.clear(); + Result = pickVPHILoc(OutValues, *MBB1, VLiveOutIdx, MOutLocs, Preds); EXPECT_TRUE(Result); if (Result) { - EXPECT_EQ(*Result, RbxPHIInBlk1); + EXPECT_EQ(OutValues[0], RbxPHIInBlk1ID); } } @@ -2835,6 +2938,10 @@ DebugVariable Var(FuncVariable, None, nullptr); DbgValueProperties EmptyProps(EmptyExpr, false, false); + DIExpression *TwoOpExpr = + DIExpression::get(Ctx, {dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, + 1, dwarf::DW_OP_plus}); + DbgValueProperties VariadicProps(TwoOpExpr, false, true); SmallSet AllVars; AllVars.insert(Var); @@ -2876,6 +2983,23 @@ VLocs[0].Vars.clear(); VLocs[1].Vars.clear(); + // A variadic assignment should behave the same. + DbgOpID Locs0[] = {LiveInRspID, LiveInRaxID}; + VLocs[0].Vars.insert({Var, DbgValue(Locs0, VariadicProps)}); + buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output, MOutLocs, + MInLocs, VLocs); + EXPECT_EQ(Output[0].size(), 0ul); + ASSERT_EQ(Output[1].size(), 1ul); + ASSERT_EQ(Output[2].size(), 1ul); + EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def); + EXPECT_EQ(Output[1][0].second.getDbgOpID(0), LiveInRspID); + EXPECT_EQ(Output[1][0].second.getDbgOpID(1), LiveInRaxID); + EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def); + EXPECT_EQ(Output[2][0].second.getDbgOpID(0), LiveInRspID); + ClearOutputs(); + VLocs[0].Vars.clear(); + VLocs[1].Vars.clear(); + // Put an undef assignment in the loop. Should get no live-in value. VLocs[0].Vars.insert({Var, DbgValue(LiveInRspID, EmptyProps)}); VLocs[1].Vars.insert({Var, DbgValue(EmptyProps, DbgValue::Undef)});