Skip to content

[ConstraintElim] Add NUW flag to sub if x >=u y. - #218685

Open
fhahn wants to merge 2 commits into
llvm:mainfrom
fhahn:ce-strenghten-ce-flags-sub
Open

[ConstraintElim] Add NUW flag to sub if x >=u y.#218685
fhahn wants to merge 2 commits into
llvm:mainfrom
fhahn:ce-strenghten-ce-flags-sub

Conversation

@fhahn

@fhahn fhahn commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Enables simplifications in a number of real-world cases:
dtcxzyw/llvm-opt-benchmark-nightly#1039

Note there are a few cases where we create a few more additional
instructions due to second-order effects. In most cases, it is
additional scalar PRE or replacing things like srem.

Alive2 Proof: https://alive2.llvm.org/ce/z/YqK3i3

@fhahn fhahn changed the title [ConstraintElim] Add NUW flag sub if x >=u y. [ConstraintElim] Add NUW flag to sub if x >=u y. Aug 25, 2026
@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-llvm-transforms

Author: Florian Hahn (fhahn)

Changes

Enables simplifications in a number of real-world cases:
dtcxzyw/llvm-opt-benchmark-nightly#1039

Note there are a few cases where we create a few more additional
instructions due to second-order effects. In most cases, it is
additional scalar PRE or replacing things like srem.

Alive2 Proof: https://alive2.llvm.org/ce/z/YqK3i3


Patch is 40.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/218685.diff

7 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/ConstraintElimination.cpp (+47-3)
  • (modified) llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit-postinc.ll (+1-1)
  • (added) llvm/test/Transforms/ConstraintElimination/materialize-flags-narrow-pointer-index.ll (+208)
  • (added) llvm/test/Transforms/ConstraintElimination/materialize-flags.ll (+457)
  • (modified) llvm/test/Transforms/ConstraintElimination/reproducer-remarks.ll (+1-1)
  • (modified) llvm/test/Transforms/ConstraintElimination/sub.ll (+1-1)
  • (added) llvm/test/Transforms/PhaseOrdering/constraint-elimination-materialize-flags.ll (+262)
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 054ab3b45e108..2699c1f8c7a5c 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -101,7 +101,7 @@ struct FactOrCheck {
     InstFact,      /// A fact that holds after Inst executed (e.g. an assume or
                    /// min/mix intrinsic.
     InstCheck,     /// An instruction to simplify (e.g. an overflow math
-                   /// intrinsics).
+                   /// intrinsics) or whose flags may be strengthened.
     UseCheck       /// An use of a compare instruction to simplify.
   };
 
@@ -146,8 +146,8 @@ struct FactOrCheck {
     return FactOrCheck(DTN, U);
   }
 
-  static FactOrCheck getCheck(DomTreeNode *DTN, CallInst *CI) {
-    return FactOrCheck(EntryTy::InstCheck, DTN, CI);
+  static FactOrCheck getCheck(DomTreeNode *DTN, Instruction *I) {
+    return FactOrCheck(EntryTy::InstCheck, DTN, I);
   }
 
   bool isCheck() const {
@@ -1291,6 +1291,41 @@ static bool getConstraintFromMemoryAccess(GetElementPtrInst &GEP,
   return true;
 }
 
+/// Returns true if \p I is a candidate whose poison-generating flags may be
+/// strengthened using the constraint systems.
+static bool canStrengthenFlags(Instruction *I) {
+  switch (I->getOpcode()) {
+  case Instruction::Sub:
+    // A - B does not wrap unsigned, if A >=u B. Constant operands are handled
+    // by CorrelatedValuePropagation using ranges.
+    return I->getType()->isIntegerTy() && !I->hasNoUnsignedWrap() &&
+           !isa<Constant>(I->getOperand(1));
+  default:
+    return false;
+  }
+}
+
+
+/// Try to strengthen \p I's poison generating flags using \p Info. Returns
+/// true if \p I was modified.
+static bool tryToStrengthenFlags(Instruction *I, ConstraintInfo &Info,
+                                 SmallVectorImpl<Instruction *> &ToRemove) {
+  assert(canStrengthenFlags(I) && "not a candidate for flag strengthening");
+
+  switch (I->getOpcode()) {
+  case Instruction::Sub: {
+    // Op0 - Op1 does not wrap unsigned, if Op0 >=u Op1.
+    if (!Info.doesHold(CmpInst::ICMP_UGE, I->getOperand(0), I->getOperand(1)))
+      return false;
+    LLVM_DEBUG(dbgs() << "Adding nuw to " << *I << "\n");
+    I->setHasNoUnsignedWrap();
+    return true;
+  }
+  default:
+    return false;
+  }
+}
+
 void State::addInfoFor(BasicBlock &BB) {
   addBoundsForHeaderInductions(BB);
   addInfoForInductions(BB);
@@ -1404,6 +1439,11 @@ void State::addInfoFor(BasicBlock &BB) {
         WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), BO));
     }
 
+    // Queue instructions whose flags may be strengthened based on the facts
+    // that hold on entry to BB.
+    if (canStrengthenFlags(&I))
+      WorkList.push_back(FactOrCheck::getCheck(DT.getNode(&BB), &I));
+
     GuaranteedToExecute &= isGuaranteedToTransferExecutionToSuccessor(&I);
   }
 
@@ -2158,6 +2198,10 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
       Instruction *Inst = CB.getInstructionToSimplify();
       if (!Inst)
         continue;
+      if (canStrengthenFlags(Inst)) {
+        Changed |= tryToStrengthenFlags(Inst, Info, ToRemove);
+        continue;
+      }
       LLVM_DEBUG(dbgs() << "Processing condition to simplify: " << *Inst
                         << "\n");
       if (auto *II = dyn_cast<WithOverflowInst>(Inst)) {
diff --git a/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit-postinc.ll b/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit-postinc.ll
index 3d509158c523f..1fa5344c9911d 100644
--- a/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit-postinc.ll
+++ b/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit-postinc.ll
@@ -997,7 +997,7 @@ define i64 @latch_postdec_umin_clamp(ptr %s, i64 %n) {
 ; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 0
 ; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP]]
 ; CHECK:       [[IF_FOUND]]:
