Index: lib/CodeGen/LiveRangeCalc.cpp =================================================================== --- lib/CodeGen/LiveRangeCalc.cpp +++ lib/CodeGen/LiveRangeCalc.cpp @@ -20,6 +20,9 @@ #define DEBUG_TYPE "regalloc" +// Reserve an address that indicates a value that is known to be "undef". +static VNInfo UndefVNI(0xbad, SlotIndex()); + void LiveRangeCalc::resetLiveOutMap() { unsigned NumBlocks = MF->getNumBlockIDs(); Seen.clear(); @@ -283,7 +286,7 @@ // Determine if the exit from the block is reached by some def. unsigned N = WorkList[i]; MachineBasicBlock &B = *MF->getBlockNumbered(N); - if (Seen[N] && Map[&B].first != nullptr) + if (Seen[N] && Map[&B].first != nullptr && Map[&B].first != &UndefVNI) return MarkDefined(B); SlotIndex Begin, End; std::tie(Begin, End) = Indexes->getMBBRange(&B); @@ -387,7 +390,7 @@ auto EP = LR.extendInBlock(Undefs, Start, End); VNInfo *VNI = EP.first; FoundUndef |= EP.second; - setLiveOutValue(Pred, VNI); + setLiveOutValue(Pred, EP.second ? &UndefVNI : VNI); if (VNI) { if (TheVNI && TheVNI != VNI) UniqueVNI = false; @@ -417,7 +420,7 @@ // If a unique reaching def was found, blit in the live ranges immediately. if (UniqueVNI) { - assert(TheVNI != nullptr); + assert(TheVNI != nullptr && TheVNI != &UndefVNI); LiveRangeUpdater Updater(&LR); for (unsigned BN : WorkList) { SlotIndex Start, End; @@ -491,15 +494,20 @@ IDomValue = Map[IDom->getBlock()]; // Cache the DomTree node that defined the value. - if (IDomValue.first && !IDomValue.second) - Map[IDom->getBlock()].second = IDomValue.second = - DomTree->getNode(Indexes->getMBBFromIndex(IDomValue.first->def)); + if (IDomValue.first && IDomValue.first != &UndefVNI) + if (!IDomValue.second) + Map[IDom->getBlock()].second = IDomValue.second = + DomTree->getNode(Indexes->getMBBFromIndex(IDomValue.first->def)); for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), PE = MBB->pred_end(); PI != PE; ++PI) { LiveOutPair &Value = Map[*PI]; if (!Value.first || Value.first == IDomValue.first) continue; + if (Value.first == &UndefVNI) { + needPHI = true; + break; + } // Cache the DomTree node that defined the value. if (!Value.second) @@ -542,7 +550,7 @@ LR.addSegment(LiveInterval::Segment(Start, End, VNI)); LOP = LiveOutPair(VNI, Node); } - } else if (IDomValue.first) { + } else if (IDomValue.first && IDomValue.first != &UndefVNI) { // No phi-def here. Remember incoming value. I.Value = IDomValue.first; Index: test/CodeGen/Hexagon/regalloc-liveout-undef.ll =================================================================== --- /dev/null +++ test/CodeGen/Hexagon/regalloc-liveout-undef.ll @@ -0,0 +1,145 @@ +; RUN: llc -march=hexagon -verify-machineinstrs < %s | FileCheck %s +; +; Check that this compiles successfully. +; CHECK: call f0 + +target triple = "hexagon" + +@g0 = external local_unnamed_addr constant [4 x [36 x i32]], align 8 + +define i32 @fred(i32 %a0, i32 %a1) local_unnamed_addr #0 { +b2: + %v3 = load i8*, i8** undef, align 4 + %v4 = load i16, i16* undef, align 2 + %v5 = sdiv i16 %v4, 18 + %v6 = sext i16 %v5 to i32 + br i1 undef, label %b12, label %b7 + +b7: ; preds = %b2 + %v8 = load i32, i32* undef, align 4 + %v9 = add nsw i32 %v8, 7 + %v10 = sdiv i32 %v9, 18 + %v11 = add nsw i32 %v10, 1 + br label %b14 + +b12: ; preds = %b2 + br i1 undef, label %b13, label %b14 + +b13: ; preds = %b12 + br label %b17 + +b14: ; preds = %b12, %b7 + %v15 = phi i32 [ %v6, %b12 ], [ %v11, %b7 ] + br label %b16 + +b16: ; preds = %b16, %b14 + store i32 0, i32* undef, align 4 + br i1 undef, label %b16, label %b17 + +b17: ; preds = %b16, %b13 + %v18 = phi i32 [ 0, %b13 ], [ %v15, %b16 ] + %v19 = load i32, i32* undef, align 4 + %v20 = load i32, i32* undef, align 4 + %v21 = mul i32 %a1, 1152 + %v22 = mul i32 %v18, 36 + %v23 = add i32 %v21, %v22 + %v24 = add i32 %v23, 4608 + %v25 = getelementptr i8, i8* %v3, i32 %v24 + %v26 = tail call fastcc i32 @f1(i32* nonnull undef, i32* nonnull undef, i32 0, i32 0) #0 + %v27 = bitcast i8* %v25 to i32* + %v28 = load i32, i32* getelementptr inbounds ([4 x [36 x i32]], [4 x [36 x i32]]* @g0, i32 0, i32 2, i32 3), align 4 + %v29 = sub nsw i32 7, %v20 + br label %b30 + +b30: ; preds = %b30, %b17 + %v31 = phi i32* [ undef, %b17 ], [ %v98, %b30 ] + %v32 = phi i32* [ %v27, %b17 ], [ undef, %b30 ] + %v33 = phi i32 [ %v18, %b17 ], [ %v99, %b30 ] + %v34 = icmp slt i32 %v33, %v19 + %v35 = select i1 %v34, i32 0, i32 undef + %v36 = load i32, i32* undef, align 4 + %v37 = ashr i32 %v36, %v29 + store i32 %v37, i32* undef, align 4 + %v38 = load i32, i32* undef, align 4 + %v39 = ashr i32 %v38, %v29 + store i32 %v39, i32* undef, align 4 + store i32 undef, i32* undef, align 4 + %v40 = load i32, i32* undef, align 4 + %v41 = ashr i32 %v40, %v29 + store i32 %v41, i32* undef, align 4 + %v42 = load i32, i32* %v31, align 4 + %v43 = load i32, i32* undef, align 4 + %v44 = load i32, i32* undef, align 4 + %v45 = load i32, i32* undef, align 4 + %v46 = load i32, i32* undef, align 4 + %v47 = sub nsw i32 %v45, 0 + %v48 = sub nsw i32 %v43, 0 + %v49 = sub nsw i32 %v42, %v48 + %v50 = ashr i32 %v49, 1 + %v51 = tail call i32 @llvm.hexagon.M2.mpy.up(i32 1859775393, i32 0) #1 + %v52 = shl i32 %v51, 1 + %v53 = add nsw i32 %v50, 0 + %v54 = sub nsw i32 %v50, 0 + %v55 = add nsw i32 %v53, %v52 + %v56 = tail call i32 @llvm.hexagon.M2.mpy.up(i32 2074309917, i32 undef) #1 + %v57 = shl i32 %v56, 2 + %v58 = add nsw i32 %v55, %v57 + %v59 = add nsw i32 %v54, 0 + %v60 = sub nsw i32 %v55, %v57 + %v61 = load i32, i32* undef, align 4 + %v62 = load i32, i32* null, align 4 + %v63 = load i32, i32* undef, align 4 + %v64 = load i32, i32* undef, align 4 + %v65 = load i32, i32* undef, align 4 + %v66 = sub nsw i32 %v64, 0 + %v67 = sub nsw i32 %v62, 0 + %v68 = sub nsw i32 %v61, %v67 + %v69 = ashr i32 %v68, 1 + %v70 = add nsw i32 %v69, 0 + %v71 = sub nsw i32 %v69, 0 + %v72 = add nsw i32 %v70, 0 + %v73 = sub nsw i32 %v70, 0 + %v74 = tail call i32 @llvm.hexagon.M2.mpy.up(i32 2074309917, i32 undef) #1 + %v75 = shl i32 %v74, 2 + %v76 = tail call i32 @llvm.hexagon.M2.mpy.up(i32 1518500250, i32 undef) #1 + %v77 = shl i32 %v76, 2 + %v78 = add nsw i32 %v72, %v75 + %v79 = add nsw i32 %v71, %v77 + %v80 = add nsw i32 %v73, 0 + call fastcc void @f0(i32* %v32, i32* nonnull undef, i32 %v35) #0 + %v81 = tail call i32 @llvm.hexagon.M2.mpy.up(i32 %v28, i32 %v60) #1 + %v82 = add nsw i32 %v81, 0 + store i32 %v82, i32* undef, align 4 + %v83 = tail call i32 @llvm.hexagon.M2.mpy.up(i32 undef, i32 %v59) #1 + %v84 = tail call i32 @llvm.hexagon.M2.mpy.up(i32 undef, i32 undef) #1 + %v85 = add i32 %v83, 0 + %v86 = add i32 %v85, %v84 + store i32 %v86, i32* undef, align 4 + %v87 = tail call i32 @llvm.hexagon.M2.mpy.up(i32 undef, i32 undef) #1 + %v88 = add nsw i32 %v87, 0 + store i32 %v88, i32* undef, align 4 + %v89 = load i32, i32* undef, align 8 + %v90 = shl i32 %v89, 2 + %v91 = tail call i32 @llvm.hexagon.M2.mpy.up(i32 undef, i32 %v58) #1 + %v92 = tail call i32 @llvm.hexagon.M2.mpy.up(i32 undef, i32 undef) #1 + %v93 = add i32 %v91, %v90 + %v94 = add i32 %v93, %v92 + store i32 %v94, i32* undef, align 4 + %v95 = ashr i32 %v78, 2 + store i32 %v95, i32* %v32, align 4 + %v96 = ashr i32 %v79, 2 + store i32 %v96, i32* undef, align 4 + %v97 = ashr i32 %v80, 2 + store i32 %v97, i32* undef, align 4 + %v98 = getelementptr inbounds i32, i32* %v31, i32 18 + %v99 = add nsw i32 %v33, 1 + br label %b30 +} + +declare i32 @llvm.hexagon.M2.mpy.up(i32, i32) #1 + +declare hidden fastcc void @f0(i32* nocapture readonly, i32* nocapture, i32) unnamed_addr #0 +declare hidden fastcc i32 @f1(i32* nocapture, i32* nocapture, i32, i32) unnamed_addr #0 + +attributes #0 = { nounwind "target-cpu"="hexagonv60" } +attributes #1 = { nounwind readnone }