diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2197,17 +2197,34 @@ // If the leaf of the tree is a comparison, merge the condition into // the caseblock. if (const CmpInst *BOp = dyn_cast(Cond)) { + Value *CmpLHS = BOp->getOperand(0); + Value *CmpRHS = BOp->getOperand(1); // The operands of the cmp have to be in this block. We don't know // how to export them from some other block. If this is the first block // of the sequence, no exporting is needed. if (CurBB == SwitchBB || - (isExportableFromCurrentBlock(BOp->getOperand(0), BB) && - isExportableFromCurrentBlock(BOp->getOperand(1), BB))) { + (isExportableFromCurrentBlock(CmpLHS, BB) && + isExportableFromCurrentBlock(CmpRHS, BB))) { + Value *CmpMHS = nullptr; + ISD::CondCode Condition; if (const ICmpInst *IC = dyn_cast(Cond)) { ICmpInst::Predicate Pred = InvertCond ? IC->getInversePredicate() : IC->getPredicate(); Condition = getICmpCondCode(Pred); + + auto &TLI = DAG.getTargetLoweringInfo(); + Value *AndLHS; + ConstantInt *AndRHS; + if (IC->isEquality() && isa(CmpRHS) && + cast(CmpRHS)->isZero() && + match(CmpLHS, m_OneUse(m_And(m_Value(AndLHS), m_ConstantInt(AndRHS)))) && + TLI.isMaskAndCmp0FoldingBeneficial(*cast(CmpLHS)) && + isExportableFromCurrentBlock(AndLHS, BB) && + isExportableFromCurrentBlock(AndRHS, BB)) { + CmpLHS = AndLHS; + CmpMHS = AndRHS; + } } else { const FCmpInst *FC = cast(Cond); FCmpInst::Predicate Pred = @@ -2217,7 +2234,7 @@ Condition = getFCmpCodeWithoutNaN(Condition); } - CaseBlock CB(Condition, BOp->getOperand(0), BOp->getOperand(1), nullptr, + CaseBlock CB(Condition, CmpLHS, CmpRHS, CmpMHS, TBB, FBB, CurBB, getCurSDLoc(), TProb, FProb); SL->SwitchCases.push_back(CB); return; @@ -2458,6 +2475,8 @@ for (unsigned i = 1, e = SL->SwitchCases.size(); i != e; ++i) { ExportFromCurrentBlock(SL->SwitchCases[i].CmpLHS); ExportFromCurrentBlock(SL->SwitchCases[i].CmpRHS); + if (SL->SwitchCases[i].CmpMHS) + ExportFromCurrentBlock(SL->SwitchCases[i].CmpMHS); } // Emit the branch for this block. @@ -2529,9 +2548,7 @@ } Cond = DAG.getSetCC(dl, MVT::i1, CondLHS, CondRHS, CB.CC); } - } else { - assert(CB.CC == ISD::SETLE && "Can handle only LE ranges now"); - + } else if (CB.CC == ISD::SETLE) { const APInt& Low = cast(CB.CmpLHS)->getValue(); const APInt& High = cast(CB.CmpRHS)->getValue(); @@ -2547,6 +2564,15 @@ Cond = DAG.getSetCC(dl, MVT::i1, SUB, DAG.getConstant(High-Low, dl, VT), ISD::SETULE); } + } else { + assert(ISD::isIntEqualitySetCC(CB.CC) && "Expected equality compare"); + SDValue AndLHS = getValue(CB.CmpLHS); + SDValue AndRHS = getValue(CB.CmpMHS); + SDValue CmpRHS = getValue(CB.CmpRHS); + EVT VT = AndLHS.getValueType(); + + SDValue AND = DAG.getNode(ISD::AND, dl, VT, AndLHS, AndRHS); + Cond = DAG.getSetCC(dl, MVT::i1, AND, CmpRHS, CB.CC); } // Update successor info diff --git a/llvm/test/CodeGen/X86/peephole-na-phys-copy-folding.ll b/llvm/test/CodeGen/X86/peephole-na-phys-copy-folding.ll --- a/llvm/test/CodeGen/X86/peephole-na-phys-copy-folding.ll +++ b/llvm/test/CodeGen/X86/peephole-na-phys-copy-folding.ll @@ -14,11 +14,10 @@ define i1 @plus_one() nounwind { ; CHECK32-LABEL: plus_one: ; CHECK32: # %bb.0: # %entry -; CHECK32-NEXT: movzbl M, %eax ; CHECK32-NEXT: incl L ; CHECK32-NEXT: jne .LBB0_2 ; CHECK32-NEXT: # %bb.1: # %entry -; CHECK32-NEXT: andb $8, %al +; CHECK32-NEXT: testb $8, M ; CHECK32-NEXT: je .LBB0_2 ; CHECK32-NEXT: # %bb.3: # %exit2 ; CHECK32-NEXT: xorl %eax, %eax @@ -29,11 +28,10 @@ ; ; CHECK64-LABEL: plus_one: ; CHECK64: # %bb.0: # %entry -; CHECK64-NEXT: movzbl M(%rip), %eax ; CHECK64-NEXT: incl L(%rip) ; CHECK64-NEXT: jne .LBB0_2 ; CHECK64-NEXT: # %bb.1: # %entry -; CHECK64-NEXT: andb $8, %al +; CHECK64-NEXT: testb $8, M(%rip) ; CHECK64-NEXT: je .LBB0_2 ; CHECK64-NEXT: # %bb.3: # %exit2 ; CHECK64-NEXT: xorl %eax, %eax @@ -62,11 +60,10 @@ define i1 @plus_forty_two() nounwind { ; CHECK32-LABEL: plus_forty_two: ; CHECK32: # %bb.0: # %entry -; CHECK32-NEXT: movzbl M, %eax ; CHECK32-NEXT: addl $42, L ; CHECK32-NEXT: jne .LBB1_2 ; CHECK32-NEXT: # %bb.1: # %entry -; CHECK32-NEXT: andb $8, %al +; CHECK32-NEXT: testb $8, M ; CHECK32-NEXT: je .LBB1_2 ; CHECK32-NEXT: # %bb.3: # %exit2 ; CHECK32-NEXT: xorl %eax, %eax @@ -77,11 +74,10 @@ ; ; CHECK64-LABEL: plus_forty_two: ; CHECK64: # %bb.0: # %entry -; CHECK64-NEXT: movzbl M(%rip), %eax ; CHECK64-NEXT: addl $42, L(%rip) ; CHECK64-NEXT: jne .LBB1_2 ; CHECK64-NEXT: # %bb.1: # %entry -; CHECK64-NEXT: andb $8, %al +; CHECK64-NEXT: testb $8, M(%rip) ; CHECK64-NEXT: je .LBB1_2 ; CHECK64-NEXT: # %bb.3: # %exit2 ; CHECK64-NEXT: xorl %eax, %eax @@ -110,11 +106,10 @@ define i1 @minus_one() nounwind { ; CHECK32-LABEL: minus_one: ; CHECK32: # %bb.0: # %entry -; CHECK32-NEXT: movzbl M, %eax ; CHECK32-NEXT: decl L ; CHECK32-NEXT: jne .LBB2_2 ; CHECK32-NEXT: # %bb.1: # %entry -; CHECK32-NEXT: andb $8, %al +; CHECK32-NEXT: testb $8, M ; CHECK32-NEXT: je .LBB2_2 ; CHECK32-NEXT: # %bb.3: # %exit2 ; CHECK32-NEXT: xorl %eax, %eax @@ -125,11 +120,10 @@ ; ; CHECK64-LABEL: minus_one: ; CHECK64: # %bb.0: # %entry -; CHECK64-NEXT: movzbl M(%rip), %eax ; CHECK64-NEXT: decl L(%rip) ; CHECK64-NEXT: jne .LBB2_2 ; CHECK64-NEXT: # %bb.1: # %entry -; CHECK64-NEXT: andb $8, %al +; CHECK64-NEXT: testb $8, M(%rip) ; CHECK64-NEXT: je .LBB2_2 ; CHECK64-NEXT: # %bb.3: # %exit2 ; CHECK64-NEXT: xorl %eax, %eax @@ -158,11 +152,10 @@ define i1 @minus_forty_two() nounwind { ; CHECK32-LABEL: minus_forty_two: ; CHECK32: # %bb.0: # %entry -; CHECK32-NEXT: movzbl M, %eax ; CHECK32-NEXT: addl $-42, L ; CHECK32-NEXT: jne .LBB3_2 ; CHECK32-NEXT: # %bb.1: # %entry -; CHECK32-NEXT: andb $8, %al +; CHECK32-NEXT: testb $8, M ; CHECK32-NEXT: je .LBB3_2 ; CHECK32-NEXT: # %bb.3: # %exit2 ; CHECK32-NEXT: xorl %eax, %eax @@ -173,11 +166,10 @@ ; ; CHECK64-LABEL: minus_forty_two: ; CHECK64: # %bb.0: # %entry -; CHECK64-NEXT: movzbl M(%rip), %eax ; CHECK64-NEXT: addl $-42, L(%rip) ; CHECK64-NEXT: jne .LBB3_2 ; CHECK64-NEXT: # %bb.1: # %entry -; CHECK64-NEXT: andb $8, %al +; CHECK64-NEXT: testb $8, M(%rip) ; CHECK64-NEXT: je .LBB3_2 ; CHECK64-NEXT: # %bb.3: # %exit2 ; CHECK64-NEXT: xorl %eax, %eax diff --git a/llvm/test/CodeGen/X86/pr57402.ll b/llvm/test/CodeGen/X86/pr57402.ll --- a/llvm/test/CodeGen/X86/pr57402.ll +++ b/llvm/test/CodeGen/X86/pr57402.ll @@ -23,8 +23,9 @@ ; CHECK-NEXT: movswl %dx, %eax ; CHECK-NEXT: movswl %cx, %ecx ; CHECK-NEXT: andl %eax, %ecx -; CHECK-NEXT: imull %ecx, %eax -; CHECK-NEXT: testq %rax, %rax +; CHECK-NEXT: movslq %ecx, %rax +; CHECK-NEXT: imulq %rax, %rax +; CHECK-NEXT: testl %eax, %eax ; CHECK-NEXT: jne .LBB0_3 ; CHECK-NEXT: .LBB0_4: # %if.end ; CHECK-NEXT: retq