From bf859bb52f5d3f48957d3ff0c38f2c06601be20e Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Mon, 18 Mar 2019 14:27:51 +0000 Subject: [PATCH] [InstCombine] allow general vector constants for funnel shift to shift transforms Follow-up to: rL356338 rL356369 We can calculate an arbitrary vector constant minus the bitwidth, so there's no need to limit this transform to scalars and splats. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@356372 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineCalls.cpp | 33 ++++++++----------- test/Transforms/InstCombine/fsh.ll | 8 ++--- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 938517e64c3..49524d7f42e 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2006,40 +2006,33 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { II->setArgOperand(2, ModuloC); return II; } + assert(ConstantExpr::getICmp(ICmpInst::ICMP_UGT, WidthC, ShAmtC) == + ConstantInt::getTrue(CmpInst::makeCmpResultType(Ty)) && + "Shift amount expected to be modulo bitwidth"); + // Canonicalize funnel shift right by constant to funnel shift left. This // is not entirely arbitrary. For historical reasons, the backend may // recognize rotate left patterns but miss rotate right patterns. if (II->getIntrinsicID() == Intrinsic::fshr) { // fshr X, Y, C --> fshl X, Y, (BitWidth - C) - assert(ConstantExpr::getICmp(ICmpInst::ICMP_UGT, WidthC, ShAmtC) == - ConstantInt::getTrue(CmpInst::makeCmpResultType(Ty)) && - "Shift amount expected to be modulo bitwidth"); Constant *LeftShiftC = ConstantExpr::getSub(WidthC, ShAmtC); Module *Mod = II->getModule(); Function *Fshl = Intrinsic::getDeclaration(Mod, Intrinsic::fshl, Ty); return CallInst::Create(Fshl, { Op0, Op1, LeftShiftC }); } - } - - // TODO: Pull this into the block above. We can handle semi-arbitrary vector - // shift amount constants as well as splats. - const APInt *SA; - if (match(II->getArgOperand(2), m_APInt(SA))) { - uint64_t ShiftAmt = SA->urem(BitWidth); - assert(ShiftAmt != 0 && "SimplifyCall should have handled zero shift"); assert(II->getIntrinsicID() == Intrinsic::fshl && "All funnel shifts by simple constants should go left"); - // fshl(X, 0, C) -> shl X, C - // fshl(X, undef, C) -> shl X, C - if (match(Op1, m_Zero()) || match(Op1, m_Undef())) - return BinaryOperator::CreateShl(Op0, ConstantInt::get(Ty, ShiftAmt)); + // fshl(X, 0, C) --> shl X, C + // fshl(X, undef, C) --> shl X, C + if (match(Op1, m_ZeroInt()) || match(Op1, m_Undef())) + return BinaryOperator::CreateShl(Op0, ShAmtC); - // fshl(0, X, C) -> lshr X, (BW-C) - // fshl(undef, X, C) -> lshr X, (BW-C) - if (match(Op0, m_Zero()) || match(Op0, m_Undef())) - return BinaryOperator::CreateLShr( - Op1, ConstantInt::get(Ty, BitWidth - ShiftAmt)); + // fshl(0, X, C) --> lshr X, (BW-C) + // fshl(undef, X, C) --> lshr X, (BW-C) + if (match(Op0, m_ZeroInt()) || match(Op0, m_Undef())) + return BinaryOperator::CreateLShr(Op1, + ConstantExpr::getSub(WidthC, ShAmtC)); } // The shift amount (operand 2) of a funnel shift is modulo the bitwidth, diff --git a/test/Transforms/InstCombine/fsh.ll b/test/Transforms/InstCombine/fsh.ll index 5aa3c63f1f5..f0bdb6f79f7 100644 --- a/test/Transforms/InstCombine/fsh.ll +++ b/test/Transforms/InstCombine/fsh.ll @@ -253,7 +253,7 @@ define <2 x i32> @fshr_op1_zero_splat_vec(<2 x i32> %x) { define <2 x i31> @fshl_op0_zero_vec(<2 x i31> %x) { ; CHECK-LABEL: @fshl_op0_zero_vec( -; CHECK-NEXT: [[R:%.*]] = call <2 x i31> @llvm.fshl.v2i31(<2 x i31> zeroinitializer, <2 x i31> [[X:%.*]], <2 x i31> ) +; CHECK-NEXT: [[R:%.*]] = lshr <2 x i31> [[X:%.*]], ; CHECK-NEXT: ret <2 x i31> [[R]] ; %r = call <2 x i31> @llvm.fshl.v2i31(<2 x i31> zeroinitializer, <2 x i31> %x, <2 x i31> ) @@ -262,7 +262,7 @@ define <2 x i31> @fshl_op0_zero_vec(<2 x i31> %x) { define <2 x i31> @fshl_op1_undef_vec(<2 x i31> %x) { ; CHECK-LABEL: @fshl_op1_undef_vec( -; CHECK-NEXT: [[R:%.*]] = call <2 x i31> @llvm.fshl.v2i31(<2 x i31> [[X:%.*]], <2 x i31> undef, <2 x i31> ) +; CHECK-NEXT: [[R:%.*]] = shl <2 x i31> [[X:%.*]], ; CHECK-NEXT: ret <2 x i31> [[R]] ; %r = call <2 x i31> @llvm.fshl.v2i31(<2 x i31> %x, <2 x i31> undef, <2 x i31> ) @@ -271,7 +271,7 @@ define <2 x i31> @fshl_op1_undef_vec(<2 x i31> %x) { define <2 x i32> @fshr_op0_undef_vec(<2 x i32> %x) { ; CHECK-LABEL: @fshr_op0_undef_vec( -; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.fshl.v2i32(<2 x i32> undef, <2 x i32> [[X:%.*]], <2 x i32> ) +; CHECK-NEXT: [[R:%.*]] = lshr <2 x i32> [[X:%.*]], ; CHECK-NEXT: ret <2 x i32> [[R]] ; %r = call <2 x i32> @llvm.fshr.v2i32(<2 x i32> undef, <2 x i32> %x, <2 x i32> ) @@ -280,7 +280,7 @@ define <2 x i32> @fshr_op0_undef_vec(<2 x i32> %x) { define <2 x i32> @fshr_op1_zero_vec(<2 x i32> %x) { ; CHECK-LABEL: @fshr_op1_zero_vec( -; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.fshl.v2i32(<2 x i32> [[X:%.*]], <2 x i32> zeroinitializer, <2 x i32> ) +; CHECK-NEXT: [[R:%.*]] = shl <2 x i32> [[X:%.*]], ; CHECK-NEXT: ret <2 x i32> [[R]] ; %r = call <2 x i32> @llvm.fshr.v2i32(<2 x i32> %x, <2 x i32> zeroinitializer, <2 x i32> ) -- 2.50.1