Index: lib/CodeGen/LiveIntervalAnalysis.cpp =================================================================== --- lib/CodeGen/LiveIntervalAnalysis.cpp +++ lib/CodeGen/LiveIntervalAnalysis.cpp @@ -506,7 +506,8 @@ void LiveIntervals::shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg) { - DEBUG(dbgs() << "Shrink: " << SR << '\n'); + DEBUG(dbgs() << "Shrink: L" << PrintLaneMask(SR.LaneMask) + << ' ' << SR << '\n'); assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Can only shrink virtual registers"); // Find all the values used, including PHI kills. Index: lib/CodeGen/LiveRangeEdit.cpp =================================================================== --- lib/CodeGen/LiveRangeEdit.cpp +++ lib/CodeGen/LiveRangeEdit.cpp @@ -37,6 +37,11 @@ VRM->setIsSplitFromReg(VReg, VRM->getOriginal(OldReg)); } LiveInterval &LI = LIS.createEmptyInterval(VReg); + // Create empty subranges if the OldReg's interval has them. + LiveInterval &OldLI = LIS.getInterval(OldReg); + VNInfo::Allocator &Alloc = LIS.getVNInfoAllocator(); + for (LiveInterval::SubRange &S : OldLI.subranges()) + LI.createSubRange(Alloc, S.LaneMask); return LI; } @@ -328,6 +333,7 @@ // after all the allocations of the func are done. if (isOrigDef) { LiveInterval &NewLI = createEmptyIntervalFrom(Dest); + NewLI.removeEmptySubRanges(); VNInfo *VNI = NewLI.getNextValue(Idx, LIS.getVNInfoAllocator()); NewLI.addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), VNI)); pop_back(); Index: lib/CodeGen/SplitKit.h =================================================================== --- lib/CodeGen/SplitKit.h +++ lib/CodeGen/SplitKit.h @@ -324,6 +324,11 @@ return LRCalc[SpillMode != SM_Partition && RegIdx != 0]; } + /// Add a segment to the interval LI for the value number VNI. If LI has + /// subranges, corresponding segments will be added to them as well, but + /// with newly created value numbers. + void addDeadDef(LiveInterval &LI, VNInfo *VNI); + /// defValue - define a value in RegIdx from ParentVNI at Idx. /// Idx does not have to be ParentVNI->def, but it must be contained within /// ParentVNI's live range in ParentLI. The new value is added to the value Index: lib/CodeGen/SplitKit.cpp =================================================================== --- lib/CodeGen/SplitKit.cpp +++ lib/CodeGen/SplitKit.cpp @@ -379,6 +379,15 @@ } #endif +void SplitEditor::addDeadDef(LiveInterval &LI, VNInfo *VNI) { + SlotIndex Def = VNI->def; + LI.addSegment(LiveInterval::Segment(Def, Def.getDeadSlot(), VNI)); + for (LiveInterval::SubRange &S : LI.subranges()) { + VNInfo *V = S.getNextValue(Def, LIS.getVNInfoAllocator()); + S.addSegment(LiveInterval::Segment(Def, Def.getDeadSlot(), V)); + } +} + VNInfo *SplitEditor::defValue(unsigned RegIdx, const VNInfo *ParentVNI, SlotIndex Idx) { @@ -402,16 +411,15 @@ // If the previous value was a simple mapping, add liveness for it now. if (VNInfo *OldVNI = InsP.first->second.getPointer()) { - SlotIndex Def = OldVNI->def; - LI->addSegment(LiveInterval::Segment(Def, Def.getDeadSlot(), OldVNI)); - // No longer a simple mapping. Switch to a complex, non-forced mapping. - InsP.first->second = ValueForcePair(); + addDeadDef(*LI, OldVNI); + + // No longer a simple mapping. Switch to a complex mapping. If the + // interval has subranges, make it a forced mapping. + InsP.first->second = ValueForcePair(nullptr, LI->hasSubRanges()); } // This is a complex mapping, add liveness for VNI - SlotIndex Def = VNI->def; - LI->addSegment(LiveInterval::Segment(Def, Def.getDeadSlot(), VNI)); - + addDeadDef(*LI, VNI); return VNI; } @@ -429,9 +437,8 @@ // This was previously a single mapping. Make sure the old def is represented // by a trivial live range. - SlotIndex Def = VNI->def; - LiveInterval *LI = &LIS.getInterval(Edit->get(RegIdx)); - LI->addSegment(LiveInterval::Segment(Def, Def.getDeadSlot(), VNI)); + addDeadDef(LIS.getInterval(Edit->get(RegIdx)), VNI); + // Mark as complex mapped, forced. VFP = ValueForcePair(nullptr, true); } @@ -943,13 +950,13 @@ // The interval [Start;End) is continuously mapped to RegIdx, ParentVNI. DEBUG(dbgs() << " [" << Start << ';' << End << ")=" << RegIdx); - LiveRange &LR = LIS.getInterval(Edit->get(RegIdx)); + LiveInterval &LI = LIS.getInterval(Edit->get(RegIdx)); // Check for a simply defined value that can be blitted directly. ValueForcePair VFP = Values.lookup(std::make_pair(RegIdx, ParentVNI->id)); if (VNInfo *VNI = VFP.getPointer()) { DEBUG(dbgs() << ':' << VNI->id); - LR.addSegment(LiveInterval::Segment(Start, End, VNI)); + LI.addSegment(LiveInterval::Segment(Start, End, VNI)); Start = End; continue; } @@ -973,7 +980,7 @@ // The first block may be live-in, or it may have its own def. if (Start != BlockStart) { - VNInfo *VNI = LR.extendInBlock(BlockStart, std::min(BlockEnd, End)); + VNInfo *VNI = LI.extendInBlock(BlockStart, std::min(BlockEnd, End)); assert(VNI && "Missing def for complex mapped value"); DEBUG(dbgs() << ':' << VNI->id << "*BB#" << MBB->getNumber()); // MBB has its own def. Is it also live-out? @@ -993,7 +1000,7 @@ if (BlockStart == ParentVNI->def) { // This block has the def of a parent PHI, so it isn't live-in. assert(ParentVNI->isPHIDef() && "Non-phi defined at block start?"); - VNInfo *VNI = LR.extendInBlock(BlockStart, std::min(BlockEnd, End)); + VNInfo *VNI = LI.extendInBlock(BlockStart, std::min(BlockEnd, End)); assert(VNI && "Missing def for complex mapped parent PHI"); if (End >= BlockEnd) LRC.setLiveOutValue(&*MBB, VNI); // Live-out as well. @@ -1001,10 +1008,10 @@ // This block needs a live-in value. The last block covered may not // be live-out. if (End < BlockEnd) - LRC.addLiveInBlock(LR, MDT[&*MBB], End); + LRC.addLiveInBlock(LI, MDT[&*MBB], End); else { // Live-through, and we don't know the value. - LRC.addLiveInBlock(LR, MDT[&*MBB]); + LRC.addLiveInBlock(LI, MDT[&*MBB]); LRC.setLiveOutValue(&*MBB, nullptr); } } @@ -1025,35 +1032,69 @@ void SplitEditor::extendPHIKillRanges() { // Extend live ranges to be live-out for successor PHI values. - for (const VNInfo *PHIVNI : Edit->getParent().valnos) { - if (PHIVNI->isUnused() || !PHIVNI->isPHIDef()) - continue; - unsigned RegIdx = RegAssign.lookup(PHIVNI->def); - LiveRange &LR = LIS.getInterval(Edit->get(RegIdx)); - - // Check whether PHI is dead. - const LiveRange::Segment *Segment = LR.getSegmentContaining(PHIVNI->def); - assert(Segment != nullptr && "Missing segment for VNI"); - if (Segment->end == PHIVNI->def.getDeadSlot()) { - // This is a dead PHI. Remove it. - LR.removeSegment(*Segment, true); - continue; - } + auto RemoveDeadSegment = [] (SlotIndex Def, LiveRange &LR) -> bool { + const LiveRange::Segment *Seg = LR.getSegmentContaining(Def); + assert(Seg != nullptr && "Missing segment for VNI"); + if (Seg->end != Def.getDeadSlot()) + return false; + // This is a dead PHI. Remove it. + LR.removeSegment(*Seg, true); + return true; + }; - LiveRangeCalc &LRC = getLRCalc(RegIdx); - MachineBasicBlock *MBB = LIS.getMBBFromIndex(PHIVNI->def); - for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), - PE = MBB->pred_end(); PI != PE; ++PI) { - SlotIndex End = LIS.getMBBEndIdx(*PI); + auto ExtendPHIRange = [this] (MachineBasicBlock &B, LiveRangeCalc &LRC, + LiveRange &LR) -> void { + for (MachineBasicBlock *P : B.predecessors()) { + SlotIndex End = LIS.getMBBEndIdx(P); SlotIndex LastUse = End.getPrevSlot(); // The predecessor may not have a live-out value. That is OK, like an // undef PHI operand. - if (Edit->getParent().liveAt(LastUse)) { - assert(RegAssign.lookup(LastUse) == RegIdx && - "Different register assignment in phi predecessor"); + if (Edit->getParent().liveAt(LastUse)) LRC.extend(LR, End); - } } + }; + + // Visit each PHI def slot in the parent live interval. If the def is dead, + // remove it. Otherwise, extend the live interval to reach the end indexes + // of all predecessor blocks. + + // Each location in the parent interval may correspond to a different + // interval after splitting. Also, a slot index from the parent interval + // may contain PHI defs for the main range as well as one or more of the + // subranges. The same holds for each of the newly created intervals. + // To reduce the complexity of the traversal, collect locations of all + // PHI defs first from the parent interval (and its subranges), then for + // each location, visit the corresponding new interval and its subranges. + std::set PhiDefs; + auto AppendPhiDefs = [&PhiDefs] (LiveRange &LR) -> void { + for (const VNInfo *V : LR.valnos) + if (!V->isUnused() && V->isPHIDef()) + PhiDefs.insert(V->def); + }; + for (LiveInterval::SubRange &S : Edit->getParent().subranges()) + AppendPhiDefs(S); + AppendPhiDefs(Edit->getParent()); + + // The extending of the subranges must use a separate LiveRangeCalc, + // since the subranges can overlap. LRC caches some of its calculations + // making it unsuitable for use with overlapping ranges. + LiveRangeCalc SubLRC; + + for (SlotIndex Def : PhiDefs) { + unsigned RegIdx = RegAssign.lookup(Def); + LiveInterval &LI = LIS.getInterval(Edit->get(RegIdx)); + LiveRangeCalc &LRC = getLRCalc(RegIdx); + MachineBasicBlock &B = *LIS.getMBBFromIndex(Def); + + for (LiveInterval::SubRange &S : LI.subranges()) { + if (RemoveDeadSegment(Def, S)) + continue; + SubLRC.reset(&VRM.getMachineFunction(), LIS.getSlotIndexes(), &MDT, + &LIS.getVNInfoAllocator()); + ExtendPHIRange(B, SubLRC, S); + } + if (!RemoveDeadSegment(Def, LI)) + ExtendPHIRange(B, LRC, LI); } } @@ -1093,7 +1134,7 @@ if (MO.isDef()) { if (!MO.getSubReg() && !MO.isEarlyClobber()) continue; - // We may wan't to extend a live range for a partial redef, or for a use + // We may want to extend a live range for a partial redef, or for a use // tied to an early clobber. Idx = Idx.getPrevSlot(); if (!Edit->getParent().liveAt(Idx)) @@ -1101,7 +1142,22 @@ } else Idx = Idx.getRegSlot(true); - getLRCalc(RegIdx).extend(*LI, Idx.getNextSlot()); + SlotIndex Next = Idx.getNextSlot(); + if (LI->hasSubRanges()) { + LiveRangeCalc C; + unsigned Sub = MO.getSubReg(); + LaneBitmask LM = Sub != 0 ? TRI.getSubRegIndexLaneMask(Sub) + : MRI.getMaxLaneMaskForVReg(MO.getReg()); + for (LiveInterval::SubRange &S : LI->subranges()) { + if (S.empty() || !(S.LaneMask & LM)) + continue; + C.reset(&VRM.getMachineFunction(), LIS.getSlotIndexes(), &MDT, + &LIS.getVNInfoAllocator()); + C.extend(S, Next); + } + } + LiveRangeCalc &LRC = getLRCalc(RegIdx); + LRC.extend(*LI, Next); } } @@ -1166,7 +1222,6 @@ // Transfer the simply mapped values, check if any are skipped. bool Skipped = transferValues(); - // Rewrite virtual registers, possibly extending ranges. rewriteAssigned(Skipped); @@ -1182,6 +1237,7 @@ // Get rid of unused values and set phi-kill flags. for (LiveRangeEdit::iterator I = Edit->begin(), E = Edit->end(); I != E; ++I) { LiveInterval &LI = LIS.getInterval(*I); + LI.removeEmptySubRanges(); LI.RenumberValues(); } Index: lib/CodeGen/VirtRegMap.cpp =================================================================== --- lib/CodeGen/VirtRegMap.cpp +++ lib/CodeGen/VirtRegMap.cpp @@ -336,6 +336,7 @@ // we couldn't properly detect before. assert(LI.liveAt(BaseIndex) && "Reads of completely dead register should be marked undef already"); + assert(LI.hasSubRanges()); unsigned SubRegIdx = MO.getSubReg(); LaneBitmask UseMask = TRI->getSubRegIndexLaneMask(SubRegIdx); // See if any of the relevant subregister liveranges is defined at this point. Index: test/CodeGen/Hexagon/regalloc-bad-undef.mir =================================================================== --- /dev/null +++ test/CodeGen/Hexagon/regalloc-bad-undef.mir @@ -0,0 +1,209 @@ +# RUN: llc -march=hexagon -hexagon-subreg-liveness -start-after machine-scheduler -stop-after stack-slot-coloring %s 2>&1 -o /dev/null | FileCheck %s + +--- | + target triple = "hexagon" + + ; Function Attrs: nounwind optsize + define void @main() #0 { + entry: + br label %for.body + + for.body: ; preds = %if.end82, %entry + %lsr.iv = phi i32 [ %lsr.iv.next, %if.end82 ], [ 524288, %entry ] + %call9 = tail call i32 @lrand48() #0 + %conv10 = sext i32 %call9 to i64 + %shr11 = lshr i64 %conv10, 9 + %or12 = or i64 0, %shr11 + %call14 = tail call i32 @lrand48() #0 + %conv15138 = zext i32 %call14 to i64 + %shr16 = lshr i64 %conv15138, 9 + %0 = call i64 @llvm.hexagon.S2.extractup(i64 %conv15138, i32 22, i32 9) + %1 = shl i64 %0, 42 + %shl17 = shl i64 %shr16, 42 + %or22 = or i64 0, %1 + %or26 = or i64 %or22, 0 + %shr30 = lshr i64 undef, 25 + %2 = call i64 @llvm.hexagon.S2.extractup(i64 undef, i32 6, i32 25) + %and = and i64 %shr30, 63 + %sub = shl i64 2, %2 + %add = add i64 %sub, -1 + %shl37 = shl i64 %add, 0 + %call38 = tail call i32 @lrand48() #0 + %conv39141 = zext i32 %call38 to i64 + %shr40 = lshr i64 %conv39141, 25 + %3 = call i64 @llvm.hexagon.S2.extractup(i64 %conv39141, i32 6, i32 25) + %and41 = and i64 %shr40, 63 + %sub43 = shl i64 2, %3 + %add45 = add i64 %sub43, -1 + %call46 = tail call i32 @lrand48() #0 + %shr48 = lshr i64 undef, 25 + %4 = call i64 @llvm.hexagon.S2.extractup(i64 undef, i32 6, i32 25) + %and49 = and i64 %shr48, 63 + %shl50 = shl i64 %add45, %4 + %and52 = and i64 %shl37, %or12 + %and54 = and i64 %shl50, %or26 + store i64 %and54, i64* undef, align 8 + %cmp56 = icmp eq i64 %and52, 0 + br i1 %cmp56, label %for.end, label %if.end82 + + if.end82: ; preds = %for.body + %lsr.iv.next = add nsw i32 %lsr.iv, -1 + %exitcond = icmp eq i32 %lsr.iv.next, 0 + br i1 %exitcond, label %for.end, label %for.body + + for.end: ; preds = %if.end82, %for.body + unreachable + } + + declare i32 @lrand48() #0 + declare i64 @llvm.hexagon.S2.extractup(i64, i32, i32) #1 + + attributes #0 = { nounwind optsize "target-cpu"="hexagonv55" "target-features"="-hvx,-hvx-double" } + attributes #1 = { nounwind readnone } + +... +--- +name: main +alignment: 2 +exposesReturnsTwice: false +hasInlineAsm: false +allVRegsAllocated: false +isSSA: false +tracksRegLiveness: true +tracksSubRegLiveness: true +registers: + - { id: 0, class: intregs } + - { id: 1, class: intregs } + - { id: 2, class: intregs } + - { id: 3, class: intregs } + - { id: 4, class: doubleregs } + - { id: 5, class: intregs } + - { id: 6, class: doubleregs } + - { id: 7, class: doubleregs } + - { id: 8, class: doubleregs } + - { id: 9, class: doubleregs } + - { id: 10, class: intregs } + - { id: 11, class: doubleregs } + - { id: 12, class: doubleregs } + - { id: 13, class: doubleregs } + - { id: 14, class: intregs } + - { id: 15, class: doubleregs } + - { id: 16, class: doubleregs } + - { id: 17, class: intregs } + - { id: 18, class: doubleregs } + - { id: 19, class: intregs } + - { id: 20, class: doubleregs } + - { id: 21, class: doubleregs } + - { id: 22, class: doubleregs } + - { id: 23, class: intregs } + - { id: 24, class: doubleregs } + - { id: 25, class: predregs } + - { id: 26, class: predregs } + - { id: 27, class: intregs } + - { id: 28, class: intregs } + - { id: 29, class: doubleregs } + - { id: 30, class: intregs } + - { id: 31, class: intregs } + - { id: 32, class: doubleregs } + - { id: 33, class: intregs } + - { id: 34, class: intregs } + - { id: 35, class: doubleregs } + - { id: 36, class: doubleregs } + - { id: 37, class: intregs } + - { id: 38, class: intregs } + - { id: 39, class: doubleregs } + - { id: 40, class: doubleregs } + - { id: 41, class: intregs } + - { id: 42, class: intregs } + - { id: 43, class: doubleregs } + - { id: 44, class: intregs } + - { id: 45, class: intregs } + - { id: 46, class: doubleregs } + - { id: 47, class: doubleregs } + - { id: 48, class: doubleregs } + - { id: 49, class: doubleregs } + - { id: 50, class: doubleregs } + - { id: 51, class: doubleregs } + - { id: 52, class: intregs } + - { id: 53, class: intregs } + - { id: 54, class: intregs } + - { id: 55, class: doubleregs } + - { id: 56, class: doubleregs } + - { id: 57, class: intregs } + - { id: 58, class: intregs } + - { id: 59, class: intregs } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: true + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + successors: %bb.1.for.body + + %59 = A2_tfrsi 524288 + undef %32:subreg_hireg = A2_tfrsi 0 + %8 = S2_extractup undef %9, 6, 25 + %47 = A2_tfrpi 2 + %13 = A2_tfrpi -1 + %13 = S2_asl_r_p_acc %13, %47, %8:subreg_loreg + %51 = A2_tfrpi 0 + + ; CHECK: %d2 = S2_extractup undef %d0, 6, 25 + ; CHECK: %d0 = A2_tfrpi 2 + ; CHECK: %d13 = A2_tfrpi -1 + ; CHECK-NOT: undef %r4 + + bb.1.for.body: + successors: %bb.3.for.end, %bb.2.if.end82 + + ADJCALLSTACKDOWN 0, implicit-def dead %r29, implicit-def dead %r30, implicit %r31, implicit %r30, implicit %r29 + J2_call @lrand48, implicit-def dead %d0, implicit-def dead %d1, implicit-def dead %d2, implicit-def dead %d3, implicit-def dead %d4, implicit-def dead %d5, implicit-def dead %d6, implicit-def dead %d7, implicit-def dead %r28, implicit-def dead %r31, implicit-def dead %p0, implicit-def dead %p1, implicit-def dead %p2, implicit-def dead %p3, implicit-def dead %m0, implicit-def dead %m1, implicit-def dead %lc0, implicit-def dead %lc1, implicit-def dead %sa0, implicit-def dead %sa1, implicit-def dead %usr, implicit-def %usr_ovf, implicit-def dead %cs0, implicit-def dead %cs1, implicit-def dead %w0, implicit-def dead %w1, implicit-def dead %w2, implicit-def dead %w3, implicit-def dead %w4, implicit-def dead %w5, implicit-def dead %w6, implicit-def dead %w7, implicit-def dead %w8, implicit-def dead %w9, implicit-def dead %w10, implicit-def dead %w11, implicit-def dead %w12, implicit-def dead %w13, implicit-def dead %w14, implicit-def dead %w15, implicit-def dead %q0, implicit-def dead %q1, implicit-def dead %q2, implicit-def dead %q3, implicit-def %r0 + ADJCALLSTACKUP 0, 0, implicit-def dead %r29, implicit-def dead %r30, implicit-def dead %r31, implicit %r29 + undef %29:subreg_loreg = COPY killed %r0 + %29:subreg_hireg = S2_asr_i_r %29:subreg_loreg, 31 + ADJCALLSTACKDOWN 0, implicit-def dead %r29, implicit-def dead %r30, implicit %r31, implicit %r30, implicit %r29 + J2_call @lrand48, implicit-def dead %d0, implicit-def dead %d1, implicit-def dead %d2, implicit-def dead %d3, implicit-def dead %d4, implicit-def dead %d5, implicit-def dead %d6, implicit-def dead %d7, implicit-def dead %r28, implicit-def dead %r31, implicit-def dead %p0, implicit-def dead %p1, implicit-def dead %p2, implicit-def dead %p3, implicit-def dead %m0, implicit-def dead %m1, implicit-def dead %lc0, implicit-def dead %lc1, implicit-def dead %sa0, implicit-def dead %sa1, implicit-def dead %usr, implicit-def %usr_ovf, implicit-def dead %cs0, implicit-def dead %cs1, implicit-def dead %w0, implicit-def dead %w1, implicit-def dead %w2, implicit-def dead %w3, implicit-def dead %w4, implicit-def dead %w5, implicit-def dead %w6, implicit-def dead %w7, implicit-def dead %w8, implicit-def dead %w9, implicit-def dead %w10, implicit-def dead %w11, implicit-def dead %w12, implicit-def dead %w13, implicit-def dead %w14, implicit-def dead %w15, implicit-def dead %q0, implicit-def dead %q1, implicit-def dead %q2, implicit-def dead %q3, implicit-def %r0 + ADJCALLSTACKUP 0, 0, implicit-def dead %r29, implicit-def dead %r30, implicit-def dead %r31, implicit %r29 + %32:subreg_loreg = COPY killed %r0 + %7 = S2_extractup %32, 22, 9 + ADJCALLSTACKDOWN 0, implicit-def dead %r29, implicit-def dead %r30, implicit %r31, implicit %r30, implicit %r29 + J2_call @lrand48, implicit-def dead %d0, implicit-def dead %d1, implicit-def dead %d2, implicit-def dead %d3, implicit-def dead %d4, implicit-def dead %d5, implicit-def dead %d6, implicit-def dead %d7, implicit-def dead %r28, implicit-def dead %r31, implicit-def dead %p0, implicit-def dead %p1, implicit-def dead %p2, implicit-def dead %p3, implicit-def dead %m0, implicit-def dead %m1, implicit-def dead %lc0, implicit-def dead %lc1, implicit-def dead %sa0, implicit-def dead %sa1, implicit-def dead %usr, implicit-def %usr_ovf, implicit-def dead %cs0, implicit-def dead %cs1, implicit-def dead %w0, implicit-def dead %w1, implicit-def dead %w2, implicit-def dead %w3, implicit-def dead %w4, implicit-def dead %w5, implicit-def dead %w6, implicit-def dead %w7, implicit-def dead %w8, implicit-def dead %w9, implicit-def dead %w10, implicit-def dead %w11, implicit-def dead %w12, implicit-def dead %w13, implicit-def dead %w14, implicit-def dead %w15, implicit-def dead %q0, implicit-def dead %q1, implicit-def dead %q2, implicit-def dead %q3, implicit-def %r0 + ADJCALLSTACKUP 0, 0, implicit-def dead %r29, implicit-def dead %r30, implicit-def dead %r31, implicit %r29 + undef %43:subreg_loreg = COPY killed %r0 + %43:subreg_hireg = COPY %32:subreg_hireg + %16 = S2_extractup %43, 6, 25 + %18 = A2_tfrpi -1 + %18 = S2_asl_r_p_acc %18, %47, %16:subreg_loreg + ADJCALLSTACKDOWN 0, implicit-def dead %r29, implicit-def dead %r30, implicit %r31, implicit %r30, implicit %r29 + J2_call @lrand48, implicit-def dead %d0, implicit-def dead %d1, implicit-def dead %d2, implicit-def dead %d3, implicit-def dead %d4, implicit-def dead %d5, implicit-def dead %d6, implicit-def dead %d7, implicit-def dead %r28, implicit-def dead %r31, implicit-def dead %p0, implicit-def dead %p1, implicit-def dead %p2, implicit-def dead %p3, implicit-def dead %m0, implicit-def dead %m1, implicit-def dead %lc0, implicit-def dead %lc1, implicit-def dead %sa0, implicit-def dead %sa1, implicit-def dead %usr, implicit-def %usr_ovf, implicit-def dead %cs0, implicit-def dead %cs1, implicit-def dead %w0, implicit-def dead %w1, implicit-def dead %w2, implicit-def dead %w3, implicit-def dead %w4, implicit-def dead %w5, implicit-def dead %w6, implicit-def dead %w7, implicit-def dead %w8, implicit-def dead %w9, implicit-def dead %w10, implicit-def dead %w11, implicit-def dead %w12, implicit-def dead %w13, implicit-def dead %w14, implicit-def dead %w15, implicit-def dead %q0, implicit-def dead %q1, implicit-def dead %q2, implicit-def dead %q3 + ADJCALLSTACKUP 0, 0, implicit-def dead %r29, implicit-def dead %r30, implicit-def dead %r31, implicit %r29 + %22 = S2_asl_r_p %18, %8:subreg_loreg + %21 = COPY %13 + %21 = S2_lsr_i_p_and %21, %29, 9 + %22 = S2_asl_i_p_and %22, %7, 42 + S2_storerd_io undef %23, 0, %22 :: (store 8 into `i64* undef`) + %25 = C2_cmpeqp %21, %51 + J2_jumpt %25, %bb.3.for.end, implicit-def dead %pc + J2_jump %bb.2.if.end82, implicit-def dead %pc + + bb.2.if.end82: + successors: %bb.3.for.end, %bb.1.for.body + + %59 = A2_addi %59, -1 + %26 = C2_cmpeqi %59, 0 + J2_jumpf %26, %bb.1.for.body, implicit-def dead %pc + J2_jump %bb.3.for.end, implicit-def dead %pc + + bb.3.for.end: + +...