[llvm] 42f488b - [InstCombine] improve matching for sext-lshr-trunc patterns
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 8 08:55:37 PDT 2020
Author: Sanjay Patel
Date: 2020-06-08T11:55:30-04:00
New Revision: 42f488b63a04fdaa931315bdadecb6d23e20529a
URL: https://github.com/llvm/llvm-project/commit/42f488b63a04fdaa931315bdadecb6d23e20529a
DIFF: https://github.com/llvm/llvm-project/commit/42f488b63a04fdaa931315bdadecb6d23e20529a.diff
LOG: [InstCombine] improve matching for sext-lshr-trunc patterns
This is intended to preserve the logic of the existing transform,
but remove unnecessary restrictions on uses and types.
https://rise4fun.com/Alive/pYfR
Pre: C1 <= width(C1) - 8
%B = sext i8 %A
%C = lshr %B, C1
%r = trunc %C to i8
=>
%r = ashr i8 %A, trunc(umin(C1, 7))
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
llvm/test/Transforms/InstCombine/cast.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index bfe1fb7817df..7256c88f5dc3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -784,7 +784,21 @@ Instruction *InstCombiner::visitTrunc(TruncInst &Trunc) {
return CastInst::CreateIntegerCast(Shift, DestTy, false);
}
- // FIXME: We should canonicalize to zext/trunc and remove this transform.
+ const APInt *C;
+ if (match(Src, m_LShr(m_SExt(m_Value(A)), m_APInt(C))) &&
+ A->getType() == DestTy) {
+ // If the shift is small enough, all zero bits created by the shift are
+ // removed by the trunc:
+ // trunc (lshr (sext A), C) --> ashr A, C
+ if (C->getZExtValue() <= SrcWidth - DestWidth) {
+ unsigned ShAmt = std::min((unsigned)C->getZExtValue(), DestWidth - 1);
+ return BinaryOperator::CreateAShr(A, ConstantInt::get(DestTy, ShAmt));
+ }
+ // TODO: Mask high bits with 'and'.
+ }
+
+ // More complicated: deal with mismatched sizes.
+ // FIXME: This is too restrictive for uses and doesn't work with vectors.
// Transform trunc(lshr (sext A), Cst) to ashr A, Cst to eliminate type
// conversion.
// It works because bits coming from sign extension have the same value as
@@ -803,9 +817,6 @@ Instruction *InstCombiner::visitTrunc(TruncInst &Trunc) {
// FIXME: Instead of bailing when the shift is too large, use and to clear
// the extra bits.
if (ShiftAmt <= MaxAmt) {
- if (DestWidth == ASize)
- return BinaryOperator::CreateAShr(
- A, ConstantInt::get(DestTy, std::min(ShiftAmt, ASize - 1)));
if (SExt->hasOneUse()) {
Value *Shift = Builder.CreateAShr(A, std::min(ShiftAmt, ASize - 1));
Shift->takeName(Src);
diff --git a/llvm/test/Transforms/InstCombine/cast.ll b/llvm/test/Transforms/InstCombine/cast.ll
index 6215e6694cd6..ac6c814cd45a 100644
--- a/llvm/test/Transforms/InstCombine/cast.ll
+++ b/llvm/test/Transforms/InstCombine/cast.ll
@@ -1518,8 +1518,7 @@ define <2 x i8> @trunc_lshr_sext_uses1(<2 x i8> %A) {
; ALL-LABEL: @trunc_lshr_sext_uses1(
; ALL-NEXT: [[B:%.*]] = sext <2 x i8> [[A:%.*]] to <2 x i32>
; ALL-NEXT: call void @use_v2i32(<2 x i32> [[B]])
-; ALL-NEXT: [[C:%.*]] = lshr <2 x i32> [[B]], <i32 6, i32 6>
-; ALL-NEXT: [[D:%.*]] = trunc <2 x i32> [[C]] to <2 x i8>
+; ALL-NEXT: [[D:%.*]] = ashr <2 x i8> [[A]], <i8 6, i8 6>
; ALL-NEXT: ret <2 x i8> [[D]]
;
%B = sext <2 x i8> %A to <2 x i32>
@@ -1534,7 +1533,7 @@ define i8 @trunc_lshr_sext_uses2(i8 %A) {
; ALL-NEXT: [[B:%.*]] = sext i8 [[A:%.*]] to i32
; ALL-NEXT: [[C:%.*]] = lshr i32 [[B]], 6
; ALL-NEXT: call void @use_i32(i32 [[C]])
-; ALL-NEXT: [[D:%.*]] = trunc i32 [[C]] to i8
+; ALL-NEXT: [[D:%.*]] = ashr i8 [[A]], 6
; ALL-NEXT: ret i8 [[D]]
;
%B = sext i8 %A to i32
@@ -1550,7 +1549,7 @@ define <2 x i8 >@trunc_lshr_sext_uses3(<2 x i8> %A) {
; ALL-NEXT: call void @use_v2i32(<2 x i32> [[B]])
; ALL-NEXT: [[C:%.*]] = lshr <2 x i32> [[B]], <i32 6, i32 6>
; ALL-NEXT: call void @use_v2i32(<2 x i32> [[C]])
-; ALL-NEXT: [[D:%.*]] = trunc <2 x i32> [[C]] to <2 x i8>
+; ALL-NEXT: [[D:%.*]] = ashr <2 x i8> [[A]], <i8 6, i8 6>
; ALL-NEXT: ret <2 x i8> [[D]]
;
%B = sext <2 x i8 >%A to <2 x i32>
@@ -1563,9 +1562,7 @@ define <2 x i8 >@trunc_lshr_sext_uses3(<2 x i8> %A) {
define <2 x i8> @trunc_lshr_overshift_sext(<2 x i8> %A) {
; ALL-LABEL: @trunc_lshr_overshift_sext(
-; ALL-NEXT: [[B:%.*]] = sext <2 x i8> [[A:%.*]] to <2 x i32>
-; ALL-NEXT: [[C:%.*]] = lshr <2 x i32> [[B]], <i32 8, i32 8>
-; ALL-NEXT: [[D:%.*]] = trunc <2 x i32> [[C]] to <2 x i8>
+; ALL-NEXT: [[D:%.*]] = ashr <2 x i8> [[A:%.*]], <i8 7, i8 7>
; ALL-NEXT: ret <2 x i8> [[D]]
;
%B = sext <2 x i8> %A to <2 x i32>
@@ -1593,7 +1590,7 @@ define <2 x i8> @trunc_lshr_overshift_sext_uses2(<2 x i8> %A) {
; ALL-NEXT: [[B:%.*]] = sext <2 x i8> [[A:%.*]] to <2 x i32>
; ALL-NEXT: [[C:%.*]] = lshr <2 x i32> [[B]], <i32 8, i32 8>
; ALL-NEXT: call void @use_v2i32(<2 x i32> [[C]])
-; ALL-NEXT: [[D:%.*]] = trunc <2 x i32> [[C]] to <2 x i8>
+; ALL-NEXT: [[D:%.*]] = ashr <2 x i8> [[A]], <i8 7, i8 7>
; ALL-NEXT: ret <2 x i8> [[D]]
;
%B = sext <2 x i8> %A to <2 x i32>
@@ -1609,7 +1606,7 @@ define i8 @trunc_lshr_overshift_sext_uses3(i8 %A) {
; ALL-NEXT: call void @use_i32(i32 [[B]])
; ALL-NEXT: [[C:%.*]] = lshr i32 [[B]], 8
; ALL-NEXT: call void @use_i32(i32 [[C]])
-; ALL-NEXT: [[D:%.*]] = trunc i32 [[C]] to i8
+; ALL-NEXT: [[D:%.*]] = ashr i8 [[A]], 7
; ALL-NEXT: ret i8 [[D]]
;
%B = sext i8 %A to i32
More information about the llvm-commits
mailing list