summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp14
-rw-r--r--llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll6
-rw-r--r--llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll33
3 files changed, 27 insertions, 26 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 0b6b7c3c66d..05a624fde86 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -704,11 +704,19 @@ static Value *canonicalizeSaturatedSubtract(const ICmpInst *ICI,
assert((Pred == ICmpInst::ICMP_UGE || Pred == ICmpInst::ICMP_UGT) &&
"Unexpected isUnsigned predicate!");
- // Account for swapped form of subtraction: ((a > b) ? b - a : 0).
+ // Ensure the sub is of the form:
+ // (a > b) ? a - b : 0 -> usub.sat(a, b)
+ // (a > b) ? b - a : 0 -> -usub.sat(a, b)
+ // Checking for both a-b and a+(-b) as a constant.
bool IsNegative = false;
- if (match(TrueVal, m_Sub(m_Specific(B), m_Specific(A))))
+ const APInt *C;
+ if (match(TrueVal, m_Sub(m_Specific(B), m_Specific(A))) ||
+ (match(A, m_APInt(C)) &&
+ match(TrueVal, m_Add(m_Specific(B), m_SpecificInt(-*C)))))
IsNegative = true;
- else if (!match(TrueVal, m_Sub(m_Specific(A), m_Specific(B))))
+ else if (!match(TrueVal, m_Sub(m_Specific(A), m_Specific(B))) &&
+ !(match(B, m_APInt(C)) &&
+ match(TrueVal, m_Add(m_Specific(A), m_SpecificInt(-*C)))))
return nullptr;
// If we are adding a negate and the sub and icmp are used anywhere else, we
diff --git a/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll b/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll
index 96d0772da38..4093a121060 100644
--- a/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll
+++ b/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll
@@ -48,10 +48,8 @@ entry:
; CHECK: define i64 @internal_pointer(i64 %sz)
; CHECK-NEXT: entry:
-; CHECK-NEXT: %0 = add i64 %sz, -2
-; CHECK-NEXT: %1 = icmp ult i64 %sz, 2
-; CHECK-NEXT: %2 = select i1 %1, i64 0, i64 %0
-; CHECK-NEXT: ret i64 %2
+; CHECK-NEXT: %0 = call i64 @llvm.usub.sat.i64(i64 %sz, i64 2)
+; CHECK-NEXT: ret i64 %0
; CHECK-NEXT: }
define i64 @uses_nullptr_no_fold() {
diff --git a/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll b/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll
index 4fa1b182d67..60da66b7a38 100644
--- a/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll
+++ b/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll
@@ -254,10 +254,8 @@ define i64 @neg_max_sub_ult_sel_swapped(i64 %a, i64 %b) {
define i32 @max_sub_ugt_c1(i32 %a) {
; CHECK-LABEL: @max_sub_ugt_c1(
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 1
-; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -1
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
-; CHECK-NEXT: ret i32 [[SEL]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 1)
+; CHECK-NEXT: ret i32 [[TMP1]]
;
%cmp = icmp ugt i32 %a, 1
%sub = add i32 %a, -1
@@ -280,10 +278,8 @@ define i32 @max_sub_ugt_c01(i32 %a) {
define i32 @max_sub_ugt_c10(i32 %a) {
; CHECK-LABEL: @max_sub_ugt_c10(
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 10
-; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -10
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
-; CHECK-NEXT: ret i32 [[SEL]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 10)
+; CHECK-NEXT: ret i32 [[TMP1]]
;
%cmp = icmp ugt i32 %a, 10
%sub = add i32 %a, -10
@@ -354,10 +350,9 @@ define i32 @max_sub_ult_c1(i32 %a) {
define i32 @max_sub_ult_c2(i32 %a) {
; CHECK-LABEL: @max_sub_ult_c2(
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 2
-; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -2
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
-; CHECK-NEXT: ret i32 [[SEL]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A:%.*]])
+; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]]
+; CHECK-NEXT: ret i32 [[TMP2]]
;
%cmp = icmp ult i32 %a, 2
%sub = add i32 %a, -2
@@ -368,10 +363,10 @@ define i32 @max_sub_ult_c2(i32 %a) {
define i32 @max_sub_ult_c2_oneuseicmp(i32 %a) {
; CHECK-LABEL: @max_sub_ult_c2_oneuseicmp(
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 2
-; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -2
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A]])
+; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]]
; CHECK-NEXT: call void @usei1(i1 [[CMP]])
-; CHECK-NEXT: ret i32 [[SEL]]
+; CHECK-NEXT: ret i32 [[TMP2]]
;
%cmp = icmp ult i32 %a, 2
%sub = add i32 %a, -2
@@ -382,11 +377,11 @@ define i32 @max_sub_ult_c2_oneuseicmp(i32 %a) {
define i32 @max_sub_ult_c2_oneusesub(i32 %a) {
; CHECK-LABEL: @max_sub_ult_c2_oneusesub(
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 2
-; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A]], -2
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
+; CHECK-NEXT: [[SUB:%.*]] = add i32 [[A:%.*]], -2
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A]])
+; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]]
; CHECK-NEXT: call void @usei32(i32 [[SUB]])
-; CHECK-NEXT: ret i32 [[SEL]]
+; CHECK-NEXT: ret i32 [[TMP2]]
;
%cmp = icmp ult i32 %a, 2
%sub = add i32 %a, -2
OpenPOWER on IntegriCloud