From 5bee7a74e3fe4e05c1bed1a63192af9053a5871b Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Fri, 4 Oct 2024 21:26:17 +0800 Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC. --- llvm/test/Transforms/InstCombine/lshr.ll | 64 ++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/lshr.ll b/llvm/test/Transforms/InstCombine/lshr.ll index 4360714c78caa..e07314c3707ef 100644 --- a/llvm/test/Transforms/InstCombine/lshr.ll +++ b/llvm/test/Transforms/InstCombine/lshr.ll @@ -1523,3 +1523,67 @@ define <2 x i8> @bool_add_lshr_vec_wrong_shift_amt(<2 x i1> %a, <2 x i1> %b) { %lshr = lshr <2 x i8> %add, ret <2 x i8> %lshr } + +define i32 @lowbits_of_lshr_mul(i64 %x) { +; CHECK-LABEL: @lowbits_of_lshr_mul( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[X:%.*]], 64424509440 +; CHECK-NEXT: [[SHIFT:%.*]] = lshr exact i64 [[MUL]], 32 +; CHECK-NEXT: [[CONV:%.*]] = trunc nuw i64 [[SHIFT]] to i32 +; CHECK-NEXT: ret i32 [[CONV]] +; +entry: + %mul = mul i64 %x, 64424509440 + %shift = lshr i64 %mul, 32 + %conv = trunc i64 %shift to i32 + ret i32 %conv +} + +define i32 @lowbits_of_lshr_mul_mask(i32 %x) { +; CHECK-LABEL: @lowbits_of_lshr_mul_mask( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 104857600 +; CHECK-NEXT: [[SHIFT:%.*]] = lshr exact i32 [[MUL]], 16 +; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 32704 +; CHECK-NEXT: ret i32 [[CONV]] +; +entry: + %mul = mul i32 %x, 104857600 + %shift = lshr i32 %mul, 16 + %conv = and i32 %shift, 32767 + ret i32 %conv +} + +; Negative tests + +define i32 @lowbits_of_lshr_mul_mask_multiuse(i32 %x) { +; CHECK-LABEL: @lowbits_of_lshr_mul_mask_multiuse( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 104857600 +; CHECK-NEXT: call void @use(i32 [[MUL]]) +; CHECK-NEXT: [[SHIFT:%.*]] = lshr exact i32 [[MUL]], 16 +; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 32704 +; CHECK-NEXT: ret i32 [[CONV]] +; +entry: + %mul = mul i32 %x, 104857600 + call void @use(i32 %mul) + %shift = lshr i32 %mul, 16 + %conv = and i32 %shift, 32767 + ret i32 %conv +} + +define i32 @lowbits_of_lshr_mul_mask_indivisible(i32 %x) { +; CHECK-LABEL: @lowbits_of_lshr_mul_mask_indivisible( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 25600 +; CHECK-NEXT: [[SHIFT:%.*]] = lshr i32 [[MUL]], 16 +; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 32767 +; CHECK-NEXT: ret i32 [[CONV]] +; +entry: + %mul = mul i32 %x, 25600 + %shift = lshr i32 %mul, 16 + %conv = and i32 %shift, 32767 + ret i32 %conv +} From 7de2345ffe1352cf5fd3f242feba0dd2c142497f Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Fri, 4 Oct 2024 21:26:49 +0800 Subject: [PATCH 2/2] [InstCombine] Fold `(X * (Y << K)) u>> K -> X * Y` when highbits are not demanded --- .../InstCombine/InstCombineSimplifyDemanded.cpp | 9 +++++++++ llvm/test/Transforms/InstCombine/lshr.ll | 10 ++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index ee6b60f7f70d6..b330a8ad9f8a6 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -770,6 +770,15 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I, return InsertNewInstWith(Shl, I->getIterator()); } } + + const APInt *Factor; + if (match(I->getOperand(0), + m_OneUse(m_Mul(m_Value(X), m_APInt(Factor)))) && + Factor->countr_zero() >= ShiftAmt) { + BinaryOperator *Mul = BinaryOperator::CreateMul( + X, ConstantInt::get(X->getType(), Factor->lshr(ShiftAmt))); + return InsertNewInstWith(Mul, I->getIterator()); + } } // Unsigned shift right. diff --git a/llvm/test/Transforms/InstCombine/lshr.ll b/llvm/test/Transforms/InstCombine/lshr.ll index e07314c3707ef..ccc2b61b2989a 100644 --- a/llvm/test/Transforms/InstCombine/lshr.ll +++ b/llvm/test/Transforms/InstCombine/lshr.ll @@ -1527,9 +1527,8 @@ define <2 x i8> @bool_add_lshr_vec_wrong_shift_amt(<2 x i1> %a, <2 x i1> %b) { define i32 @lowbits_of_lshr_mul(i64 %x) { ; CHECK-LABEL: @lowbits_of_lshr_mul( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[X:%.*]], 64424509440 -; CHECK-NEXT: [[SHIFT:%.*]] = lshr exact i64 [[MUL]], 32 -; CHECK-NEXT: [[CONV:%.*]] = trunc nuw i64 [[SHIFT]] to i32 +; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[X:%.*]] to i32 +; CHECK-NEXT: [[CONV:%.*]] = mul i32 [[TMP0]], 15 ; CHECK-NEXT: ret i32 [[CONV]] ; entry: @@ -1542,9 +1541,8 @@ entry: define i32 @lowbits_of_lshr_mul_mask(i32 %x) { ; CHECK-LABEL: @lowbits_of_lshr_mul_mask( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 104857600 -; CHECK-NEXT: [[SHIFT:%.*]] = lshr exact i32 [[MUL]], 16 -; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 32704 +; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[X:%.*]], 1600 +; CHECK-NEXT: [[CONV:%.*]] = and i32 [[TMP0]], 32704 ; CHECK-NEXT: ret i32 [[CONV]] ; entry: