[llvm] 1c6ebe2 - [InstCombine] reduce multi-use casts+masks
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Sun Nov 6 06:07:25 PST 2022
Author: Sanjay Patel
Date: 2022-11-06T09:07:17-05:00
New Revision: 1c6ebe29d3c03382a62985fab764f5641db7f875
URL: https://github.com/llvm/llvm-project/commit/1c6ebe29d3c03382a62985fab764f5641db7f875
DIFF: https://github.com/llvm/llvm-project/commit/1c6ebe29d3c03382a62985fab764f5641db7f875.diff
LOG: [InstCombine] reduce multi-use casts+masks
As noted in the code comment, we could generalize this:
https://alive2.llvm.org/ce/z/N5m-eZ
It saves an instruction even without a constant operand,
but the 'and' is wider. We can do that as another step
if it doesn't harm anything.
I noticed that this missing pattern with a constant operand
inhibited other transforms in a recent bug report, so this
is enough to solve that case.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
llvm/test/Transforms/InstCombine/zext.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index c91786148beb4..dfe49fb525fc1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -1328,6 +1328,17 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &CI) {
return BinaryOperator::CreateXor(Builder.CreateAnd(X, ZC), ZC);
}
+ // If we are truncating, masking, and then zexting back to the original type,
+ // that's just a mask. This is not handled by canEvaluateZextd if the
+ // intermediate values have extra uses. This could be generalized further for
+ // a non-constant mask operand.
+ // zext (and (trunc X), C) --> and X, (zext C)
+ if (match(Src, m_And(m_Trunc(m_Value(X)), m_Constant(C))) &&
+ X->getType() == DestTy) {
+ Constant *ZextC = ConstantExpr::getZExt(C, DestTy);
+ return BinaryOperator::CreateAnd(X, ZextC);
+ }
+
if (match(Src, m_VScale(DL))) {
if (CI.getFunction() &&
CI.getFunction()->hasFnAttribute(Attribute::VScaleRange)) {
diff --git a/llvm/test/Transforms/InstCombine/zext.ll b/llvm/test/Transforms/InstCombine/zext.ll
index 06188de5751ed..25f59d5570ee2 100644
--- a/llvm/test/Transforms/InstCombine/zext.ll
+++ b/llvm/test/Transforms/InstCombine/zext.ll
@@ -537,6 +537,8 @@ join:
ret i16 %conv4
}
+; negative test - but this could be transformed to eliminate a use of 't'
+
define i64 @and_trunc_extra_use1(i64 %x, i32 %y) {
; CHECK-LABEL: @and_trunc_extra_use1(
; CHECK-NEXT: [[T:%.*]] = trunc i64 [[X:%.*]] to i32
@@ -552,6 +554,8 @@ define i64 @and_trunc_extra_use1(i64 %x, i32 %y) {
ret i64 %z
}
+; negative test - but this could be transformed to eliminate a use of 't'
+
define i64 @and_trunc_extra_use1_commute(i64 %x, i32 %p) {
; CHECK-LABEL: @and_trunc_extra_use1_commute(
; CHECK-NEXT: [[Y:%.*]] = mul i32 [[P:%.*]], [[P]]
@@ -569,6 +573,8 @@ define i64 @and_trunc_extra_use1_commute(i64 %x, i32 %p) {
ret i64 %z
}
+; negative test - avoid creating an extra instruction
+
define i64 @and_trunc_extra_use2(i64 %x, i32 %y) {
; CHECK-LABEL: @and_trunc_extra_use2(
; CHECK-NEXT: [[T:%.*]] = trunc i64 [[X:%.*]] to i32
@@ -584,12 +590,14 @@ define i64 @and_trunc_extra_use2(i64 %x, i32 %y) {
ret i64 %z
}
+; With constant mask, we duplicate it as a wider constant.
+
define i64 @and_trunc_extra_use2_constant(i64 %x) {
; CHECK-LABEL: @and_trunc_extra_use2_constant(
; CHECK-NEXT: [[T:%.*]] = trunc i64 [[X:%.*]] to i32
; CHECK-NEXT: [[A:%.*]] = and i32 [[T]], 42
; CHECK-NEXT: call void @use32(i32 [[A]])
-; CHECK-NEXT: [[Z:%.*]] = zext i32 [[A]] to i64
+; CHECK-NEXT: [[Z:%.*]] = and i64 [[X]], 42
; CHECK-NEXT: ret i64 [[Z]]
;
%t = trunc i64 %x to i32
@@ -599,13 +607,15 @@ define i64 @and_trunc_extra_use2_constant(i64 %x) {
ret i64 %z
}
+; Works with arbitrary vectors and verify that the constant is zext.
+
define <2 x i17> @and_trunc_extra_use3_constant_vec(<2 x i17> %x) {
; CHECK-LABEL: @and_trunc_extra_use3_constant_vec(
; CHECK-NEXT: [[T:%.*]] = trunc <2 x i17> [[X:%.*]] to <2 x i9>
; CHECK-NEXT: call void @use_vec(<2 x i9> [[T]])
; CHECK-NEXT: [[A:%.*]] = and <2 x i9> [[T]], <i9 42, i9 -3>
; CHECK-NEXT: call void @use_vec(<2 x i9> [[A]])
-; CHECK-NEXT: [[Z:%.*]] = zext <2 x i9> [[A]] to <2 x i17>
+; CHECK-NEXT: [[Z:%.*]] = and <2 x i17> [[X]], <i17 42, i17 509>
; CHECK-NEXT: ret <2 x i17> [[Z]]
;
%t = trunc <2 x i17> %x to <2 x i9>
@@ -616,6 +626,8 @@ define <2 x i17> @and_trunc_extra_use3_constant_vec(<2 x i17> %x) {
ret <2 x i17> %z
}
+; negative test - would require another cast
+
define i64 @and_trunc_extra_use1_wider_src(i65 %x, i32 %y) {
; CHECK-LABEL: @and_trunc_extra_use1_wider_src(
; CHECK-NEXT: [[T:%.*]] = trunc i65 [[X:%.*]] to i32
More information about the llvm-commits
mailing list