-; CHECK-NEXT:    [[IDX:%.*]] = sub i64 [[N]], [[IV]]
+; CHECK-NEXT:    [[IDX:%.*]] = sub nuw i64 [[N]], [[IV]]
 ; CHECK-NEXT:    br label %[[EXIT]]
 ; CHECK:       [[EXIT]]:
 ; CHECK-NEXT:    [[RES:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[N]], %[[LOOP_LATCH]] ], [ [[IDX]], %[[IF_FOUND]] ]
diff --git a/llvm/test/Transforms/ConstraintElimination/materialize-flags-narrow-pointer-index.ll b/llvm/test/Transforms/ConstraintElimination/materialize-flags-narrow-pointer-index.ll
new file mode 100644
index 0000000000000..bcdf22c109743
--- /dev/null
+++ b/llvm/test/Transforms/ConstraintElimination/materialize-flags-narrow-pointer-index.ll
@@ -0,0 +1,208 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
+
+; The offsets of a GEP are computed in the pointer index type. With a 16 bit
+; index type, a stride or struct member offset that does not fit in 15 bits is
+; negative there, so a non-negative index does not imply a non-negative offset
+; and nuw must not be added.
+
+target datalayout = "p:16:16"
+
+%S.big = type { [40000 x i8], i8 }
+%S.small = type { i16, i8 }
+
+; The stride 40000 is negative as an i16, so the offset for a positive index is
+; negative and the GEP may wrap in the unsigned sense.
+define ptr @gep_no_nuw_stride_negative_in_index_type(ptr %p, i16 %i, i16 %j) {
+; CHECK-LABEL: define ptr @gep_no_nuw_stride_negative_in_index_type(
+; CHECK-SAME: ptr [[P:%.*]], i16 [[I:%.*]], i16 [[J:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C_0:%.*]] = icmp sgt i16 [[I]], [[J]]
+; CHECK-NEXT:    br i1 [[C_0]], label %[[BB_1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[BB_1]]:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i16 [[J]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label %[[BB_2:.*]], label %[[EXIT]]
+; CHECK:       [[BB_2]]:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr nusw [40000 x i8], ptr [[P]], i16 [[I]]
+; CHECK-NEXT:    ret ptr [[GEP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  %c.0 = icmp sgt i16 %i, %j
+  br i1 %c.0, label %bb.1, label %exit
+
+bb.1:
+  %c.1 = icmp sgt i16 %j, 0
+  br i1 %c.1, label %bb.2, label %exit
+
+bb.2:
+  %gep = getelementptr nusw [40000 x i8], ptr %p, i16 %i
+  ret ptr %gep
+
+exit:
+  ret ptr null
+}
+
+; Same for the offset of a struct member, which is 40000 for the second field.
+define ptr @gep_no_nuw_struct_offset_negative_in_index_type(ptr %p, i16 %i, i16 %j) {
+; CHECK-LABEL: define ptr @gep_no_nuw_struct_offset_negative_in_index_type(
+; CHECK-SAME: ptr [[P:%.*]], i16 [[I:%.*]], i16 [[J:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C_0:%.*]] = icmp sgt i16 [[I]], [[J]]
+; CHECK-NEXT:    br i1 [[C_0]], label %[[BB_1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[BB_1]]:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i16 [[J]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label %[[BB_2:.*]], label %[[EXIT]]
+; CHECK:       [[BB_2]]:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr nusw [[S_BIG:%.*]], ptr [[P]], i16 [[I]], i32 1
+; CHECK-NEXT:    ret ptr [[GEP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  %c.0 = icmp sgt i16 %i, %j
+  br i1 %c.0, label %bb.1, label %exit
+
+bb.1:
+  %c.1 = icmp sgt i16 %j, 0
+  br i1 %c.1, label %bb.2, label %exit
+
+bb.2:
+  %gep = getelementptr nusw %S.big, ptr %p, i16 %i, i32 1
+  ret ptr %gep
+
+exit:
+  ret ptr null
+}
+
+; The stride of the outer array is 160000, which is 28928 and thus non-negative
+; as an i16, but the stride of the inner array is negative.
+define ptr @gep_no_nuw_inner_stride_negative_in_index_type(ptr %p, i16 %i, i16 %j) {
+; CHECK-LABEL: define ptr @gep_no_nuw_inner_stride_negative_in_index_type(
+; CHECK-SAME: ptr [[P:%.*]], i16 [[I:%.*]], i16 [[J:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C_0:%.*]] = icmp sgt i16 [[I]], [[J]]
+; CHECK-NEXT:    br i1 [[C_0]], label %[[BB_1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[BB_1]]:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i16 [[J]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label %[[BB_2:.*]], label %[[EXIT]]
+; CHECK:       [[BB_2]]:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr nusw [4 x [40000 x i8]], ptr [[P]], i16 [[I]], i16 [[J]]
+; CHECK-NEXT:    ret ptr [[GEP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  %c.0 = icmp sgt i16 %i, %j
+  br i1 %c.0, label %bb.1, label %exit
+
+bb.1:
+  %c.1 = icmp sgt i16 %j, 0
+  br i1 %c.1, label %bb.2, label %exit
+
+bb.2:
+  %gep = getelementptr nusw [4 x [40000 x i8]], ptr %p, i16 %i, i16 %j
+  ret ptr %gep
+
+exit:
+  ret ptr null
+}
+
+; The stride fits in the index type, so nuw can be added.
+define ptr @gep_nuw_stride_fits_index_type(ptr %p, i16 %i, i16 %j) {
+; CHECK-LABEL: define ptr @gep_nuw_stride_fits_index_type(
+; CHECK-SAME: ptr [[P:%.*]], i16 [[I:%.*]], i16 [[J:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C_0:%.*]] = icmp sgt i16 [[I]], [[J]]
+; CHECK-NEXT:    br i1 [[C_0]], label %[[BB_1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[BB_1]]:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i16 [[J]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label %[[BB_2:.*]], label %[[EXIT]]
+; CHECK:       [[BB_2]]:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr nusw i16, ptr [[P]], i16 [[I]]
+; CHECK-NEXT:    ret ptr [[GEP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  %c.0 = icmp sgt i16 %i, %j
+  br i1 %c.0, label %bb.1, label %exit
+
+bb.1:
+  %c.1 = icmp sgt i16 %j, 0
+  br i1 %c.1, label %bb.2, label %exit
+
+bb.2:
+  %gep = getelementptr nusw i16, ptr %p, i16 %i
+  ret ptr %gep
+
+exit:
+  ret ptr null
+}
+
+; The struct member offset fits in the index type, so nuw can be added.
+define ptr @gep_nuw_struct_offset_fits_index_type(ptr %p, i16 %i, i16 %j) {
+; CHECK-LABEL: define ptr @gep_nuw_struct_offset_fits_index_type(
+; CHECK-SAME: ptr [[P:%.*]], i16 [[I:%.*]], i16 [[J:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C_0:%.*]] = icmp sgt i16 [[I]], [[J]]
+; CHECK-NEXT:    br i1 [[C_0]], label %[[BB_1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[BB_1]]:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i16 [[J]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label %[[BB_2:.*]], label %[[EXIT]]
+; CHECK:       [[BB_2]]:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr nusw [[S_SMALL:%.*]], ptr [[P]], i16 [[I]], i32 1
+; CHECK-NEXT:    ret ptr [[GEP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  %c.0 = icmp sgt i16 %i, %j
+  br i1 %c.0, label %bb.1, label %exit
+
+bb.1:
+  %c.1 = icmp sgt i16 %j, 0
+  br i1 %c.1, label %bb.2, label %exit
+
+bb.2:
+  %gep = getelementptr nusw %S.small, ptr %p, i16 %i, i32 1
+  ret ptr %gep
+
+exit:
+  ret ptr null
+}
+
+; An index wider than the index type is truncated. nusw guarantees the
+; truncation preserves the signed value, which together with the index being
+; non-negative means it also preserves the unsigned value.
+define ptr @gep_nuw_index_wider_than_index_type(ptr %p, i64 %i, i64 %j) {
+; CHECK-LABEL: define ptr @gep_nuw_index_wider_than_index_type(
+; CHECK-SAME: ptr [[P:%.*]], i64 [[I:%.*]], i64 [[J:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C_0:%.*]] = icmp sgt i64 [[I]], [[J]]
+; CHECK-NEXT:    br i1 [[C_0]], label %[[BB_1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[BB_1]]:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i64 [[J]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label %[[BB_2:.*]], label %[[EXIT]]
+; CHECK:       [[BB_2]]:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr nusw i16, ptr [[P]], i64 [[I]]
+; CHECK-NEXT:    ret ptr [[GEP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  %c.0 = icmp sgt i64 %i, %j
+  br i1 %c.0, label %bb.1, label %exit
+
+bb.1:
+  %c.1 = icmp sgt i64 %j, 0
+  br i1 %c.1, label %bb.2, label %exit
+
+bb.2:
+  %gep = getelementptr nusw i16, ptr %p, i64 %i
+  ret ptr %gep
+
+exit:
+  ret ptr null
+}
diff --git a/llvm/test/Transforms/ConstraintElimination/materialize-flags.ll b/llvm/test/Transforms/ConstraintElimination/materialize-flags.ll
new file mode 100644
index 0000000000000..d27ff1b5e3068
--- /dev/null
+++ b/llvm/test/Transforms/ConstraintElimination/materialize-flags.ll
@@ -0,0 +1,457 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
+
+define i64 @sext_to_zext_nneg(i32 %n, i32 %m) {
+; CHECK-LABEL: define i64 @sext_to_zext_nneg(
+; CHECK-SAME: i32 [[N:%.*]], i32 [[M:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i32 [[N]], [[M]]
+; CHECK-NEXT:    br i1 [[C]], label %[[EXIT:.*]], label %[[THEN:.*]]
+; CHECK:       [[THEN]]:
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[N]], [[M]]
+; CHECK-NEXT:    [[EXT:%.*]] = sext i32 [[SUB]] to i64
+; CHECK-NEXT:    ret i64 [[EXT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret i64 0
+;
+entry:
+  %c = icmp slt i32 %n, %m
+  br i1 %c, label %exit, label %then
+
+then:
+  %sub = sub nsw i32 %n, %m
+  %ext = sext i32 %sub to i64
+  ret i64 %ext
+
+exit:
+  ret i64 0
+}
+
+define i64 @sext_to_zext_nneg_negated_condition(i32 %n, i32 %m) {
+; CHECK-LABEL: define i64 @sext_to_zext_nneg_negated_condition(
+; CHECK-SAME: i32 [[N:%.*]], i32 [[M:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i32 [[N]], [[M]]
+; CHECK-NEXT:    br i1 [[C]], label %[[THEN:.*]], label %[[EXIT:.*]]
+; CHECK:       [[THEN]]:
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[N]], [[M]]
+; CHECK-NEXT:    [[EXT:%.*]] = sext i32 [[SUB]] to i64
+; CHECK-NEXT:    ret i64 [[EXT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret i64 0
+;
+entry:
+  %c = icmp slt i32 %n, %m
+  br i1 %c, label %then, label %exit
+
+then:
+  %sub = sub nsw i32 %n, %m
+  %ext = sext i32 %sub to i64
+  ret i64 %ext
+
+exit:
+  ret i64 0
+}
+
+define i64 @sext_no_conversion_known_via_value_tracking(i32 %n) {
+; CHECK-LABEL: define i64 @sext_no_conversion_known_via_value_tracking(
+; CHECK-SAME: i32 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[N]], 255
+; CHECK-NEXT:    [[EXT:%.*]] = sext i32 [[AND]] to i64
+; CHECK-NEXT:    ret i64 [[EXT]]
+;
+entry:
+  %and = and i32 %n, 255
+  %ext = sext i32 %and to i64
+  ret i64 %ext
+}
+
+define i32 @sub_nuw_relational(i32 %a, i32 %b) {
+; CHECK-LABEL: define i32 @sub_nuw_relational(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C:%.*]] = icmp uge i32 [[A]], [[B]]
+; CHECK-NEXT:    br i1 [[C]], label %[[THEN:.*]], label %[[EXIT:.*]]
+; CHECK:       [[THEN]]:
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 [[A]], [[B]]
+; CHECK-NEXT:    ret i32 [[SUB]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %c = icmp uge i32 %a, %b
+  br i1 %c, label %then, label %exit
+
+then:
+  %sub = sub i32 %a, %b
+  ret i32 %sub
+
+exit:
+  ret i32 0
+}
+
+define i32 @sub_nuw_transitive(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: define i32 @sub_nuw_transitive(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C_0:%.*]] = icmp uge i32 [[A]], [[B]]
+; CHECK-NEXT:    br i1 [[C_0]], label %[[BB_1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[BB_1]]:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp uge i32 [[B]], [[C]]
+; CHECK-NEXT:    br i1 [[C_1]], label %[[BB_2:.*]], label %[[EXIT]]
+; CHECK:       [[BB_2]]:
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw i32 [[A]], [[C]]
+; CHECK-NEXT:    ret i32 [[SUB]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %c.0 = icmp uge i32 %a, %b
+  br i1 %c.0, label %bb.1, label %exit
+
+bb.1:
+  %c.1 = icmp uge i32 %b, %c
+  br i1 %c.1, label %bb.2, label %exit
+
+bb.2:
+  %sub = sub i32 %a, %c
+  ret i32 %sub
+
+exit:
+  ret i32 0
+}
+
+; A signed fact does not imply the unsigned no-wrap flag.
+define i32 @sub_no_nuw_signed_fact(i32 %a, i32 %b) {
+; CHECK-LABEL: define i32 @sub_no_nuw_signed_fact(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C:%.*]] = icmp sge i32 [[A]], [[B]]
+; CHECK-NEXT:    br i1 [[C]], label %[[THEN:.*]], label %[[EXIT:.*]]
+; CHECK:       [[THEN]]:
+; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[A]], [[B]]
+; CHECK-NEXT:    ret i32 [[SUB]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %c = icmp sge i32 %a, %b
+  br i1 %c, label %then, label %exit
+
+then:
+  %sub = sub i32 %a, %b
+  ret i32 %sub
+
+exit:
+  ret i32 0
+}
+
+define ptr @gep_nuw_transitive(ptr %p, i64 %i, i64 %j) {
+; CHECK-LABEL: define ptr @gep_nuw_transitive(
+; CHECK-SAME: ptr [[P:%.*]], i64 [[I:%.*]], i64 [[J:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C_0:%.*]] = icmp sgt i64 [[I]], [[J]]
+; CHECK-NEXT:    br i1 [[C_0]], label %[[BB_1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[BB_1]]:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i64 [[J]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label %[[BB_2:.*]], label %[[EXIT]]
+; CHECK:       [[BB_2]]:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr nusw i32, ptr [[P]], i64 [[I]]
+; CHECK-NEXT:    ret ptr [[GEP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  %c.0 = icmp sgt i64 %i, %j
+  br i1 %c.0, label %bb.1, label %exit
+
+bb.1:
+  %c.1 = icmp sgt i64 %j, 0
+  br i1 %c.1, label %bb.2, label %exit
+
+bb.2:
+  %gep = getelementptr nusw i32, ptr %p, i64 %i
+  ret ptr %gep
+
+exit:
+  ret ptr null
+}
+
+define ptr @gep_no_nuw_unknown_index(ptr %p, i64 %i, i64 %n) {
+; CHECK-LABEL: define ptr @gep_no_nuw_unknown_index(
+; CHECK-SAME: ptr [[P:%.*]], i64 [[I:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C:%.*]] = icmp sge i64 [[I]], [[N]]
+; CHECK-NEXT:    br i1 [[C]], label %[[EXIT:.*]], label %[[THEN:.*]]
+; CHECK:       [[THEN]]:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr nusw i32, ptr [[P]], i64 [[I]]
+; CHECK-NEXT:    ret ptr [[GEP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  %c = icmp sge i64 %i, %n
+  br i1 %c, label %exit, label %then
+
+then:
+  %gep = getelementptr nusw i32, ptr %p, i64 %i
+  ret ptr %gep
+
+exit:
+  ret ptr null
+}
+
+; The negative constant index means the GEP wraps in the unsigned sense.
+define ptr @gep_no_nuw_negative_constant_index(ptr %p, i64 %i, i64 %j) {
+; CHECK-LABEL: define ptr @gep_no_nuw_negative_constant_index(
+; CHECK-SAME: ptr [[P:%.*]], i64 [[I:%.*]], i64 [[J:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C_0:%.*]] = icmp sgt i64 [[I]], [[J]]
+; CHECK-NEXT:    br i1 [[C_0]], label %[[BB_1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[BB_1]]:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i64 [[J]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label %[[BB_2:.*]], label %[[EXIT]]
+; CHECK:       [[BB_2]]:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr nusw i32, ptr [[P]], i64 [[I]]
+; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr nusw i32, ptr [[GEP]], i64 -1
+; CHECK-NEXT:    ret ptr [[GEP_2]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  %c.0 = icmp sgt i64 %i, %j
+  br i1 %c.0, label %bb.1, label %exit
+
+bb.1:
+  %c.1 = icmp sgt i64 %j, 0
+  br i1 %c.1, label %bb.2, label %exit
+
+bb.2:
+  %gep = getelementptr nusw i32, ptr %p, i64 %i
+  %gep.2 = getelementptr nusw i32, ptr %gep, i64 -1
+  ret ptr %gep.2
+
+exit:
+  ret ptr null
+}
+
+; Without nusw, nuw cannot be implied by non-negative offsets.
+define ptr @gep_no_nusw(ptr %p, i64 %i, i64 %j) {
+; CHECK-LABEL: define ptr @gep_no_nusw(
+; CHECK-SAME: ptr [[P:%.*]], i64 [[I:%.*]], i64 [[J:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[C_0:%.*]] = icmp sgt i64 [[I]], [[J]]
+; CHECK-NEXT:    br i1 [[C_0]], label %[[BB_1:.*]], label %[[EXIT:.*]]
+; CHECK:       [[BB_1]]:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i64 [[J]], 0
+; CHECK-NEXT:    br i1 [[C_1]], label %[[BB_2:.*]], label %[[EXIT]]
+; CHECK:       [[BB_2]]:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[P]], i64 [[I]]
+; CHECK-NEXT:    ret ptr [[GEP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret ptr null
+;
+entry:
+  %c.0 = icmp sgt i64 %i, %j
+  br i1 %c.0, label %bb.1, label %exit
+
+bb.1:
+  %c.1 = icmp sgt i64 %j, 0
+  br i1 %c.1, label %bb.2, label %exit
+
+bb.2:
+  %gep = getelementptr i32, ptr %p, i64 %i
+  ret ptr %gep
+
+exit:
+  ret ptr null
+}
+
+define ptr @gep_no_nuw_constant_index(ptr %p) {
+; CHECK-LABEL: define ptr @gep_no_nuw_constant_index(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [...
[truncated]

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown

✅ With the latest revision this PR passed the C/C++ code formatter.

@fhahn
fhahn force-pushed the ce-strenghten-ce-flags-sub branch from a058888 to 2f684e1 Compare August 25, 2026 13:36
@github-actions

Copy link
Copy Markdown

🐧 Linux x64 Test Results

  • 181231 tests passed
  • 3725 tests skipped
  • 3 tests failed

Failed Tests

(click on a test name to see its output)

Clang

Clang.CodeGen/attr-counted-by-for-pointers.c
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 2
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -cc1 -internal-isystem /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lib/clang/24/include -nostdsysteminc -triple x86_64-unknown-linux-gnu -O2 -DWITH_ATTRS -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-for-pointers.c | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck --check-prefix=SANITIZE-WITH-ATTR /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-for-pointers.c
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -cc1 -internal-isystem /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lib/clang/24/include -nostdsysteminc -triple x86_64-unknown-linux-gnu -O2 -DWITH_ATTRS -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-for-pointers.c
# note: command had no output on stdout or stderr
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck --check-prefix=SANITIZE-WITH-ATTR /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-for-pointers.c
# .---command stderr------------
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-for-pointers.c:265:30: error: SANITIZE-WITH-ATTR-LABEL: expected string not found in input
# | // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -17179869168, 34359738361) i64 @test_bdos_of_element_address(
# |                              ^
# | <stdin>:106:94: note: scanning from here
# | define dso_local range(i64 -17179869184, 17179869177) i64 @test_bdos_of_pointer_through_cast(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 {
# |                                                                                              ^
# | <stdin>:118:1: note: possible intended match here
# | define dso_local range(i64 0, 17179869177) i64 @test_bdos_of_element_address(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 {
# | ^
# | 
# | Input file: <stdin>
# | Check file: /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-for-pointers.c
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |              .
# |              .
# |              .
# |            101:  %1 = select i1 %0, i64 %array_size, i64 0 
# |            102:  ret i64 %1 
# |            103: } 
# |            104:  
# |            105: ; Function Attrs: nounwind 
# |            106: define dso_local range(i64 -17179869184, 17179869177) i64 @test_bdos_of_pointer_through_cast(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 { 
# | label:265'0                                                                                                 {                                                              search range start (exclusive)
# | label:265'1                                                                                                                                                                error: no match found in search range
# |            107: entry: 
# |            108:  %counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 16 
# |            109:  %counted_by.load = load i32, ptr %counted_by.gep, align 4 
# |            110:  %count = sext i32 %counted_by.load to i64 
# |            111:  %array_size = shl nsw i64 %count, 3 
# |            112:  %0 = icmp sgt i32 %counted_by.load, -1 
# |            113:  %1 = select i1 %0, i64 %array_size, i64 0 
# |            114:  ret i64 %1 
# |            115: } 
# |            116:  
# |            117: ; Function Attrs: nounwind 
# |            118: define dso_local range(i64 0, 17179869177) i64 @test_bdos_of_element_address(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 { 
# | label:265'2     ?                                                                                                                                          possible intended match
# |            119: entry: 
# |            120:  %.counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 16 
# |            121:  %.counted_by.load = load i32, ptr %.counted_by.gep, align 4 
# |            122:  %0 = icmp ule i32 %index, %.counted_by.load, !nosanitize !6 
# |            123:  %1 = icmp sgt i32 %.counted_by.load, 0, !nosanitize !6 
# |              .
# |              .
# |              .
# |            254: !13 = !{!"any pointer", !4, i64 0} 
# |            255: !14 = !{!15, !15, i64 0} 
# |            256: !15 = !{!"p1 _ZTS3foo", !13, i64 0} 
# |            257: !16 = !{!17, !18, i64 0} 
# |            258: !17 = !{!"annotated_volatile_ptr", !18, i64 0, !3, i64 8} 
# |            259: !18 = !{!"p1 int", !13, i64 0} 
# | label:265'3                                    } search range end (exclusive)
# | >>>>>>
# `-----------------------------
# error: command failed with exit status: 1

--

Clang.CodeGen/attr-counted-by-with-sanitizers.c
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 2
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -cc1 -internal-isystem /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lib/clang/24/include -nostdsysteminc -triple x86_64-unknown-linux-gnu -DCOUNTED_BY -O2 -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -emit-llvm -o - /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck --check-prefix=SANITIZE-WITH-ATTR /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -cc1 -internal-isystem /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lib/clang/24/include -nostdsysteminc -triple x86_64-unknown-linux-gnu -DCOUNTED_BY -O2 -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -emit-llvm -o - /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c
# .---command stderr------------
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c:1591:41: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                         ^
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c:1591:48: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                ^
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c:1591:55: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                       ^
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c:1591:58: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                          ^
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c:1591:65: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                                 ^~
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c:1591:61: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                             ^
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c:1591:51: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                   ^
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c:1591:44: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                            ^
# | 8 warnings generated.
# `-----------------------------
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck --check-prefix=SANITIZE-WITH-ATTR /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c
# .---command stderr------------
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c:306:30: error: SANITIZE-WITH-ATTR-LABEL: expected string not found in input
# | // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -8589934584, 17179869181) i64 @test_return_bdos_of_pointer_into_fam(
# |                              ^
# | <stdin>:194:61: note: scanning from here
# | define dso_local void @test_assign_size_of_pointer_into_fam(ptr noundef %p, i32 noundef %index, i32 noundef %fam_idx) local_unnamed_addr #0 {
# |                                                             ^
# | <stdin>:271:1: note: possible intended match here
# | define dso_local range(i64 0, 8589934589) i64 @test_return_bdos_of_pointer_into_fam(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 {
# | ^
# | 
# | Input file: <stdin>
# | Check file: /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-counted-by-with-sanitizers.c
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |              .
# |              .
# |              .
# |            189: entry: 
# |            190:  ret i64 -1 
# |            191: } 
# |            192:  
# |            193: ; Function Attrs: nounwind 
# |            194: define dso_local void @test_assign_size_of_pointer_into_fam(ptr noundef %p, i32 noundef %index, i32 noundef %fam_idx) local_unnamed_addr #0 { 
# | label:306'0                                                                {                                                                                    search range start (exclusive)
# | label:306'1                                                                                                                                                     error: no match found in search range
# |            195: entry: 
# |            196:  %array = getelementptr inbounds nuw i8, ptr %p, i64 12 
# |            197:  %.counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 8 
# |            198:  %.counted_by.load = load i32, ptr %.counted_by.gep, align 4 
# |            199:  %0 = icmp sgt i32 %.counted_by.load, 2 
# |              .
# |              .
# |              .
# |            266:  store i32 %8, ptr %arrayidx65, align 4, !tbaa !8 
# |            267:  ret void 
# |            268: } 
# |            269:  
# |            270: ; Function Attrs: nounwind 
# |            271: define dso_local range(i64 0, 8589934589) i64 @test_return_bdos_of_pointer_into_fam(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 { 
# | label:306'2     ?                                                                                                                                                 possible intended match
# |            272: entry: 
# |            273:  %.counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 8 
# |            274:  %.counted_by.load = load i32, ptr %.counted_by.gep, align 4 
# |            275:  %0 = icmp ule i32 %index, %.counted_by.load, !nosanitize !6 
# |            276:  %1 = icmp sgt i32 %.counted_by.load, 0, !nosanitize !6 
# |              .
# |              .
# |              .
# |           1070: !24 = !{!25, !25, i64 0} 
# |           1071: !25 = !{!"p1 _ZTS9annotated", !15, i64 0} 
# |           1072: !26 = !{!27, !27, i64 0} 
# |           1073: !27 = !{!"long", !4, i64 0} 
# |           1074: !28 = !{!29, !29, i64 0} 
# |           1075: !29 = !{!"p1 _ZTS3baz", !15, i64 0} 
# | label:306'3                                         } search range end (exclusive)
# | >>>>>>
# `-----------------------------
# error: command failed with exit status: 1

--

Clang.CodeGen/attr-sized-by-for-pointers.c
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 2
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -cc1 -internal-isystem /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lib/clang/24/include -nostdsysteminc -triple x86_64-unknown-linux-gnu -O2 -DWITH_ATTRS -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-sized-by-for-pointers.c | /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck --check-prefix=SANITIZE-WITH-ATTR /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-sized-by-for-pointers.c
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -cc1 -internal-isystem /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lib/clang/24/include -nostdsysteminc -triple x86_64-unknown-linux-gnu -O2 -DWITH_ATTRS -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-sized-by-for-pointers.c
# note: command had no output on stdout or stderr
# executed command: /home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/FileCheck --check-prefix=SANITIZE-WITH-ATTR /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-sized-by-for-pointers.c
# .---command stderr------------
# | /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-sized-by-for-pointers.c:61:30: error: SANITIZE-WITH-ATTR-LABEL: expected string not found in input
# | // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -2147483646, 4294967296) i64 @test_bdos_of_element_address(
# |                              ^
# | <stdin>:21:69: note: scanning from here
# | define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer(ptr noundef %p) local_unnamed_addr #0 {
# |                                                                     ^
# | <stdin>:31:1: note: possible intended match here
# | define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_element_address(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 {
# | ^
# | 
# | Input file: <stdin>
# | Check file: /home/gha/actions-runner/_work/llvm-project/llvm-project/clang/test/CodeGen/attr-sized-by-for-pointers.c
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |             .
# |             .
# |             .
# |            16: @9 = private unnamed_addr global { { ptr, i32, i32 }, ptr, ptr } { { ptr, i32, i32 } { ptr @.src, i32 469, i32 32 }, ptr @7, ptr @1 } 
# |            17: @10 = private unnamed_addr constant { i16, i16, [17 x i8] } { i16 -1, i16 0, [17 x i8] c"'unsigned int *'\00" } 
# |            18: @11 = private unnamed_addr global { { ptr, i32, i32 }, ptr, ptr } { { ptr, i32, i32 } { ptr @.src, i32 521, i32 10 }, ptr @10, ptr @1 } 
# |            19:  
# |            20: ; Function Attrs: nounwind 
# |            21: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer(ptr noundef %p) local_unnamed_addr #0 { 
# | label:61'0                                                                        {                                          search range start (exclusive)
# | label:61'1                                                                                                                   error: no match found in search range
# |            22: entry: 
# |            23:  %counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 16 
# |            24:  %counted_by.load = load i32, ptr %counted_by.gep, align 4 
# |            25:  %narrow = tail call i32 @llvm.smax.i32(i32 %counted_by.load, i32 0) 
# |            26:  %0 = zext nneg i32 %narrow to i64 
# |            27:  ret i64 %0 
# |            28: } 
# |            29:  
# |            30: ; Function Attrs: nounwind 
# |            31: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_element_address(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 { 
# | label:61'2     ?                                                                                                                                         possible intended match
# |            32: entry: 
# |            33:  %.counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 16 
# |            34:  %.counted_by.load = load i32, ptr %.counted_by.gep, align 4 
# |            35:  %0 = icmp ule i32 %index, %.counted_by.load, !nosanitize !6 
# |            36:  %1 = icmp sgt i32 %.counted_by.load, 0, !nosanitize !6 
# |             .
# |             .
# |             .
# |           232: !6 = !{} 
# |           233: !7 = !{!"branch_weights", i32 1048575, i32 1} 
# |           234: !8 = !{!9, !10, i64 0} 
# |           235: !9 = !{!"annotated_volatile_ptr", !10, i64 0, !3, i64 8} 
# |           236: !10 = !{!"p1 int", !11, i64 0} 
# |           237: !11 = !{!"any pointer", !4, i64 0} 
# | label:61'3                                        } search range end (exclusive)
# | >>>>>>
# `-----------------------------
# error: command failed with exit status: 1

--

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

@github-actions

Copy link
Copy Markdown

🪟 Windows x64 Test Results

  • 140352 tests passed
  • 3711 tests skipped
  • 3 tests failed

Failed Tests

(click on a test name to see its output)

Clang

Clang.CodeGen/attr-counted-by-for-pointers.c
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 2
c:\_work\llvm-project\llvm-project\build\bin\clang.exe -cc1 -internal-isystem C:\_work\llvm-project\llvm-project\build\lib\clang\24\include -nostdsysteminc -triple x86_64-unknown-linux-gnu -O2 -DWITH_ATTRS -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-for-pointers.c | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe --check-prefix=SANITIZE-WITH-ATTR C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-for-pointers.c
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\clang.exe' -cc1 -internal-isystem 'C:\_work\llvm-project\llvm-project\build\lib\clang\24\include' -nostdsysteminc -triple x86_64-unknown-linux-gnu -O2 -DWITH_ATTRS -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - 'C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-for-pointers.c'
# note: command had no output on stdout or stderr
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' --check-prefix=SANITIZE-WITH-ATTR 'C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-for-pointers.c'
# .---command stderr------------
# | C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-for-pointers.c:265:30: error: SANITIZE-WITH-ATTR-LABEL: expected string not found in input
# | // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -17179869168, 34359738361) i64 @test_bdos_of_element_address(
# |                              ^
# | <stdin>:106:94: note: scanning from here
# | define dso_local range(i64 -17179869184, 17179869177) i64 @test_bdos_of_pointer_through_cast(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 {
# |                                                                                              ^
# | <stdin>:118:1: note: possible intended match here
# | define dso_local range(i64 0, 17179869177) i64 @test_bdos_of_element_address(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 {
# | ^
# | 
# | Input file: <stdin>
# | Check file: C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-for-pointers.c
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |              .
# |              .
# |              .
# |            101:  %1 = select i1 %0, i64 %array_size, i64 0 
# |            102:  ret i64 %1 
# |            103: } 
# |            104:  
# |            105: ; Function Attrs: nounwind 
# |            106: define dso_local range(i64 -17179869184, 17179869177) i64 @test_bdos_of_pointer_through_cast(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 { 
# | label:265'0                                                                                                 {                                                              search range start (exclusive)
# | label:265'1                                                                                                                                                                error: no match found in search range
# |            107: entry: 
# |            108:  %counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 16 
# |            109:  %counted_by.load = load i32, ptr %counted_by.gep, align 4 
# |            110:  %count = sext i32 %counted_by.load to i64 
# |            111:  %array_size = shl nsw i64 %count, 3 
# |            112:  %0 = icmp sgt i32 %counted_by.load, -1 
# |            113:  %1 = select i1 %0, i64 %array_size, i64 0 
# |            114:  ret i64 %1 
# |            115: } 
# |            116:  
# |            117: ; Function Attrs: nounwind 
# |            118: define dso_local range(i64 0, 17179869177) i64 @test_bdos_of_element_address(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 { 
# | label:265'2     ?                                                                                                                                          possible intended match
# |            119: entry: 
# |            120:  %.counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 16 
# |            121:  %.counted_by.load = load i32, ptr %.counted_by.gep, align 4 
# |            122:  %0 = icmp ule i32 %index, %.counted_by.load, !nosanitize !6 
# |            123:  %1 = icmp sgt i32 %.counted_by.load, 0, !nosanitize !6 
# |              .
# |              .
# |              .
# |            254: !13 = !{!"any pointer", !4, i64 0} 
# |            255: !14 = !{!15, !15, i64 0} 
# |            256: !15 = !{!"p1 _ZTS3foo", !13, i64 0} 
# |            257: !16 = !{!17, !18, i64 0} 
# |            258: !17 = !{!"annotated_volatile_ptr", !18, i64 0, !3, i64 8} 
# |            259: !18 = !{!"p1 int", !13, i64 0} 
# | label:265'3                                    } search range end (exclusive)
# | >>>>>>
# `-----------------------------
# error: command failed with exit status: 1

--

Clang.CodeGen/attr-counted-by-with-sanitizers.c
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 2
c:\_work\llvm-project\llvm-project\build\bin\clang.exe -cc1 -internal-isystem C:\_work\llvm-project\llvm-project\build\lib\clang\24\include -nostdsysteminc -triple x86_64-unknown-linux-gnu -DCOUNTED_BY -O2 -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -emit-llvm -o - C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe --check-prefix=SANITIZE-WITH-ATTR C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\clang.exe' -cc1 -internal-isystem 'C:\_work\llvm-project\llvm-project\build\lib\clang\24\include' -nostdsysteminc -triple x86_64-unknown-linux-gnu -DCOUNTED_BY -O2 -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -emit-llvm -o - 'C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c'
# .---command stderr------------
# | C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c:1591:41: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                         ^
# | C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c:1591:48: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                ^
# | C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c:1591:55: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                       ^
# | C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c:1591:58: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                          ^
# | C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c:1591:65: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                                 ^~
# | C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c:1591:61: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                             ^
# | C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c:1591:51: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                                   ^
# | C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c:1591:44: warning: left operand of comma operator has no effect [-Wunused-value]
# |  1591 |   return __builtin_dynamic_object_size((1, 2, (4, 5, (7, 8, 9, (10, ptr->array)))), 1);
# |       |                                            ^
# | 8 warnings generated.
# `-----------------------------
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' --check-prefix=SANITIZE-WITH-ATTR 'C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c'
# .---command stderr------------
# | C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c:306:30: error: SANITIZE-WITH-ATTR-LABEL: expected string not found in input
# | // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -8589934584, 17179869181) i64 @test_return_bdos_of_pointer_into_fam(
# |                              ^
# | <stdin>:194:61: note: scanning from here
# | define dso_local void @test_assign_size_of_pointer_into_fam(ptr noundef %p, i32 noundef %index, i32 noundef %fam_idx) local_unnamed_addr #0 {
# |                                                             ^
# | <stdin>:271:1: note: possible intended match here
# | define dso_local range(i64 0, 8589934589) i64 @test_return_bdos_of_pointer_into_fam(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 {
# | ^
# | 
# | Input file: <stdin>
# | Check file: C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-counted-by-with-sanitizers.c
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |              .
# |              .
# |              .
# |            189: entry: 
# |            190:  ret i64 -1 
# |            191: } 
# |            192:  
# |            193: ; Function Attrs: nounwind 
# |            194: define dso_local void @test_assign_size_of_pointer_into_fam(ptr noundef %p, i32 noundef %index, i32 noundef %fam_idx) local_unnamed_addr #0 { 
# | label:306'0                                                                {                                                                                    search range start (exclusive)
# | label:306'1                                                                                                                                                     error: no match found in search range
# |            195: entry: 
# |            196:  %array = getelementptr inbounds nuw i8, ptr %p, i64 12 
# |            197:  %.counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 8 
# |            198:  %.counted_by.load = load i32, ptr %.counted_by.gep, align 4 
# |            199:  %0 = icmp sgt i32 %.counted_by.load, 2 
# |              .
# |              .
# |              .
# |            266:  store i32 %8, ptr %arrayidx65, align 4, !tbaa !8 
# |            267:  ret void 
# |            268: } 
# |            269:  
# |            270: ; Function Attrs: nounwind 
# |            271: define dso_local range(i64 0, 8589934589) i64 @test_return_bdos_of_pointer_into_fam(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 { 
# | label:306'2     ?                                                                                                                                                 possible intended match
# |            272: entry: 
# |            273:  %.counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 8 
# |            274:  %.counted_by.load = load i32, ptr %.counted_by.gep, align 4 
# |            275:  %0 = icmp ule i32 %index, %.counted_by.load, !nosanitize !6 
# |            276:  %1 = icmp sgt i32 %.counted_by.load, 0, !nosanitize !6 
# |              .
# |              .
# |              .
# |           1070: !24 = !{!25, !25, i64 0} 
# |           1071: !25 = !{!"p1 _ZTS9annotated", !15, i64 0} 
# |           1072: !26 = !{!27, !27, i64 0} 
# |           1073: !27 = !{!"long", !4, i64 0} 
# |           1074: !28 = !{!29, !29, i64 0} 
# |           1075: !29 = !{!"p1 _ZTS3baz", !15, i64 0} 
# | label:306'3                                         } search range end (exclusive)
# | >>>>>>
# `-----------------------------
# error: command failed with exit status: 1

--

Clang.CodeGen/attr-sized-by-for-pointers.c
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 2
c:\_work\llvm-project\llvm-project\build\bin\clang.exe -cc1 -internal-isystem C:\_work\llvm-project\llvm-project\build\lib\clang\24\include -nostdsysteminc -triple x86_64-unknown-linux-gnu -O2 -DWITH_ATTRS -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-sized-by-for-pointers.c | c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe --check-prefix=SANITIZE-WITH-ATTR C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-sized-by-for-pointers.c
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\clang.exe' -cc1 -internal-isystem 'C:\_work\llvm-project\llvm-project\build\lib\clang\24\include' -nostdsysteminc -triple x86_64-unknown-linux-gnu -O2 -DWITH_ATTRS -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -fexperimental-late-parse-attributes -emit-llvm -o - 'C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-sized-by-for-pointers.c'
# note: command had no output on stdout or stderr
# executed command: 'c:\_work\llvm-project\llvm-project\build\bin\filecheck.exe' --check-prefix=SANITIZE-WITH-ATTR 'C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-sized-by-for-pointers.c'
# .---command stderr------------
# | C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-sized-by-for-pointers.c:61:30: error: SANITIZE-WITH-ATTR-LABEL: expected string not found in input
# | // SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -2147483646, 4294967296) i64 @test_bdos_of_element_address(
# |                              ^
# | <stdin>:21:69: note: scanning from here
# | define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer(ptr noundef %p) local_unnamed_addr #0 {
# |                                                                     ^
# | <stdin>:31:1: note: possible intended match here
# | define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_element_address(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 {
# | ^
# | 
# | Input file: <stdin>
# | Check file: C:\_work\llvm-project\llvm-project\clang\test\CodeGen\attr-sized-by-for-pointers.c
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |             .
# |             .
# |             .
# |            16: @9 = private unnamed_addr global { { ptr, i32, i32 }, ptr, ptr } { { ptr, i32, i32 } { ptr @.src, i32 469, i32 32 }, ptr @7, ptr @1 } 
# |            17: @10 = private unnamed_addr constant { i16, i16, [17 x i8] } { i16 -1, i16 0, [17 x i8] c"'unsigned int *'\00" } 
# |            18: @11 = private unnamed_addr global { { ptr, i32, i32 }, ptr, ptr } { { ptr, i32, i32 } { ptr @.src, i32 521, i32 10 }, ptr @10, ptr @1 } 
# |            19:  
# |            20: ; Function Attrs: nounwind 
# |            21: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_pointer(ptr noundef %p) local_unnamed_addr #0 { 
# | label:61'0                                                                        {                                          search range start (exclusive)
# | label:61'1                                                                                                                   error: no match found in search range
# |            22: entry: 
# |            23:  %counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 16 
# |            24:  %counted_by.load = load i32, ptr %counted_by.gep, align 4 
# |            25:  %narrow = tail call i32 @llvm.smax.i32(i32 %counted_by.load, i32 0) 
# |            26:  %0 = zext nneg i32 %narrow to i64 
# |            27:  ret i64 %0 
# |            28: } 
# |            29:  
# |            30: ; Function Attrs: nounwind 
# |            31: define dso_local range(i64 0, 2147483648) i64 @test_bdos_of_element_address(ptr noundef %p, i32 noundef %index) local_unnamed_addr #0 { 
# | label:61'2     ?                                                                                                                                         possible intended match
# |            32: entry: 
# |            33:  %.counted_by.gep = getelementptr inbounds nuw i8, ptr %p, i64 16 
# |            34:  %.counted_by.load = load i32, ptr %.counted_by.gep, align 4 
# |            35:  %0 = icmp ule i32 %index, %.counted_by.load, !nosanitize !6 
# |            36:  %1 = icmp sgt i32 %.counted_by.load, 0, !nosanitize !6 
# |             .
# |             .
# |             .
# |           232: !6 = !{} 
# |           233: !7 = !{!"branch_weights", i32 1048575, i32 1} 
# |           234: !8 = !{!9, !10, i64 0} 
# |           235: !9 = !{!"annotated_volatile_ptr", !10, i64 0, !3, i64 8} 
# |           236: !10 = !{!"p1 int", !11, i64 0} 
# |           237: !11 = !{!"any pointer", !4, i64 0} 
# | label:61'3                                        } search range end (exclusive)
# | >>>>>>
# `-----------------------------
# error: command failed with exit status: 1

--

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

@nikic nikic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this have compile-time impact?

switch (I->getOpcode()) {
case Instruction::Sub:
// A - B does not wrap unsigned, if A >=u B. Constant operands are handled
// by CorrelatedValuePropagation using ranges.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sub specifically, a constant on the RHS will get canonicalized to add anyway.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this phase ordering test is not affected by the patch. Is that intended?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants