diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 0865de3d39893..23c161f80a41f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3443,7 +3443,9 @@ Instruction *InstCombinerImpl::foldICmpEqIntrinsicWithConstant( } /// Fold an icmp with LLVM intrinsics -static Instruction *foldICmpIntrinsicWithIntrinsic(ICmpInst &Cmp) { +static Instruction * +foldICmpIntrinsicWithIntrinsic(ICmpInst &Cmp, + InstCombiner::BuilderTy &Builder) { assert(Cmp.isEquality()); ICmpInst::Predicate Pred = Cmp.getPredicate(); @@ -3461,16 +3463,32 @@ static Instruction *foldICmpIntrinsicWithIntrinsic(ICmpInst &Cmp) { // original values. return new ICmpInst(Pred, IIOp0->getOperand(0), IIOp1->getOperand(0)); case Intrinsic::fshl: - case Intrinsic::fshr: + case Intrinsic::fshr: { // If both operands are rotated by same amount, just compare the // original values. if (IIOp0->getOperand(0) != IIOp0->getOperand(1)) break; if (IIOp1->getOperand(0) != IIOp1->getOperand(1)) break; - if (IIOp0->getOperand(2) != IIOp1->getOperand(2)) - break; - return new ICmpInst(Pred, IIOp0->getOperand(0), IIOp1->getOperand(0)); + if (IIOp0->getOperand(2) == IIOp1->getOperand(2)) + return new ICmpInst(Pred, IIOp0->getOperand(0), IIOp1->getOperand(0)); + + // rotate(X, AmtX) == rotate(Y, AmtY) + // -> rotate(X, AmtX - AmtY) == Y + // Do this if either both rotates have one use or if only one has one use + // and AmtX/AmtY are constants. + unsigned OneUses = IIOp0->hasOneUse() + IIOp1->hasOneUse(); + if (OneUses == 2 || + (OneUses == 1 && match(IIOp0->getOperand(2), m_ImmConstant()) && + match(IIOp1->getOperand(2), m_ImmConstant()))) { + Value *SubAmt = + Builder.CreateSub(IIOp0->getOperand(2), IIOp1->getOperand(2)); + Value *CombinedRotate = Builder.CreateIntrinsic( + Op0->getType(), IIOp0->getIntrinsicID(), + {IIOp0->getOperand(0), IIOp0->getOperand(0), SubAmt}); + return new ICmpInst(Pred, IIOp1->getOperand(0), CombinedRotate); + } + } break; default: break; } @@ -4970,7 +4988,7 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) { } } - if (Instruction *ICmp = foldICmpIntrinsicWithIntrinsic(I)) + if (Instruction *ICmp = foldICmpIntrinsicWithIntrinsic(I, Builder)) return ICmp; // Canonicalize checking for a power-of-2-or-zero value: diff --git a/llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll b/llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll index 8decf28333953..f87f786e004f8 100644 --- a/llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll +++ b/llvm/test/Transforms/InstCombine/icmp-equality-rotate.ll @@ -63,9 +63,9 @@ define i1 @cmpeq_rorr_to_rorl_multiuse_fail(i8 %x, i8 %C) { define i1 @cmpne_rorr_rorr(i8 %x, i8 %C0, i8 %C1) { ; CHECK-LABEL: @cmpne_rorr_rorr( -; CHECK-NEXT: [[X_RORR0:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[C0:%.*]]) -; CHECK-NEXT: [[X_RORR1:%.*]] = call i8 @llvm.fshr.i8(i8 [[X]], i8 [[X]], i8 [[C1:%.*]]) -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X_RORR0]], [[X_RORR1]] +; CHECK-NEXT: [[TMP1:%.*]] = sub i8 [[C0:%.*]], [[C1:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[TMP1]]) +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP2]], [[X]] ; CHECK-NEXT: ret i1 [[R]] ; %x_rorr0 = call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %C0) @@ -76,9 +76,9 @@ define i1 @cmpne_rorr_rorr(i8 %x, i8 %C0, i8 %C1) { define i1 @cmpne_rorrX_rorrY(i8 %x, i8 %y, i8 %C0, i8 %C1) { ; CHECK-LABEL: @cmpne_rorrX_rorrY( -; CHECK-NEXT: [[X_RORR0:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[C0:%.*]]) -; CHECK-NEXT: [[Y_RORR1:%.*]] = call i8 @llvm.fshr.i8(i8 [[Y:%.*]], i8 [[Y]], i8 [[C1:%.*]]) -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X_RORR0]], [[Y_RORR1]] +; CHECK-NEXT: [[TMP1:%.*]] = sub i8 [[C0:%.*]], [[C1:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[TMP1]]) +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP2]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %x_rorr0 = call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %C0) @@ -132,10 +132,10 @@ define i1 @cmpne_rorl_rorl_multiuse1_fail(i8 %x, i8 %C0) { define i1 @cmpeq_rorlXC_rorlYC_multiuse1(i8 %x, i8 %y) { ; CHECK-LABEL: @cmpeq_rorlXC_rorlYC_multiuse1( -; CHECK-NEXT: [[X_RORL0:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 6) ; CHECK-NEXT: [[Y_RORL1:%.*]] = call i8 @llvm.fshl.i8(i8 [[Y:%.*]], i8 [[Y]], i8 3) ; CHECK-NEXT: call void @use.i8(i8 [[Y_RORL1]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X_RORL0]], [[Y_RORL1]] +; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 3) +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP1]], [[Y]] ; CHECK-NEXT: ret i1 [[R]] ; %x_rorl0 = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 6) diff --git a/llvm/test/Transforms/InstCombine/icmp-rotate.ll b/llvm/test/Transforms/InstCombine/icmp-rotate.ll index abd7caf621a51..2580bb6a865c7 100644 --- a/llvm/test/Transforms/InstCombine/icmp-rotate.ll +++ b/llvm/test/Transforms/InstCombine/icmp-rotate.ll @@ -211,9 +211,9 @@ define i1 @wrong_pred(i8 %x, i8 %y, i8 %z) { ; negative test - rotate amounts mismatch define i1 @amounts_mismatch(i8 %x, i8 %y, i8 %z, i8 %w) { ; CHECK-LABEL: @amounts_mismatch( -; CHECK-NEXT: [[F:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Z:%.*]]) -; CHECK-NEXT: [[F2:%.*]] = tail call i8 @llvm.fshl.i8(i8 [[Y:%.*]], i8 [[Y]], i8 [[W:%.*]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[F]], [[F2]] +; CHECK-NEXT: [[TMP1:%.*]] = sub i8 [[Z:%.*]], [[W:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[TMP1]]) +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP2]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %f = tail call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %z)