diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -47606,8 +47606,7 @@ // into: // srl(ctlz x), log2(bitsize(x)) // Input pattern is checked by caller. -static SDValue lowerX86CmpEqZeroToCtlzSrl(SDValue Op, EVT ExtTy, - SelectionDAG &DAG) { +static SDValue lowerX86CmpEqZeroToCtlzSrl(SDValue Op, SelectionDAG &DAG) { SDValue Cmp = Op.getOperand(1); EVT VT = Cmp.getOperand(0).getValueType(); unsigned Log2b = Log2_32(VT.getSizeInBits()); @@ -47618,7 +47617,7 @@ SDValue Trunc = DAG.getZExtOrTrunc(Clz, dl, MVT::i32); SDValue Scc = DAG.getNode(ISD::SRL, dl, MVT::i32, Trunc, DAG.getConstant(Log2b, dl, MVT::i8)); - return DAG.getZExtOrTrunc(Scc, dl, ExtTy); + return Scc; } // Try to transform: @@ -47678,11 +47677,10 @@ // or(srl(ctlz),srl(ctlz)). // The dag combiner can then fold it into: // srl(or(ctlz, ctlz)). - EVT VT = OR->getValueType(0); - SDValue NewLHS = lowerX86CmpEqZeroToCtlzSrl(LHS, VT, DAG); + SDValue NewLHS = lowerX86CmpEqZeroToCtlzSrl(LHS, DAG); SDValue Ret, NewRHS; - if (NewLHS && (NewRHS = lowerX86CmpEqZeroToCtlzSrl(RHS, VT, DAG))) - Ret = DAG.getNode(ISD::OR, SDLoc(OR), VT, NewLHS, NewRHS); + if (NewLHS && (NewRHS = lowerX86CmpEqZeroToCtlzSrl(RHS, DAG))) + Ret = DAG.getNode(ISD::OR, SDLoc(OR), MVT::i32, NewLHS, NewRHS); if (!Ret) return SDValue(); @@ -47695,16 +47693,13 @@ // Swap rhs with lhs to match or(setcc(eq, cmp, 0), or). if (RHS->getOpcode() == ISD::OR) std::swap(LHS, RHS); - NewRHS = lowerX86CmpEqZeroToCtlzSrl(RHS, VT, DAG); + NewRHS = lowerX86CmpEqZeroToCtlzSrl(RHS, DAG); if (!NewRHS) return SDValue(); - Ret = DAG.getNode(ISD::OR, SDLoc(OR), VT, Ret, NewRHS); + Ret = DAG.getNode(ISD::OR, SDLoc(OR), MVT::i32, Ret, NewRHS); } - if (Ret) - Ret = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), N->getValueType(0), Ret); - - return Ret; + return DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), N->getValueType(0), Ret); } static SDValue foldMaskedMergeImpl(SDValue And0_L, SDValue And0_R, diff --git a/llvm/test/CodeGen/X86/lzcnt-zext-cmp.ll b/llvm/test/CodeGen/X86/lzcnt-zext-cmp.ll --- a/llvm/test/CodeGen/X86/lzcnt-zext-cmp.ll +++ b/llvm/test/CodeGen/X86/lzcnt-zext-cmp.ll @@ -154,11 +154,11 @@ define i32 @test_zext_cmp6(i32 %a, i32 %b, i32 %c) { ; FASTLZCNT-LABEL: test_zext_cmp6: ; FASTLZCNT: # %bb.0: # %entry -; FASTLZCNT-NEXT: lzcntl %edi, %eax -; FASTLZCNT-NEXT: lzcntl %esi, %ecx -; FASTLZCNT-NEXT: orl %eax, %ecx +; FASTLZCNT-NEXT: lzcntl %edi, %ecx ; FASTLZCNT-NEXT: lzcntl %edx, %eax +; FASTLZCNT-NEXT: lzcntl %esi, %esi ; FASTLZCNT-NEXT: orl %ecx, %eax +; FASTLZCNT-NEXT: orl %esi, %eax ; FASTLZCNT-NEXT: shrl $5, %eax ; FASTLZCNT-NEXT: retq ; @@ -189,11 +189,11 @@ define i32 @test_zext_cmp7(i32 %a, i32 %b, i32 %c) { ; FASTLZCNT-LABEL: test_zext_cmp7: ; FASTLZCNT: # %bb.0: # %entry -; FASTLZCNT-NEXT: lzcntl %edi, %eax -; FASTLZCNT-NEXT: lzcntl %esi, %ecx -; FASTLZCNT-NEXT: orl %eax, %ecx +; FASTLZCNT-NEXT: lzcntl %edi, %ecx ; FASTLZCNT-NEXT: lzcntl %edx, %eax +; FASTLZCNT-NEXT: lzcntl %esi, %esi ; FASTLZCNT-NEXT: orl %ecx, %eax +; FASTLZCNT-NEXT: orl %esi, %eax ; FASTLZCNT-NEXT: shrl $5, %eax ; FASTLZCNT-NEXT: retq ; @@ -335,3 +335,37 @@ %conv = zext i1 %0 to i32 ret i32 %conv } + +; PR54694 Fix an infinite loop in DAG combiner. +define i32 @test_zext_cmp12(i32 %0, i32 %1) { +; FASTLZCNT-LABEL: test_zext_cmp12: +; FASTLZCNT: # %bb.0: +; FASTLZCNT-NEXT: andl $131072, %edi # imm = 0x20000 +; FASTLZCNT-NEXT: andl $131072, %esi # imm = 0x20000 +; FASTLZCNT-NEXT: lzcntl %edi, %eax +; FASTLZCNT-NEXT: lzcntl %esi, %ecx +; FASTLZCNT-NEXT: orl %eax, %ecx +; FASTLZCNT-NEXT: movl $2, %eax +; FASTLZCNT-NEXT: shrl $5, %ecx +; FASTLZCNT-NEXT: subl %ecx, %eax +; FASTLZCNT-NEXT: retq +; +; NOFASTLZCNT-LABEL: test_zext_cmp12: +; NOFASTLZCNT: # %bb.0: +; NOFASTLZCNT-NEXT: testl $131072, %edi # imm = 0x20000 +; NOFASTLZCNT-NEXT: sete %al +; NOFASTLZCNT-NEXT: testl $131072, %esi # imm = 0x20000 +; NOFASTLZCNT-NEXT: sete %cl +; NOFASTLZCNT-NEXT: orb %al, %cl +; NOFASTLZCNT-NEXT: movl $2, %eax +; NOFASTLZCNT-NEXT: movzbl %cl, %ecx +; NOFASTLZCNT-NEXT: subl %ecx, %eax +; NOFASTLZCNT-NEXT: retq + %3 = and i32 %0, 131072 + %4 = icmp eq i32 %3, 0 + %5 = and i32 %1, 131072 + %6 = icmp eq i32 %5, 0 + %7 = select i1 %4, i1 true, i1 %6 + %8 = select i1 %7, i32 1, i32 2 + ret i32 %8 +}