Skip to content

Commit c2c048f

Browse files
committed
[InstCombine] add folds for sext(trunc nsw) and zext(trunc nuw)
1 parent 331fbc5 commit c2c048f

File tree

3 files changed

+44
-26
lines changed

3 files changed

+44
-26
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,25 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) {
11981198
if (SrcTy->isIntOrIntVectorTy(1) && Zext.hasNonNeg())
11991199
return replaceInstUsesWith(Zext, Constant::getNullValue(Zext.getType()));
12001200

1201+
Value *X;
1202+
// If trunc has nuw flag, then convert directly to final type.
1203+
if (match(Src, m_NUWTrunc(m_Value(X)))) {
1204+
unsigned XSize = X->getType()->getScalarSizeInBits();
1205+
unsigned DstSize = DestTy->getScalarSizeInBits();
1206+
if (XSize == DstSize)
1207+
return replaceInstUsesWith(Zext, X);
1208+
if (XSize < DstSize) {
1209+
auto *Res = new ZExtInst(X, DestTy);
1210+
Res->setNonNeg();
1211+
return Res;
1212+
}
1213+
if (XSize > DstSize) {
1214+
auto *Res = new TruncInst(X, DestTy);
1215+
Res->setHasNoUnsignedWrap(true);
1216+
return Res;
1217+
}
1218+
}
1219+
12011220
// Try to extend the entire expression tree to the wide destination type.
12021221
unsigned BitsToClear;
12031222
if (shouldChangeType(SrcTy, DestTy) &&
@@ -1277,7 +1296,6 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) {
12771296

12781297
// zext(trunc(X) & C) -> (X & zext(C)).
12791298
Constant *C;
1280-
Value *X;
12811299
if (match(Src, m_OneUse(m_And(m_Trunc(m_Value(X)), m_Constant(C)))) &&
12821300
X->getType() == DestTy)
12831301
return BinaryOperator::CreateAnd(X, Builder.CreateZExt(C, DestTy));
@@ -1491,6 +1509,21 @@ Instruction *InstCombinerImpl::visitSExt(SExtInst &Sext) {
14911509
return CI;
14921510
}
14931511

1512+
Value *X;
1513+
// If trunc has nsw flag, then convert directly to final type.
1514+
if (match(Src, m_NSWTrunc(m_Value(X)))) {
1515+
unsigned XBitSize = X->getType()->getScalarSizeInBits();
1516+
if (XBitSize == DestBitSize)
1517+
return replaceInstUsesWith(Sext, X);
1518+
if (XBitSize < DestBitSize)
1519+
return new SExtInst(X, DestTy);
1520+
if (XBitSize > DestBitSize) {
1521+
auto *Res = new TruncInst(X, DestTy);
1522+
Res->setHasNoSignedWrap(true);
1523+
return Res;
1524+
}
1525+
}
1526+
14941527
// Try to extend the entire expression tree to the wide destination type.
14951528
if (shouldChangeType(SrcTy, DestTy) && canEvaluateSExtd(Src, DestTy)) {
14961529
// Okay, we can transform this! Insert the new expression now.
@@ -1512,7 +1545,6 @@ Instruction *InstCombinerImpl::visitSExt(SExtInst &Sext) {
15121545
ShAmt);
15131546
}
15141547

1515-
Value *X;
15161548
if (match(Src, m_Trunc(m_Value(X)))) {
15171549
// If the input has more sign bits than bits truncated, then convert
15181550
// directly to final type.

llvm/test/Transforms/InstCombine/sext.ll

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,7 @@ define i64 @smear_set_bit_different_dest_type_wider_dst(i32 %x) {
426426

427427
define i32 @sext_trunc_nsw(i16 %x) {
428428
; CHECK-LABEL: @sext_trunc_nsw(
429-
; CHECK-NEXT: [[C:%.*]] = zext i16 [[X:%.*]] to i32
430-
; CHECK-NEXT: [[SEXT:%.*]] = shl i32 [[C]], 24
431-
; CHECK-NEXT: [[E:%.*]] = ashr exact i32 [[SEXT]], 24
429+
; CHECK-NEXT: [[E:%.*]] = sext i16 [[X:%.*]] to i32
432430
; CHECK-NEXT: ret i32 [[E]]
433431
;
434432
%c = trunc nsw i16 %x to i8
@@ -438,9 +436,7 @@ define i32 @sext_trunc_nsw(i16 %x) {
438436

439437
define i16 @sext_trunc_nsw_2(i32 %x) {
440438
; CHECK-LABEL: @sext_trunc_nsw_2(
441-
; CHECK-NEXT: [[C:%.*]] = trunc i32 [[X:%.*]] to i16
442-
; CHECK-NEXT: [[SEXT:%.*]] = shl i16 [[C]], 8
443-
; CHECK-NEXT: [[E:%.*]] = ashr exact i16 [[SEXT]], 8
439+
; CHECK-NEXT: [[E:%.*]] = trunc nsw i32 [[X:%.*]] to i16
444440
; CHECK-NEXT: ret i16 [[E]]
445441
;
446442
%c = trunc nsw i32 %x to i8
@@ -450,9 +446,7 @@ define i16 @sext_trunc_nsw_2(i32 %x) {
450446

451447
define i16 @sext_trunc_nsw_3(i16 %x) {
452448
; CHECK-LABEL: @sext_trunc_nsw_3(
453-
; CHECK-NEXT: [[SEXT:%.*]] = shl i16 [[X:%.*]], 8
454-
; CHECK-NEXT: [[E:%.*]] = ashr exact i16 [[SEXT]], 8
455-
; CHECK-NEXT: ret i16 [[E]]
449+
; CHECK-NEXT: ret i16 [[E:%.*]]
456450
;
457451
%c = trunc nsw i16 %x to i8
458452
%e = sext i8 %c to i16
@@ -463,9 +457,7 @@ define i16 @sext_trunc_nsw_use(i16 %x) {
463457
; CHECK-LABEL: @sext_trunc_nsw_use(
464458
; CHECK-NEXT: [[C:%.*]] = trunc nsw i16 [[X:%.*]] to i8
465459
; CHECK-NEXT: call void @use(i8 [[C]])
466-
; CHECK-NEXT: [[SEXT:%.*]] = shl i16 [[X]], 8
467-
; CHECK-NEXT: [[E:%.*]] = ashr exact i16 [[SEXT]], 8
468-
; CHECK-NEXT: ret i16 [[E]]
460+
; CHECK-NEXT: ret i16 [[X]]
469461
;
470462
%c = trunc nsw i16 %x to i8
471463
call void @use(i8 %c)
@@ -475,8 +467,7 @@ define i16 @sext_trunc_nsw_use(i16 %x) {
475467

476468
define <2 x i32> @sext_trunc_nsw_vec(<2 x i16> %x) {
477469
; CHECK-LABEL: @sext_trunc_nsw_vec(
478-
; CHECK-NEXT: [[C:%.*]] = trunc nsw <2 x i16> [[X:%.*]] to <2 x i8>
479-
; CHECK-NEXT: [[E:%.*]] = sext <2 x i8> [[C]] to <2 x i32>
470+
; CHECK-NEXT: [[E:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32>
480471
; CHECK-NEXT: ret <2 x i32> [[E]]
481472
;
482473
%c = trunc nsw <2 x i16> %x to <2 x i8>

llvm/test/Transforms/InstCombine/zext.ll

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -979,8 +979,7 @@ entry:
979979

980980
define i32 @zext_trunc_nuw(i16 %x) {
981981
; CHECK-LABEL: @zext_trunc_nuw(
982-
; CHECK-NEXT: [[X:%.*]] = and i16 [[X1:%.*]], 255
983-
; CHECK-NEXT: [[E1:%.*]] = zext nneg i16 [[X]] to i32
982+
; CHECK-NEXT: [[E1:%.*]] = zext nneg i16 [[X:%.*]] to i32
984983
; CHECK-NEXT: ret i32 [[E1]]
985984
;
986985
%c = trunc nuw i16 %x to i8
@@ -990,8 +989,7 @@ define i32 @zext_trunc_nuw(i16 %x) {
990989

991990
define i16 @zext_trunc_nuw_2(i32 %x) {
992991
; CHECK-LABEL: @zext_trunc_nuw_2(
993-
; CHECK-NEXT: [[C:%.*]] = trunc i32 [[X:%.*]] to i16
994-
; CHECK-NEXT: [[E:%.*]] = and i16 [[C]], 255
992+
; CHECK-NEXT: [[E:%.*]] = trunc nuw i32 [[X:%.*]] to i16
995993
; CHECK-NEXT: ret i16 [[E]]
996994
;
997995
%c = trunc nuw i32 %x to i8
@@ -1001,8 +999,7 @@ define i16 @zext_trunc_nuw_2(i32 %x) {
1001999

10021000
define i16 @zext_trunc_nuw_3(i16 %x) {
10031001
; CHECK-LABEL: @zext_trunc_nuw_3(
1004-
; CHECK-NEXT: [[E:%.*]] = and i16 [[X:%.*]], 255
1005-
; CHECK-NEXT: ret i16 [[E]]
1002+
; CHECK-NEXT: ret i16 [[E:%.*]]
10061003
;
10071004
%c = trunc nuw i16 %x to i8
10081005
%e = zext i8 %c to i16
@@ -1013,8 +1010,7 @@ define i16 @zext_trunc_nuw_use(i16 %x) {
10131010
; CHECK-LABEL: @zext_trunc_nuw_use(
10141011
; CHECK-NEXT: [[C:%.*]] = trunc nuw i16 [[X:%.*]] to i8
10151012
; CHECK-NEXT: call void @use64(i8 [[C]])
1016-
; CHECK-NEXT: [[E:%.*]] = and i16 [[X]], 255
1017-
; CHECK-NEXT: ret i16 [[E]]
1013+
; CHECK-NEXT: ret i16 [[X]]
10181014
;
10191015
%c = trunc nuw i16 %x to i8
10201016
call void @use64(i8 %c)
@@ -1024,8 +1020,7 @@ define i16 @zext_trunc_nuw_use(i16 %x) {
10241020

10251021
define <2 x i32> @zext_trunc_nuw_vec(<2 x i16> %x) {
10261022
; CHECK-LABEL: @zext_trunc_nuw_vec(
1027-
; CHECK-NEXT: [[X:%.*]] = and <2 x i16> [[X1:%.*]], <i16 255, i16 255>
1028-
; CHECK-NEXT: [[E1:%.*]] = zext nneg <2 x i16> [[X]] to <2 x i32>
1023+
; CHECK-NEXT: [[E1:%.*]] = zext nneg <2 x i16> [[X:%.*]] to <2 x i32>
10291024
; CHECK-NEXT: ret <2 x i32> [[E1]]
10301025
;
10311026
%c = trunc nuw <2 x i16> %x to <2 x i8>

0 commit comments

Comments
 (0)