Skip to content

Commit e07b596

Browse files
authored
[InstCombine] Fold select pattern with sub and negation to abs intrinsic (#156246)
```llvm %sub = sub nsw T %x, %y %cmp = icmp sgt T %x, %y ; or sge %neg = sub T 0, %sub %abs = select i1 %cmp, T %sub, T %neg ``` becomes: ```llvm %sub = sub nsw T %x, %y %abs = call T @llvm.abs.T(T %sub, i1 false) ``` Alive2: https://alive2.llvm.org/ce/z/ApdJX8 https://alive2.llvm.org/ce/z/gRTmZk
1 parent 94213a4 commit e07b596

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,38 @@ static Value *foldAbsDiff(ICmpInst *Cmp, Value *TVal, Value *FVal,
11531153
return Builder.CreateBinaryIntrinsic(Intrinsic::abs, TI, Builder.getTrue());
11541154
}
11551155

1156+
// Match: (A > B) ? (A - B) : (0 - (A - B)) --> abs(A - B)
1157+
if (Pred == CmpInst::ICMP_SGT &&
1158+
match(TI, m_NSWSub(m_Specific(A), m_Specific(B))) &&
1159+
match(FI, m_Neg(m_Specific(TI)))) {
1160+
return Builder.CreateBinaryIntrinsic(Intrinsic::abs, TI,
1161+
Builder.getFalse());
1162+
}
1163+
1164+
// Match: (A < B) ? (0 - (A - B)) : (A - B) --> abs(A - B)
1165+
if (Pred == CmpInst::ICMP_SLT &&
1166+
match(FI, m_NSWSub(m_Specific(A), m_Specific(B))) &&
1167+
match(TI, m_Neg(m_Specific(FI)))) {
1168+
return Builder.CreateBinaryIntrinsic(Intrinsic::abs, FI,
1169+
Builder.getFalse());
1170+
}
1171+
1172+
// Match: (A > B) ? (0 - (B - A)) : (B - A) --> abs(B - A)
1173+
if (Pred == CmpInst::ICMP_SGT &&
1174+
match(FI, m_NSWSub(m_Specific(B), m_Specific(A))) &&
1175+
match(TI, m_Neg(m_Specific(FI)))) {
1176+
return Builder.CreateBinaryIntrinsic(Intrinsic::abs, FI,
1177+
Builder.getFalse());
1178+
}
1179+
1180+
// Match: (A < B) ? (B - A) : (0 - (B - A)) --> abs(B - A)
1181+
if (Pred == CmpInst::ICMP_SLT &&
1182+
match(TI, m_NSWSub(m_Specific(B), m_Specific(A))) &&
1183+
match(FI, m_Neg(m_Specific(TI)))) {
1184+
return Builder.CreateBinaryIntrinsic(Intrinsic::abs, TI,
1185+
Builder.getFalse());
1186+
}
1187+
11561188
return nullptr;
11571189
}
11581190

