Author: Ikhlas Ajbar Date: 2026-07-25T17:28:57+02:00 New Revision: d6d907272ed54ea40d6331de8501607ec183190d
URL: https://github.com/llvm/llvm-project/commit/d6d907272ed54ea40d6331de8501607ec183190d DIFF: https://github.com/llvm/llvm-project/commit/d6d907272ed54ea40d6331de8501607ec183190d.diff LOG: [Pipeliner] Use VRMapPhi to generate phi in epilog (#211723) When generating a phi in the epilog block corresponding to an existing phi in the loop, the loop value should come from the new phi generated in the kernel block (for a non-phi instruction in the loop) rather than directly from the value map of the previous stage. The new phis generated by generatePhis for non-phi instructions are stored in VRMapPhi. Thread VRMapPhi through generateExistingPhis and add a helper getMapPhiReg that returns the phi-generated register when available, falling back to VRMap otherwise. Without this fix, the epilog can pick up the initial prolog value of a loop-carried register instead of the last kernel-iteration value, producing incorrect results for pipelined loops with two or more stages that carry values across iterations. This has been observed on Hexagon with the modulo scheduled epilog of a right-shift-with-carry loop after loop unrolling. Fixes #208943 (cherry picked from commit f61e1fac80cfda6af7ef615a0eb84d58d3c56105) Added: llvm/test/CodeGen/Hexagon/swp-epilog-carry.ll llvm/test/CodeGen/Hexagon/swp-epilog-phi12.mir Modified: llvm/include/llvm/CodeGen/ModuloSchedule.h llvm/lib/CodeGen/ModuloSchedule.cpp Removed: ################################################################################ diff --git a/llvm/include/llvm/CodeGen/ModuloSchedule.h b/llvm/include/llvm/CodeGen/ModuloSchedule.h index 87dc77a329a7e..586a3a157f3e0 100644 --- a/llvm/include/llvm/CodeGen/ModuloSchedule.h +++ b/llvm/include/llvm/CodeGen/ModuloSchedule.h @@ -197,9 +197,9 @@ class ModuloScheduleExpander { MBBVectorTy &PrologBBs); void generateExistingPhis(MachineBasicBlock *NewBB, MachineBasicBlock *BB1, MachineBasicBlock *BB2, MachineBasicBlock *KernelBB, - ValueMapTy *VRMap, InstrMapTy &InstrMap, - unsigned LastStageNum, unsigned CurStageNum, - bool IsLast); + ValueMapTy *VRMap, ValueMapTy *VRMapPhi, + InstrMapTy &InstrMap, unsigned LastStageNum, + unsigned CurStageNum, bool IsLast); void generatePhis(MachineBasicBlock *NewBB, MachineBasicBlock *BB1, MachineBasicBlock *BB2, MachineBasicBlock *KernelBB, ValueMapTy *VRMap, ValueMapTy *VRMapPhi, @@ -233,6 +233,16 @@ class ModuloScheduleExpander { Register NewReg, Register PrevReg = Register()); bool isLoopCarried(MachineInstr &Phi); + // Check if register at StageNum is defined by a new phi instruction generated + // in kernel or epilog. If found, return register from VRMapPhi. Else return + // register from VRMap. + Register getMapPhiReg(ValueMapTy *VRMap, ValueMapTy *VRMapPhi, + unsigned StageNum, Register OldReg) { + if (Register R = VRMapPhi[StageNum].lookup(OldReg)) + return R; + return VRMap[StageNum].lookup(OldReg); + } + /// Return the max. number of stages/iterations that can occur between a /// register definition and its uses. unsigned getStagesForReg(Register Reg, unsigned CurStage) { diff --git a/llvm/lib/CodeGen/ModuloSchedule.cpp b/llvm/lib/CodeGen/ModuloSchedule.cpp index 36db54cc516e7..bd2af691470c4 100644 --- a/llvm/lib/CodeGen/ModuloSchedule.cpp +++ b/llvm/lib/CodeGen/ModuloSchedule.cpp @@ -161,7 +161,7 @@ void ModuloScheduleExpander::generatePipelinedLoop() { KernelBB->replaceSuccessor(BB, KernelBB); generateExistingPhis(KernelBB, PrologBBs.back(), KernelBB, KernelBB, VRMap, - InstrMap, MaxStageCount, MaxStageCount, false); + VRMapPhi, InstrMap, MaxStageCount, MaxStageCount, false); generatePhis(KernelBB, PrologBBs.back(), KernelBB, KernelBB, VRMap, VRMapPhi, InstrMap, MaxStageCount, MaxStageCount, false); @@ -313,7 +313,7 @@ void ModuloScheduleExpander::generateEpilog( } } generateExistingPhis(NewBB, PrologBBs[i - 1], PredBB, KernelBB, VRMap, - InstrMap, LastStage, EpilogStage, i == 1); + VRMapPhi, InstrMap, LastStage, EpilogStage, i == 1); generatePhis(NewBB, PrologBBs[i - 1], PredBB, KernelBB, VRMap, VRMapPhi, InstrMap, LastStage, EpilogStage, i == 1); PredBB = NewBB; @@ -370,8 +370,9 @@ static bool hasUseAfterLoop(Register Reg, MachineBasicBlock *BB, /// creation of new Phis. void ModuloScheduleExpander::generateExistingPhis( MachineBasicBlock *NewBB, MachineBasicBlock *BB1, MachineBasicBlock *BB2, - MachineBasicBlock *KernelBB, ValueMapTy *VRMap, InstrMapTy &InstrMap, - unsigned LastStageNum, unsigned CurStageNum, bool IsLast) { + MachineBasicBlock *KernelBB, ValueMapTy *VRMap, ValueMapTy *VRMapPhi, + InstrMapTy &InstrMap, unsigned LastStageNum, unsigned CurStageNum, + bool IsLast) { // Compute the stage number for the initial value of the Phi, which // comes from the prolog. The prolog to use depends on to which kernel/ // epilog that we're adding the Phi. @@ -499,23 +500,26 @@ void ModuloScheduleExpander::generateExistingPhis( // contains the last definition of the Phi. if (np == 0 && PrevStage == LastStageNum && (StageScheduled != 0 || LoopValStage != 0) && - VRMap[PrevStage - StageDiffAdj].count(LoopVal)) - PhiOp2 = VRMap[PrevStage - StageDiffAdj][LoopVal]; + getMapPhiReg(VRMap, VRMapPhi, PrevStage - StageDiffAdj, LoopVal)) + PhiOp2 = + getMapPhiReg(VRMap, VRMapPhi, PrevStage - StageDiffAdj, LoopVal); // Use the value defined by the Phi. We add one because we switch // from looking at the loop value to the Phi definition. else if (np > 0 && PrevStage == LastStageNum && - VRMap[PrevStage - np + 1].count(Def)) - PhiOp2 = VRMap[PrevStage - np + 1][Def]; + getMapPhiReg(VRMap, VRMapPhi, PrevStage - np + 1, Def)) + PhiOp2 = getMapPhiReg(VRMap, VRMapPhi, PrevStage - np + 1, Def); // Use the loop value defined in the kernel. else if (static_cast<unsigned>(LoopValStage) > PrologStage + 1 && - VRMap[PrevStage - StageDiffAdj - np].count(LoopVal)) - PhiOp2 = VRMap[PrevStage - StageDiffAdj - np][LoopVal]; + getMapPhiReg(VRMap, VRMapPhi, PrevStage - StageDiffAdj - np, + LoopVal)) + PhiOp2 = getMapPhiReg(VRMap, VRMapPhi, PrevStage - StageDiffAdj - np, + LoopVal); // Use the value defined by the Phi, unless we're generating the first // epilog and the Phi refers to a Phi in a diff erent stage. - else if (VRMap[PrevStage - np].count(Def) && + else if (getMapPhiReg(VRMap, VRMapPhi, PrevStage - np, Def) && (!LoopDefIsPhi || (PrevStage != LastStageNum) || (LoopValStage == StageScheduled))) - PhiOp2 = VRMap[PrevStage - np][Def]; + PhiOp2 = getMapPhiReg(VRMap, VRMapPhi, PrevStage - np, Def); } // Check if we can reuse an existing Phi. This occurs when a Phi diff --git a/llvm/test/CodeGen/Hexagon/swp-epilog-carry.ll b/llvm/test/CodeGen/Hexagon/swp-epilog-carry.ll new file mode 100644 index 0000000000000..e60c736e0fd77 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/swp-epilog-carry.ll @@ -0,0 +1,190 @@ +; RUN: llc -mtriple=hexagon -mcpu=hexagonv68 -O2 < %s | FileCheck %s + +; Regression test for https://github.com/llvm/llvm-project/issues/208943. +; +; The pipelined epilog of the unrolled remainder loop must use the carry +; produced by the last kernel iteration, not the initial carry from the +; prolog. The buggy code emits an extra "r4 = r5" copy between :endloop0 +; and the epilog packet that clobbers the correct carry. + +; CHECK-LABEL: mp_div_2d: + +; CHECK-LABEL: %for.body.epil +; CHECK: loop0(.[[KERNEL:LBB[0-9]+_[0-9]+]], +; CHECK: .[[KERNEL]]:{{.*}}%for.body.epil +; CHECK: [[CARRY:r[0-9]+]] |= asl([[PRIOR:r[0-9]+]],r{{[0-9]+}}) +; CHECK-NEXT: [[PRIOR]] = r{{[0-9]+}} +; CHECK: :endloop0 +; CHECK-NOT: [[PRIOR]] = r +; CHECK: [[CARRY]] |= asl([[PRIOR]],r{{[0-9]+}}) +; CHECK-NEXT: memw({{.*}}) = [[CARRY]].new + +define dso_local i32 @mp_div_2d(ptr noundef %a, i32 noundef %b, ptr noundef %c, ptr noundef %d) #0 { +entry: + %cmp = icmp slt i32 %b, 1 + %call = tail call i32 @mp_copy(ptr noundef %a, ptr noundef %c) + br i1 %cmp, label %if.then, label %if.end3 + +if.then: + %cmp1.not = icmp eq ptr %d, null + br i1 %cmp1.not, label %cleanup, label %if.then2 + +if.then2: + tail call void @mp_zero(ptr noundef nonnull %d) + br label %cleanup + +if.end3: + %cmp5.not = icmp eq i32 %call, 0 + br i1 %cmp5.not, label %if.end7, label %cleanup + +if.end7: + %cmp8.not = icmp eq ptr %d, null + br i1 %cmp8.not, label %if.end14, label %if.then9 + +if.then9: + %call10 = tail call i32 @mp_mod_2d(ptr noundef %a, i32 noundef %b, ptr noundef nonnull %d) + %cmp11.not = icmp eq i32 %call10, 0 + br i1 %cmp11.not, label %if.end14, label %cleanup + +if.end14: + %cmp15 = icmp samesign ugt i32 %b, 27 + br i1 %cmp15, label %if.then16, label %if.end17 + +if.then16: + %div = udiv i32 %b, 28 + tail call void @mp_rshd(ptr noundef %c, i32 noundef %div) + br label %if.end17 + +if.end17: + %rem = urem i32 %b, 28 + %cmp18.not = icmp eq i32 %rem, 0 + br i1 %cmp18.not, label %if.end26, label %if.then19 + +if.then19: + %notmask = shl nsw i32 -1, %rem + %sub = xor i32 %notmask, -1 + %sub20 = sub nuw nsw i32 28, %rem + %0 = load i32, ptr %c, align 4 + %cmp2455 = icmp sgt i32 %0, 0 + br i1 %cmp2455, label %for.body.preheader, label %if.end26 + +for.body.preheader: + %dp = getelementptr inbounds nuw i8, ptr %c, i32 12 + %1 = load ptr, ptr %dp, align 4 + %2 = getelementptr [4 x i8], ptr %1, i32 %0 + %add.ptr = getelementptr i8, ptr %2, i32 -4 + %xtraiter = and i32 %0, 7 + %3 = icmp ult i32 %0, 8 + br i1 %3, label %for.body.epil.preheader, label %for.body.preheader.new + +for.body.preheader.new: + %unroll_iter = and i32 %0, 2147483640 + br label %for.body + +for.body: + %r.058 = phi i32 [ 0, %for.body.preheader.new ], [ %and.7, %for.body ] + %tmpc.057 = phi ptr [ %add.ptr, %for.body.preheader.new ], [ %incdec.ptr.7, %for.body ] + %niter = phi i32 [ 0, %for.body.preheader.new ], [ %niter.next.7, %for.body ] + %4 = load i32, ptr %tmpc.057, align 4 + %shr = lshr i32 %4, %rem + %shl25 = shl i32 %r.058, %sub20 + %or = or i32 %shr, %shl25 + store i32 %or, ptr %tmpc.057, align 4 + %incdec.ptr = getelementptr inbounds i8, ptr %tmpc.057, i32 -4 + %5 = load i32, ptr %incdec.ptr, align 4 + %shr.1 = lshr i32 %5, %rem + %6 = shl i32 %4, %sub20 + %shl25.1 = and i32 %6, 268435455 + %or.1 = or i32 %shr.1, %shl25.1 + store i32 %or.1, ptr %incdec.ptr, align 4 + %incdec.ptr.1 = getelementptr inbounds i8, ptr %tmpc.057, i32 -8 + %7 = load i32, ptr %incdec.ptr.1, align 4 + %shr.2 = lshr i32 %7, %rem + %8 = shl i32 %5, %sub20 + %shl25.2 = and i32 %8, 268435455 + %or.2 = or i32 %shr.2, %shl25.2 + store i32 %or.2, ptr %incdec.ptr.1, align 4 + %incdec.ptr.2 = getelementptr inbounds i8, ptr %tmpc.057, i32 -12 + %9 = load i32, ptr %incdec.ptr.2, align 4 + %shr.3 = lshr i32 %9, %rem + %10 = shl i32 %7, %sub20 + %shl25.3 = and i32 %10, 268435455 + %or.3 = or i32 %shr.3, %shl25.3 + store i32 %or.3, ptr %incdec.ptr.2, align 4 + %incdec.ptr.3 = getelementptr inbounds i8, ptr %tmpc.057, i32 -16 + %11 = load i32, ptr %incdec.ptr.3, align 4 + %shr.4 = lshr i32 %11, %rem + %12 = shl i32 %9, %sub20 + %shl25.4 = and i32 %12, 268435455 + %or.4 = or i32 %shr.4, %shl25.4 + store i32 %or.4, ptr %incdec.ptr.3, align 4 + %incdec.ptr.4 = getelementptr inbounds i8, ptr %tmpc.057, i32 -20 + %13 = load i32, ptr %incdec.ptr.4, align 4 + %shr.5 = lshr i32 %13, %rem + %14 = shl i32 %11, %sub20 + %shl25.5 = and i32 %14, 268435455 + %or.5 = or i32 %shr.5, %shl25.5 + store i32 %or.5, ptr %incdec.ptr.4, align 4 + %incdec.ptr.5 = getelementptr inbounds i8, ptr %tmpc.057, i32 -24 + %15 = load i32, ptr %incdec.ptr.5, align 4 + %shr.6 = lshr i32 %15, %rem + %16 = shl i32 %13, %sub20 + %shl25.6 = and i32 %16, 268435455 + %or.6 = or i32 %shr.6, %shl25.6 + store i32 %or.6, ptr %incdec.ptr.5, align 4 + %incdec.ptr.6 = getelementptr inbounds i8, ptr %tmpc.057, i32 -28 + %17 = load i32, ptr %incdec.ptr.6, align 4 + %and.7 = and i32 %17, %sub + %shr.7 = lshr i32 %17, %rem + %18 = shl i32 %15, %sub20 + %shl25.7 = and i32 %18, 268435455 + %or.7 = or i32 %shr.7, %shl25.7 + store i32 %or.7, ptr %incdec.ptr.6, align 4 + %incdec.ptr.7 = getelementptr inbounds i8, ptr %tmpc.057, i32 -32 + %niter.next.7 = add i32 %niter, 8 + %niter.ncmp.7 = icmp eq i32 %niter.next.7, %unroll_iter + br i1 %niter.ncmp.7, label %if.end26.loopexit.unr-lcssa, label %for.body + +if.end26.loopexit.unr-lcssa: + %lcmp.mod.not = icmp eq i32 %xtraiter, 0 + br i1 %lcmp.mod.not, label %if.end26, label %for.body.epil.preheader + +for.body.epil.preheader: + %r.058.epil.init = phi i32 [ 0, %for.body.preheader ], [ %and.7, %if.end26.loopexit.unr-lcssa ] + %tmpc.057.epil.init = phi ptr [ %add.ptr, %for.body.preheader ], [ %incdec.ptr.7, %if.end26.loopexit.unr-lcssa ] + %lcmp.mod59 = icmp ne i32 %xtraiter, 0 + tail call void @llvm.assume(i1 %lcmp.mod59) + br label %for.body.epil + +for.body.epil: + %r.058.epil = phi i32 [ %and.epil, %for.body.epil ], [ %r.058.epil.init, %for.body.epil.preheader ] + %tmpc.057.epil = phi ptr [ %incdec.ptr.epil, %for.body.epil ], [ %tmpc.057.epil.init, %for.body.epil.preheader ] + %epil.iter = phi i32 [ %epil.iter.next, %for.body.epil ], [ 0, %for.body.epil.preheader ] + %19 = load i32, ptr %tmpc.057.epil, align 4 + %and.epil = and i32 %19, %sub + %shr.epil = lshr i32 %19, %rem + %shl25.epil = shl i32 %r.058.epil, %sub20 + %or.epil = or i32 %shr.epil, %shl25.epil + store i32 %or.epil, ptr %tmpc.057.epil, align 4 + %incdec.ptr.epil = getelementptr inbounds i8, ptr %tmpc.057.epil, i32 -4 + %epil.iter.next = add i32 %epil.iter, 1 + %epil.iter.cmp.not = icmp eq i32 %epil.iter.next, %xtraiter + br i1 %epil.iter.cmp.not, label %if.end26, label %for.body.epil + +if.end26: + tail call void @mp_clamp(ptr noundef %c) + br label %cleanup + +cleanup: + %retval.0 = phi i32 [ 0, %if.end26 ], [ %call, %if.then ], [ %call, %if.end3 ], [ %call, %if.then2 ], [ %call10, %if.then9 ] + ret i32 %retval.0 +} + +declare i32 @mp_copy(ptr noundef, ptr noundef) +declare void @mp_zero(ptr noundef) +declare i32 @mp_mod_2d(ptr noundef, i32 noundef, ptr noundef) +declare void @mp_rshd(ptr noundef, i32 noundef) +declare void @mp_clamp(ptr noundef) +declare void @llvm.assume(i1 noundef) + +attributes #0 = { nounwind "target-cpu"="hexagonv68" } diff --git a/llvm/test/CodeGen/Hexagon/swp-epilog-phi12.mir b/llvm/test/CodeGen/Hexagon/swp-epilog-phi12.mir new file mode 100644 index 0000000000000..6a5d6c9501353 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/swp-epilog-phi12.mir @@ -0,0 +1,148 @@ +# RUN: llc -march=hexagon -run-pass=pipeliner -debug-only=pipeliner %s -o - 2>&1 > /dev/null | FileCheck %s + +# Test that the phi in the epilog block generated for an existing phi +# in the loop, obtains loop value from phi generated in the kernel block. +# Phis generated in kernel for non-phi instructions in the loop are stored +# in separate data structure and need to be used during existing phi generation +# in epilog. + +# CHECK: prolog: +# CHECK: bb.[[BB0:([0-9]+)]] +# CHECK: %[[REG0:([0-9]+)]]:intregs = L2_loadri_io %{{.*}}%ir.a +# CHECK: New block +# CHECK: bb.[[BB1:([0-9]+)]] +# CHECK: %[[REG1:([0-9]+)]]:intregs = PHI %[[REG0]]:intregs, %{{.*}} +# CHECK: epilog: +# CHECK: %{{[0-9]+}}:intregs = PHI %{{[0-9]+}}:intregs, %bb.[[BB0]], %[[REG1]]:intregs, %bb.[[BB1]] + +--- | + target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048" + target triple = "hexagon" + + define dso_local void @bar(ptr nocapture noundef readonly %i, ptr nocapture noundef readonly %j, ptr nocapture noundef writeonly %k, i32 noundef %l, i32 noundef %m, i32 noundef %n) local_unnamed_addr #0 { + entry: + %a = getelementptr i8, ptr %i, i32 4 + %b = getelementptr i8, ptr %i, i32 16 + %c = getelementptr i8, ptr %k, i32 4 + %d = getelementptr i8, ptr %k, i32 16 + ret void + } + + attributes #0 = { nofree nosync nounwind memory(readwrite, inaccessiblemem: none) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv69" "target-features"="+v69,-long-calls" } + + !0 = !{!"Simple C/C++ TBAA"} + +... +--- +name: bar +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +isOutlined: false +failsVerification: false +registers: + - { id: 0, class: doubleregs, preferred-register: '' } + - { id: 1, class: doubleregs, preferred-register: '' } + - { id: 2, class: intregs, preferred-register: '' } + - { id: 3, class: intregs, preferred-register: '' } + - { id: 4, class: intregs, preferred-register: '' } + - { id: 5, class: intregs, preferred-register: '' } + - { id: 6, class: intregs, preferred-register: '' } + - { id: 7, class: intregs, preferred-register: '' } + - { id: 8, class: intregs, preferred-register: '' } + - { id: 9, class: intregs, preferred-register: '' } + - { id: 10, class: intregs, preferred-register: '' } + - { id: 11, class: doubleregs, preferred-register: '' } + - { id: 12, class: doubleregs, preferred-register: '' } + - { id: 13, class: intregs, preferred-register: '' } + - { id: 14, class: intregs, preferred-register: '' } + - { id: 15, class: intregs, preferred-register: '' } + - { id: 16, class: intregs, preferred-register: '' } + - { id: 17, class: intregs, preferred-register: '' } + - { id: 18, class: doubleregs, preferred-register: '' } + - { id: 19, class: intregs, preferred-register: '' } + - { id: 20, class: intregs, preferred-register: '' } + - { id: 21, class: doubleregs, preferred-register: '' } + - { id: 22, class: doubleregs, preferred-register: '' } + - { id: 23, class: intregs, preferred-register: '' } + - { id: 24, class: doubleregs, preferred-register: '' } + - { id: 25, class: intregs, preferred-register: '' } + - { id: 26, class: intregs, preferred-register: '' } + - { id: 27, class: intregs, preferred-register: '' } + - { id: 28, class: doubleregs, preferred-register: '' } + - { id: 29, class: intregs, preferred-register: '' } + - { id: 30, class: intregs, preferred-register: '' } + - { id: 31, class: doubleregs, preferred-register: '' } + - { id: 32, class: intregs, preferred-register: '' } + - { id: 33, class: intregs, preferred-register: '' } + - { id: 34, class: intregs, preferred-register: '' } + - { id: 35, class: predregs, preferred-register: '' } +liveins: + - { reg: '$r0', virtual-reg: '%0' } + - { reg: '$r1', virtual-reg: '%1' } + - { reg: '$r2', virtual-reg: '%2' } + - { reg: '$r3', virtual-reg: '%3' } + - { reg: '$r4', virtual-reg: '%4' } + - { reg: '$r5', virtual-reg: '%5' } +body: | + bb.0.entry: + successors: %bb.1, %bb.3 + liveins: $r0, $r1, $r2, $r3, $r4, $r5 + + %5:intregs = COPY $r5 + %4:intregs = COPY $r4 + %3:intregs = COPY $r3 + %2:intregs = COPY $r2 + %1:doubleregs = COPY $r1 + %0:doubleregs = COPY $r0 + %6:intregs, %7:intregs = L2_loadri_pi %3, 12 + %8:intregs, %9:intregs = L2_loadri_pi %4, 12 + %35:predregs = C2_cmpgti %8, 0 + J2_jumpf %35, %bb.3, implicit-def dead $pc + J2_jump %bb.1, implicit-def dead $pc + + bb.1: + successors: %bb.2 + + J2_loop0r %bb.2, %8, implicit-def $lc0, implicit-def $sa0, implicit-def $usr + J2_jump %bb.2, implicit-def $pc + + bb.2: + successors: %bb.3, %bb.2 + + %10:intregs = PHI %7, %bb.1, %25, %bb.2 + %11:doubleregs = PHI %0, %bb.1, %18, %bb.2 + %12:doubleregs = PHI %1, %bb.1, %21, %bb.2 + %13:intregs = PHI %2, %bb.1, %17, %bb.2 + %14:intregs = PHI %9, %bb.1, %26, %bb.2 + %15:intregs = PHI %5, %bb.1, %20, %bb.2 + %16:intregs = PHI %6, %bb.1, %19, %bb.2 + %22:doubleregs = M2_cmacs_s1 %12, %15, %13, implicit-def dead $usr_ovf + %17:intregs = L2_loadri_io %14, 4 :: (load (s32) from %ir.a + 8, !tbaa !0) + %23:intregs, %26:intregs = L2_loadri_pi %14, 8 :: (load (s32) from %ir.b + 8, !tbaa !0) + %24:doubleregs = M2_cmacs_s1 %11, %16, %13, implicit-def dead $usr_ovf + %18:doubleregs = M2_cmacs_s1 %24, %15, %23, implicit-def dead $usr_ovf + %19:intregs = L2_loadri_io %10, -4 :: (load (s32) from %ir.c + 8, !tbaa !0) + %20:intregs, %25:intregs = L2_loadri_pi %10, 8 :: (load (s32) from %ir.d + 8, !tbaa !0) + %21:doubleregs = M2_cmacs_s1 %22, %19, %23, implicit-def dead $usr_ovf + ENDLOOP0 %bb.2, implicit-def $pc, implicit-def $lc0, implicit $sa0, implicit $lc0 + J2_jump %bb.3, implicit-def dead $pc + + bb.3: + %27:intregs = PHI %2, %bb.0, %17, %bb.2 + %28:doubleregs = PHI %0, %bb.0, %18, %bb.2 + %29:intregs = PHI %6, %bb.0, %19, %bb.2 + %30:intregs = PHI %5, %bb.0, %20, %bb.2 + %31:doubleregs = PHI %1, %bb.0, %21, %bb.2 + %32:intregs = PHI %9, %bb.0, %26, %bb.2 + %33:intregs = A2_add %27, %29 + S2_storerd_io %33, 0, %28 + %34:intregs = A2_add %30, %32 + S2_storerd_io %34, 0, %31 + PS_jmpret $r31, implicit-def dead $pc + +... _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
