diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -2667,6 +2667,20 @@ bool HasChainOp = True.getOperand(True.getNumOperands() - 1).getValueType() == MVT::Other; + if (HasChainOp) { + // Avoid creating cycles in the DAG. We must ensure that none of the other + // operands depend on True through it's Chain. + SmallVector LoopWorklist; + SmallPtrSet Visited; + LoopWorklist.push_back(False.getNode()); + LoopWorklist.push_back(Mask.getNode()); + LoopWorklist.push_back(VL.getNode()); + if (SDNode *Glued = N->getGluedNode()) + LoopWorklist.push_back(Glued); + if (SDNode::hasPredecessorHelper(True.getNode(), Visited, LoopWorklist)) + return false; + } + // Need True has same VL with N. unsigned TrueVLIndex = True.getNumOperands() - HasChainOp - 2; SDValue TrueVL = True.getOperand(TrueVLIndex); diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll --- a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll @@ -843,3 +843,40 @@ %b = call @llvm.vp.select.nxv2i32( %m, %a, %passthru, i32 %vl) ret %b } + +; Folding this would create a loop in the DAG becuase the chain from the VLE is +; used by the vssubu. +define void @test_dag_loop() { +; CHECK-LABEL: test_dag_loop: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetivli zero, 1, e16, m8, ta, mu +; CHECK-NEXT: vle16.v v8, (zero) +; CHECK-NEXT: vsetvli a0, zero, e8, m4, ta, mu +; CHECK-NEXT: vmclr.m v0 +; CHECK-NEXT: vmv.v.i v16, 0 +; CHECK-NEXT: vsetivli zero, 0, e8, m4, tu, mu +; CHECK-NEXT: vmv4r.v v20, v16 +; CHECK-NEXT: vssubu.vx v20, v16, zero, v0.t +; CHECK-NEXT: vsetvli zero, zero, e8, m4, ta, mu +; CHECK-NEXT: vmseq.vv v0, v20, v16 +; CHECK-NEXT: vsetvli a0, zero, e16, m8, ta, mu +; CHECK-NEXT: vmv.v.i v16, 0 +; CHECK-NEXT: vsetivli zero, 1, e16, m8, tu, mu +; CHECK-NEXT: vmerge.vvm v16, v16, v8, v0 +; CHECK-NEXT: vsetivli zero, 0, e16, m8, ta, mu +; CHECK-NEXT: vse16.v v16, (zero) +; CHECK-NEXT: ret +entry: + %0 = call @llvm.riscv.vle.nxv32i16.i64( undef, * null, i64 1) + %1 = tail call @llvm.riscv.vssubu.mask.nxv32i8.i8.i64( zeroinitializer, zeroinitializer, i8 0, zeroinitializer, i64 0, i64 0) + %2 = tail call @llvm.riscv.vmseq.nxv32i8.nxv32i8.i64( %1, zeroinitializer, i64 0) + %3 = tail call @llvm.riscv.vmerge.nxv32i16.nxv32i16.i64( zeroinitializer, zeroinitializer, %0, %2, i64 1) + call void @llvm.riscv.vse.nxv32i16.i64( %3, * null, i64 0) + ret void +} + +declare @llvm.riscv.vle.nxv32i16.i64(, * nocapture, i64) +declare @llvm.riscv.vssubu.mask.nxv32i8.i8.i64(, , i8, , i64, i64 immarg) +declare @llvm.riscv.vmseq.nxv32i8.nxv32i8.i64(, , i64) +declare @llvm.riscv.vmerge.nxv32i16.nxv32i16.i64(, , , , i64) +declare void @llvm.riscv.vse.nxv32i16.i64(, * nocapture, i64)