llvm/test/Transforms/InstCombine/abs-intrinsic.ll

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,4 +859,141 @@ define i32 @abs_range_metadata(i32 %x) {
859859
%b = and i32 %a, 15
860860
ret i32 %b
861861
}
862+
862863
!1 = !{i32 0, i32 16}
864+
865+
define i32 @abs_diff(i32 %x, i32 %y) {
866+
; CHECK-LABEL: @abs_diff(
867+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]]
868+
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 false)
869+
; CHECK-NEXT: ret i32 [[COND]]
870+
;
871+
%sub = sub nsw i32 %x, %y
872+
%cmp = icmp sgt i32 %x, %y
873+
%sub1 = sub i32 0, %sub
874+
%cond = select i1 %cmp, i32 %sub, i32 %sub1
875+
ret i32 %cond
876+
}
877+
878+
define i32 @abs_diff_neg_no_nsw_neg(i32 %x, i32 %y) {
879+
; CHECK-LABEL: @abs_diff_neg_no_nsw_neg(
880+
; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]]
881+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
882+
; CHECK-NEXT: [[SUB1:%.*]] = sub i32 0, [[SUB]]
883+
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[SUB1]]
884+
; CHECK-NEXT: ret i32 [[COND]]
885+
;
886+
%sub = sub i32 %x, %y
887+
%cmp = icmp sgt i32 %x, %y
888+
%sub1 = sub i32 0, %sub
889+
%cond = select i1 %cmp, i32 %sub, i32 %sub1
890+
ret i32 %cond
891+
}
892+
893+
define i32 @abs_diff_neg(i32 %x, i32 %y) {
894+
; CHECK-LABEL: @abs_diff_neg(
895+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[Y:%.*]], [[X:%.*]]
896+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
897+
; CHECK-NEXT: [[SUB1:%.*]] = sub i32 0, [[SUB]]
898+
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[SUB1]]
899+
; CHECK-NEXT: ret i32 [[COND]]
900+
;
901+
%sub = sub nsw i32 %y, %x
902+
%cmp = icmp sgt i32 %x, %y
903+
%sub1 = sub i32 0, %sub
904+
%cond = select i1 %cmp, i32 %sub, i32 %sub1
905+
ret i32 %cond
906+
}
907+
908+
define i32 @abs_diff_neg_no_nsw(i32 %x, i32 %y) {
909+
; CHECK-LABEL: @abs_diff_neg_no_nsw(
910+
; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[Y:%.*]], [[X:%.*]]
911+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
912+
; CHECK-NEXT: [[SUB1:%.*]] = sub i32 0, [[SUB]]
913+
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[SUB1]]
914+
; CHECK-NEXT: ret i32 [[COND]]
915+
;
916+
%sub = sub i32 %y, %x
917+
%cmp = icmp sgt i32 %x, %y
918+
%sub1 = sub i32 0, %sub
919+
%cond = select i1 %cmp, i32 %sub, i32 %sub1
920+
ret i32 %cond
921+
}
922+
923+
define i32 @abs_diff_ge(i32 %x, i32 %y) {
924+
; CHECK-LABEL: @abs_diff_ge(
925+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]]
926+
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 false)
927+
; CHECK-NEXT: ret i32 [[COND]]
928+
;
929+
%sub = sub nsw i32 %x, %y
930+
%cmp = icmp sge i32 %x, %y
931+
%sub1 = sub i32 0, %sub
932+
%cond = select i1 %cmp, i32 %sub, i32 %sub1
933+
ret i32 %cond
934+
}
935+
936+
define i32 @abs_diff_slt_commute(i32 %x, i32 %y) {
937+
; CHECK-LABEL: @abs_diff_slt_commute(
938+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]]
939+
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 false)
940+
; CHECK-NEXT: ret i32 [[COND]]
941+
;
942+
%sub = sub nsw i32 %x, %y
943+
%cmp = icmp slt i32 %y, %x
944+
%sub1 = sub i32 0, %sub
945+
%cond = select i1 %cmp, i32 %sub, i32 %sub1
946+
ret i32 %cond
947+
}
948+
949+
define i32 @abs_diff_sge_same(i32 %x, i32 %y) {
950+
; CHECK-LABEL: @abs_diff_sge_same(
951+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]]
952+
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 false)
953+
; CHECK-NEXT: ret i32 [[COND]]
954+
;
955+
%sub = sub nsw i32 %x, %y
956+
%cmp = icmp sge i32 %x, %y
957+
%sub1 = sub i32 0, %sub
958+
%cond = select i1 %cmp, i32 %sub, i32 %sub1
959+
ret i32 %cond
960+
}
961+
962+
define i32 @abs_diff_sle_inverted(i32 %x, i32 %y) {
963+
; CHECK-LABEL: @abs_diff_sle_inverted(
964+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]]
965+
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 false)
966+
; CHECK-NEXT: ret i32 [[COND]]
967+
;
968+
%sub = sub nsw i32 %x, %y
969+
%cmp = icmp sle i32 %x, %y
970+
%sub1 = sub i32 0, %sub
971+
%cond = select i1 %cmp, i32 %sub1, i32 %sub
972+
ret i32 %cond
973+
}
974+
975+
define i32 @abs_diff_sle_commute(i32 %x, i32 %y) {
976+
; CHECK-LABEL: @abs_diff_sle_commute(
977+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]]
978+
; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 false)
979+
; CHECK-NEXT: ret i32 [[COND]]
980+
;
981+
%sub = sub nsw i32 %x, %y
982+
%cmp = icmp sle i32 %y, %x
983+
%sub1 = sub i32 0, %sub
984+
%cond = select i1 %cmp, i32 %sub, i32 %sub1
985+
ret i32 %cond
986+
}
987+
988+
define i8 @abs_diff_sle_y_x(i8 %x, i8 %y) {
989+
; CHECK-LABEL: @abs_diff_sle_y_x(
990+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
991+
; CHECK-NEXT: [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB]], i1 false)
992+
; CHECK-NEXT: ret i8 [[COND]]
993+
;
994+
%sub = sub nsw i8 %x, %y
995+
%cmp = icmp sle i8 %y, %x
996+
%sub1 = sub i8 0, %sub
997+
%cond = select i1 %cmp, i8 %sub, i8 %sub1
998+
ret i8 %cond
999+
}

0 commit comments

Comments
 (0)