Skip to content

Commit e88c255

Browse files
authored
[InstCombine] Add support for cast instructions in getFreelyInvertedImpl (#82451)
This patch adds support for cast instructions in `getFreelyInvertedImpl` to enable more optimizations. Alive2: https://alive2.llvm.org/ce/z/F6maEE
1 parent 2685e7e commit e88c255

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2387,6 +2387,20 @@ Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
23872387
return NonNull;
23882388
}
23892389

2390+
if (match(V, m_SExtLike(m_Value(A)))) {
2391+
if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
2392+
DoesConsume, Depth))
2393+
return Builder ? Builder->CreateSExt(AV, V->getType()) : NonNull;
2394+
return nullptr;
2395+
}
2396+
2397+
if (match(V, m_Trunc(m_Value(A)))) {
2398+
if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
2399+
DoesConsume, Depth))
2400+
return Builder ? Builder->CreateTrunc(AV, V->getType()) : NonNull;
2401+
return nullptr;
2402+
}
2403+
23902404
return nullptr;
23912405
}
23922406

llvm/test/Transforms/InstCombine/not.ll

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,3 +769,92 @@ entry:
769769
%cmp = icmp sle i32 %select, %not.c
770770
ret i1 %cmp
771771
}
772+
773+
define i32 @test_sext(i32 %a, i32 %b){
774+
; CHECK-LABEL: @test_sext(
775+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[A:%.*]], 0
776+
; CHECK-NEXT: [[TMP2:%.*]] = sext i1 [[TMP1]] to i32
777+
; CHECK-NEXT: [[NOT:%.*]] = sub i32 [[TMP2]], [[B:%.*]]
778+
; CHECK-NEXT: ret i32 [[NOT]]
779+
;
780+
%cmp = icmp eq i32 %a, 0
781+
%sext = sext i1 %cmp to i32
782+
%add = add i32 %b, %sext
783+
%not = xor i32 %add, -1
784+
ret i32 %not
785+
}
786+
787+
define <2 x i32> @test_sext_vec(<2 x i32> %a, <2 x i32> %b){
788+
; CHECK-LABEL: @test_sext_vec(
789+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[A:%.*]], zeroinitializer
790+
; CHECK-NEXT: [[TMP2:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
791+
; CHECK-NEXT: [[NOT:%.*]] = sub <2 x i32> [[TMP2]], [[B:%.*]]
792+
; CHECK-NEXT: ret <2 x i32> [[NOT]]
793+
;
794+
%cmp = icmp eq <2 x i32> %a, zeroinitializer
795+
%sext = sext <2 x i1> %cmp to <2 x i32>
796+
%add = add <2 x i32> %b, %sext
797+
%not = xor <2 x i32> %add, <i32 -1, i32 -1>
798+
ret <2 x i32> %not
799+
}
800+
801+
define i64 @test_zext_nneg(i32 %c1, i64 %c2, i64 %c3){
802+
; CHECK-LABEL: @test_zext_nneg(
803+
; CHECK-NEXT: [[DOTNEG:%.*]] = add i64 [[C2:%.*]], -4
804+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[C1:%.*]] to i64
805+
; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[TMP1]], [[C3:%.*]]
806+
; CHECK-NEXT: [[SUB:%.*]] = add i64 [[DOTNEG]], [[TMP2]]
807+
; CHECK-NEXT: ret i64 [[SUB]]
808+
;
809+
%not = xor i32 %c1, -1
810+
%conv = zext nneg i32 %not to i64
811+
%add1 = add i64 %c2, -5
812+
%add2 = add i64 %conv, %c3
813+
%sub = sub i64 %add1, %add2
814+
ret i64 %sub
815+
}
816+
817+
define i8 @test_trunc(i8 %a){
818+
; CHECK-LABEL: @test_trunc(
819+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i8 [[A:%.*]], 0
820+
; CHECK-NEXT: [[NOT:%.*]] = sext i1 [[TMP1]] to i8
821+
; CHECK-NEXT: ret i8 [[NOT]]
822+
;
823+
%zext = zext i8 %a to i32
824+
%sub = add nsw i32 %zext, -1
825+
%shr = ashr i32 %sub, 31
826+
%conv = trunc i32 %shr to i8
827+
%not = xor i8 %conv, -1
828+
ret i8 %not
829+
}
830+
831+
define <2 x i8> @test_trunc_vec(<2 x i8> %a){
832+
; CHECK-LABEL: @test_trunc_vec(
833+
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i8> [[A:%.*]], zeroinitializer
834+
; CHECK-NEXT: [[NOT:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i8>
835+
; CHECK-NEXT: ret <2 x i8> [[NOT]]
836+
;
837+
%zext = zext <2 x i8> %a to <2 x i32>
838+
%sub = add nsw <2 x i32> %zext, <i32 -1, i32 -1>
839+
%shr = ashr <2 x i32> %sub, <i32 31, i32 31>
840+
%conv = trunc <2 x i32> %shr to <2 x i8>
841+
%not = xor <2 x i8> %conv, <i8 -1, i8 -1>
842+
ret <2 x i8> %not
843+
}
844+
845+
; Negative tests
846+
847+
define i32 @test_zext(i32 %a, i32 %b){
848+
; CHECK-LABEL: @test_zext(
849+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
850+
; CHECK-NEXT: [[SEXT:%.*]] = zext i1 [[CMP]] to i32
851+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SEXT]], [[B:%.*]]
852+
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[ADD]], -1
853+
; CHECK-NEXT: ret i32 [[NOT]]
854+
;
855+
%cmp = icmp eq i32 %a, 0
856+
%sext = zext i1 %cmp to i32
857+
%add = add i32 %b, %sext
858+
%not = xor i32 %add, -1
859+
ret i32 %not
860+
}

0 commit comments

Comments
 (0)