[llvm] [InstCombine] Extend canonicalization of addition to positive numbers (PR #179343)

via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 3 06:59:21 PST 2026


https://github.com/SiliconA-Z updated https://github.com/llvm/llvm-project/pull/179343

>From 4a4d8590383f7d60cc1a37b82316d97e28c7f348 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Mon, 2 Feb 2026 16:10:42 -0500
Subject: [PATCH 1/2] Pre-commit tests (NFC)

---
 .../InstCombine/saturating-add-sub.ll         | 144 ++++++++++++++++++
 1 file changed, 144 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/saturating-add-sub.ll b/llvm/test/Transforms/InstCombine/saturating-add-sub.ll
index 80676de47f193..61c7499883d2b 100644
--- a/llvm/test/Transforms/InstCombine/saturating-add-sub.ll
+++ b/llvm/test/Transforms/InstCombine/saturating-add-sub.ll
@@ -2708,6 +2708,150 @@ define i8 @neg_neg_constant(i8 %x, i8 %y) {
   ret i8 %s
 }
 
+;
+; Negative constant signed saturated add - saturates to INT_MIN
+;
+
+; Basic pattern: (x <= threshold) ? INT_MIN : (x + C) where C < 0
+; threshold should be INT_MIN - C or INT_MIN - C + 1
+
+; (x <= -119) ? -128 : (x + -10) --> sadd.sat(x, -10)
+define i8 @sadd_sat_neg_constant(i8 %x) {
+; CHECK-LABEL: @sadd_sat_neg_constant(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 -118)
+; CHECK-NEXT:    [[R:%.*]] = add nsw i8 [[TMP1]], -10
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %cmp = icmp sle i8 %x, -119
+  %add = add i8 %x, -10
+  %r = select i1 %cmp, i8 -128, i8 %add
+  ret i8 %r
+}
+
+; (x < -118) ? -128 : (x + -10) --> sadd.sat(x, -10)
+define i8 @sadd_sat_neg_constant_slt(i8 %x) {
+; CHECK-LABEL: @sadd_sat_neg_constant_slt(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 -118)
+; CHECK-NEXT:    [[R:%.*]] = add nsw i8 [[TMP1]], -10
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %cmp = icmp slt i8 %x, -118
+  %add = add i8 %x, -10
+  %r = select i1 %cmp, i8 -128, i8 %add
+  ret i8 %r
+}
+
+; Commuted select: (x >= threshold) ? (x + C) : INT_MIN --> sadd.sat(x, C)
+define i8 @sadd_sat_neg_constant_commuted_select(i8 %x) {
+; CHECK-LABEL: @sadd_sat_neg_constant_commuted_select(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 -118)
+; CHECK-NEXT:    [[R:%.*]] = add nsw i8 [[TMP1]], -10
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %cmp = icmp sge i8 %x, -118
+  %add = add i8 %x, -10
+  %r = select i1 %cmp, i8 %add, i8 -128
+  ret i8 %r
+}
+
+; sle minimum signed value is canonicalized to eq and requires special handling
+; (x == INT_MIN) ? INT_MIN : x + -1 --> sadd.sat(x, -1)
+define i8 @sadd_sat_eq_int_min(i8 %x) {
+; CHECK-LABEL: @sadd_sat_eq_int_min(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X:%.*]], -128
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], -1
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i8 -128, i8 [[ADD]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %cmp = icmp eq i8 %x, -128
+  %add = add i8 %x, -1
+  %r = select i1 %cmp, i8 -128, i8 %add
+  ret i8 %r
+}
+
+; Vector version of negative constant pattern
+define <2 x i8> @sadd_sat_neg_constant_vector(<2 x i8> %x) {
+; CHECK-LABEL: @sadd_sat_neg_constant_vector(
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[X:%.*]], <2 x i8> splat (i8 -118))
+; CHECK-NEXT:    [[R:%.*]] = add nsw <2 x i8> [[TMP1]], splat (i8 -10)
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %cmp = icmp sle <2 x i8> %x, <i8 -119, i8 -119>
+  %add = add <2 x i8> %x, <i8 -10, i8 -10>
+  %r = select <2 x i1> %cmp, <2 x i8> <i8 -128, i8 -128>, <2 x i8> %add
+  ret <2 x i8> %r
+}
+
+; Pattern with variable: (INT_MIN - X > Y) ? INT_MIN : (X + Y) with nsw sub
+define i8 @sadd_sat_int_min_minus_x_nsw(i8 %x, i8 %y) {
+; CHECK-LABEL: @sadd_sat_int_min_minus_x_nsw(
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 -128, [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[SUB]], [[Y:%.*]]
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], [[Y]]
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i8 -128, i8 [[ADD]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %sub = sub nsw i8 -128, %x
+  %cmp = icmp sgt i8 %sub, %y
+  %add = add i8 %x, %y
+  %r = select i1 %cmp, i8 -128, i8 %add
+  ret i8 %r
+}
+
+; Negative test: wrong saturation value
+define i8 @sadd_sat_neg_constant_wrong_sat_value(i8 %x) {
+; CHECK-LABEL: @sadd_sat_neg_constant_wrong_sat_value(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], -118
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], -10
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i8 -127, i8 [[ADD]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %cmp = icmp sle i8 %x, -119
+  %add = add i8 %x, -10
+  %r = select i1 %cmp, i8 -127, i8 %add
+  ret i8 %r
+}
+
+; Boundary case: threshold allows exact match at the saturation limit
+define i8 @sadd_sat_neg_constant_boundary(i8 %x) {
+; CHECK-LABEL: @sadd_sat_neg_constant_boundary(
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 -10)
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %cmp = icmp sle i8 %x, -118
+  %add = add i8 %x, -10
+  %r = select i1 %cmp, i8 -128, i8 %add
+  ret i8 %r
+}
+
+; Negative test: threshold too high
+define i8 @sadd_sat_neg_constant_wrong_threshold(i8 %x) {
+; CHECK-LABEL: @sadd_sat_neg_constant_wrong_threshold(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], -116
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], -10
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i8 -128, i8 [[ADD]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %cmp = icmp sle i8 %x, -117
+  %add = add i8 %x, -10
+  %r = select i1 %cmp, i8 -128, i8 %add
+  ret i8 %r
+}
+
+; Negative test: positive constant (should use INT_MAX saturation, not INT_MIN)
+define i8 @sadd_sat_neg_pattern_positive_constant(i8 %x) {
+; CHECK-LABEL: @sadd_sat_neg_pattern_positive_constant(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], -118
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], 10
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i8 -128, i8 [[ADD]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %cmp = icmp sle i8 %x, -119
+  %add = add i8 %x, 10
+  %r = select i1 %cmp, i8 -128, i8 %add
+  ret i8 %r
+}
+
 ; Make sure we don't crash in this case.
 define i32 @pr153053_strict_pred_with_nonconstant_rhs(i32 %x, i32 %y) {
 ; CHECK-LABEL: @pr153053_strict_pred_with_nonconstant_rhs(

>From fdeea0a6c9f1013601ace93b0f1c99a595c346ce Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Mon, 2 Feb 2026 16:29:24 -0500
Subject: [PATCH 2/2] [InstCombine] Extend canonicalization of addition to
 positive numbers

https://alive2.llvm.org/ce/z/6PQdaP

Extend this to positive numbers too.
---
 .../InstCombine/InstCombineSelect.cpp         | 88 ++++++++++++++-----
 .../InstCombine/saturating-add-sub.ll         | 21 ++---
 2 files changed, 72 insertions(+), 37 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index fb30a4545cffe..62ace0474ed7c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1147,39 +1147,48 @@ static Value *canonicalizeSaturatedAddSigned(ICmpInst *Cmp, Value *TVal,
   Value *Cmp0 = Cmp->getOperand(0);
   Value *Cmp1 = Cmp->getOperand(1);
   ICmpInst::Predicate Pred = Cmp->getPredicate();
-  Value *X;
-  const APInt *C;
 
-  // Canonicalize INT_MAX to true value of the select.
-  if (match(FVal, m_MaxSignedValue())) {
+  // Canonicalize TVal to be the saturation constant.
+  if (match(FVal, m_MaxSignedValue()) || match(FVal, m_SignMask())) {
     std::swap(TVal, FVal);
     Pred = CmpInst::getInversePredicate(Pred);
   }
 
-  if (!match(TVal, m_MaxSignedValue()))
+  const APInt *SatC;
+  if (!match(TVal, m_APInt(SatC)) ||
+      !(SatC->isMaxSignedValue() || SatC->isSignMask()))
     return nullptr;
 
+  bool IsMax = SatC->isMaxSignedValue();
+
   // sge maximum signed value is canonicalized to eq maximum signed value and
-  // requires special handling (a == INT_MAX) ? INT_MAX : a + 1 -> sadd.sat(a,
-  // 1)
-  if (Pred == ICmpInst::ICMP_EQ) {
-    if (match(FVal, m_Add(m_Specific(Cmp0), m_One())) && Cmp1 == TVal) {
+  // requires special handling. sle minimum signed value is similarly
+  // canonicalized to eq minimum signed value.
+  if (Pred == ICmpInst::ICMP_EQ && Cmp1 == TVal) {
+    // (a == INT_MAX) ? INT_MAX : a + 1 -> sadd.sat(a, 1)
+    if (IsMax && match(FVal, m_Add(m_Specific(Cmp0), m_One()))) {
       return Builder.CreateBinaryIntrinsic(
           Intrinsic::sadd_sat, Cmp0, ConstantInt::get(Cmp0->getType(), 1));
     }
+
+    // (a == INT_MIN) ? INT_MIN : a + -1 -> sadd.sat(a, -1)
+    if (!IsMax && match(FVal, m_Add(m_Specific(Cmp0), m_AllOnes()))) {
+      return Builder.CreateBinaryIntrinsic(
+          Intrinsic::sadd_sat, Cmp0,
+          ConstantInt::getAllOnesValue(Cmp0->getType()));
+    }
     return nullptr;
   }
 
+  const APInt *C;
+
   // (X > Y) ? INT_MAX : (X + C) --> sadd.sat(X, C)
   // (X >= Y) ? INT_MAX : (X + C) --> sadd.sat(X, C)
-  // where Y is INT_MAX - C or INT_MAX - C - 1, and C > 0
-  if ((Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) &&
+  // where C > 0 and Y is INT_MAX - C or INT_MAX - C - 1
+  if (IsMax && (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) &&
       isa<Constant>(Cmp1) &&
       match(FVal, m_Add(m_Specific(Cmp0), m_StrictlyPositive(C)))) {
-    APInt IntMax =
-        APInt::getSignedMaxValue(Cmp1->getType()->getScalarSizeInBits());
-
-    // For SGE, try to flip to SGT to normalize the comparison constant.
+    // Normalize SGE to SGT for threshold comparison.
     if (Pred == ICmpInst::ICMP_SGE) {
       if (auto Flipped = getFlippedStrictnessPredicateAndConstant(
               Pred, cast<Constant>(Cmp1))) {
@@ -1187,11 +1196,35 @@ static Value *canonicalizeSaturatedAddSigned(ICmpInst *Cmp, Value *TVal,
         Cmp1 = Flipped->second;
       }
     }
-
-    // Check the pattern: X > INT_MAX - C or X > INT_MAX - C - 1
+    // Check: X > INT_MAX - C or X > INT_MAX - C - 1
+    APInt Threshold = *SatC - *C;
     if (Pred == ICmpInst::ICMP_SGT &&
-        (match(Cmp1, m_SpecificIntAllowPoison(IntMax - *C)) ||
-         match(Cmp1, m_SpecificIntAllowPoison(IntMax - *C - 1))))
+        (match(Cmp1, m_SpecificIntAllowPoison(Threshold)) ||
+         match(Cmp1, m_SpecificIntAllowPoison(Threshold - 1))))
+      return Builder.CreateBinaryIntrinsic(
+          Intrinsic::sadd_sat, Cmp0, ConstantInt::get(Cmp0->getType(), *C));
+  }
+
+  // (X < Y) ? INT_MIN : (X + C) --> sadd.sat(X, C)
+  // (X <= Y) ? INT_MIN : (X + C) --> sadd.sat(X, C)
+  // where C < 0 and Y is INT_MIN - C or INT_MIN - C + 1
+  if (!IsMax && (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE) &&
+      isa<Constant>(Cmp1) &&
+      match(FVal, m_Add(m_Specific(Cmp0), m_Negative(C)))) {
+    // Normalize SLE to SLT for threshold comparison.
+    if (Pred == ICmpInst::ICMP_SLE) {
+      if (auto Flipped = getFlippedStrictnessPredicateAndConstant(
+              Pred, cast<Constant>(Cmp1))) {
+        Pred = Flipped->first;
+        Cmp1 = Flipped->second;
+      }
+    }
+    // Check: X < INT_MIN - C or X < INT_MIN - C + 1
+    // INT_MIN - C for negative C is like INT_MIN + |C|
+    APInt Threshold = *SatC - *C;
+    if (Pred == ICmpInst::ICMP_SLT &&
+        (match(Cmp1, m_SpecificIntAllowPoison(Threshold)) ||
+         match(Cmp1, m_SpecificIntAllowPoison(Threshold + 1))))
       return Builder.CreateBinaryIntrinsic(
           Intrinsic::sadd_sat, Cmp0, ConstantInt::get(Cmp0->getType(), *C));
   }
@@ -1205,13 +1238,24 @@ static Value *canonicalizeSaturatedAddSigned(ICmpInst *Cmp, Value *TVal,
   if (Pred != ICmpInst::ICMP_SLT && Pred != ICmpInst::ICMP_SLE)
     return nullptr;
 
-  if (match(Cmp0, m_NSWSub(m_MaxSignedValue(), m_Value(X))) &&
+  Value *X;
+
+  // (INT_MAX - X s< Y) ? INT_MAX : (X + Y) --> sadd.sat(X, Y)
+  // (INT_MAX - X s< Y) ? INT_MAX : (Y + X) --> sadd.sat(X, Y)
+  if (IsMax && match(Cmp0, m_NSWSub(m_SpecificInt(*SatC), m_Value(X))) &&
       match(FVal, m_c_Add(m_Specific(X), m_Specific(Cmp1)))) {
-    // (INT_MAX - X s< Y) ? INT_MAX : (X + Y) --> sadd.sat(X, Y)
-    // (INT_MAX - X s< Y) ? INT_MAX : (Y + X) --> sadd.sat(X, Y)
     return Builder.CreateBinaryIntrinsic(Intrinsic::sadd_sat, X, Cmp1);
   }
 
+  // (INT_MIN - X s> Y) ? INT_MIN : (X + Y) --> sadd.sat(X, Y)
+  // (INT_MIN - X s> Y) ? INT_MIN : (Y + X) --> sadd.sat(X, Y)
+  // After swapping operands from the SGT/SGE canonicalization above,
+  // this becomes (Y s< INT_MIN - X).
+  if (!IsMax && match(Cmp1, m_NSWSub(m_SpecificInt(*SatC), m_Value(X))) &&
+      match(FVal, m_c_Add(m_Specific(X), m_Specific(Cmp0)))) {
+    return Builder.CreateBinaryIntrinsic(Intrinsic::sadd_sat, X, Cmp0);
+  }
+
   return nullptr;
 }
 
diff --git a/llvm/test/Transforms/InstCombine/saturating-add-sub.ll b/llvm/test/Transforms/InstCombine/saturating-add-sub.ll
index 61c7499883d2b..efa89db4af61a 100644
--- a/llvm/test/Transforms/InstCombine/saturating-add-sub.ll
+++ b/llvm/test/Transforms/InstCombine/saturating-add-sub.ll
@@ -2718,8 +2718,7 @@ define i8 @neg_neg_constant(i8 %x, i8 %y) {
 ; (x <= -119) ? -128 : (x + -10) --> sadd.sat(x, -10)
 define i8 @sadd_sat_neg_constant(i8 %x) {
 ; CHECK-LABEL: @sadd_sat_neg_constant(
-; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 -118)
-; CHECK-NEXT:    [[R:%.*]] = add nsw i8 [[TMP1]], -10
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 -10)
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %cmp = icmp sle i8 %x, -119
@@ -2731,8 +2730,7 @@ define i8 @sadd_sat_neg_constant(i8 %x) {
 ; (x < -118) ? -128 : (x + -10) --> sadd.sat(x, -10)
 define i8 @sadd_sat_neg_constant_slt(i8 %x) {
 ; CHECK-LABEL: @sadd_sat_neg_constant_slt(
-; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 -118)
-; CHECK-NEXT:    [[R:%.*]] = add nsw i8 [[TMP1]], -10
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 -10)
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %cmp = icmp slt i8 %x, -118
@@ -2744,8 +2742,7 @@ define i8 @sadd_sat_neg_constant_slt(i8 %x) {
 ; Commuted select: (x >= threshold) ? (x + C) : INT_MIN --> sadd.sat(x, C)
 define i8 @sadd_sat_neg_constant_commuted_select(i8 %x) {
 ; CHECK-LABEL: @sadd_sat_neg_constant_commuted_select(
-; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 -118)
-; CHECK-NEXT:    [[R:%.*]] = add nsw i8 [[TMP1]], -10
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 -10)
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %cmp = icmp sge i8 %x, -118
@@ -2758,9 +2755,7 @@ define i8 @sadd_sat_neg_constant_commuted_select(i8 %x) {
 ; (x == INT_MIN) ? INT_MIN : x + -1 --> sadd.sat(x, -1)
 define i8 @sadd_sat_eq_int_min(i8 %x) {
 ; CHECK-LABEL: @sadd_sat_eq_int_min(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X:%.*]], -128
-; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], -1
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i8 -128, i8 [[ADD]]
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 -1)
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %cmp = icmp eq i8 %x, -128
@@ -2772,8 +2767,7 @@ define i8 @sadd_sat_eq_int_min(i8 %x) {
 ; Vector version of negative constant pattern
 define <2 x i8> @sadd_sat_neg_constant_vector(<2 x i8> %x) {
 ; CHECK-LABEL: @sadd_sat_neg_constant_vector(
-; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[X:%.*]], <2 x i8> splat (i8 -118))
-; CHECK-NEXT:    [[R:%.*]] = add nsw <2 x i8> [[TMP1]], splat (i8 -10)
+; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[X:%.*]], <2 x i8> splat (i8 -10))
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %cmp = icmp sle <2 x i8> %x, <i8 -119, i8 -119>
@@ -2785,10 +2779,7 @@ define <2 x i8> @sadd_sat_neg_constant_vector(<2 x i8> %x) {
 ; Pattern with variable: (INT_MIN - X > Y) ? INT_MIN : (X + Y) with nsw sub
 define i8 @sadd_sat_int_min_minus_x_nsw(i8 %x, i8 %y) {
 ; CHECK-LABEL: @sadd_sat_int_min_minus_x_nsw(
-; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 -128, [[X:%.*]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[SUB]], [[Y:%.*]]
-; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], [[Y]]
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP]], i8 -128, i8 [[ADD]]
+; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %sub = sub nsw i8 -128, %x



More information about the llvm-commits mailing list