Skip to content

SimplifyIndVar: teach widenLoopCompare about samesign #125851

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 6, 2025

Conversation

artagnon
Copy link
Contributor

@artagnon artagnon commented Feb 5, 2025

@artagnon
Copy link
Contributor Author

artagnon commented Feb 5, 2025

Duplicate of #125764, since GitHub seems to have hung on that PR.

@llvmbot
Copy link
Member

llvmbot commented Feb 5, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Ramkumar Ramachandra (artagnon)

Changes

Proof: https://alive2.llvm.org/ce/z/NVXaeo


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

3 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/SimplifyIndVar.cpp (+3-2)
  • (added) llvm/test/Transforms/IndVarSimplify/iv-ext-samesign.ll (+716)
  • (removed) llvm/test/Transforms/IndVarSimplify/iv-zext-samesign-datalayout.ll (-62)
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index e41a1adadfcc5bd..7b9c5c77cbe986e 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -1614,7 +1614,8 @@ bool WidenIV::widenLoopCompare(WidenIV::NarrowIVDefUse DU) {
   //      (A) == icmp slt i32 sext(%narrow), sext(%val)
   //          == icmp slt i32 zext(%narrow), sext(%val)
   bool IsSigned = getExtendKind(DU.NarrowDef) == ExtendKind::Sign;
-  if (!(DU.NeverNegative || IsSigned == Cmp->isSigned()))
+  bool CmpPreferredSign = Cmp->hasSameSign() ? IsSigned : Cmp->isSigned();
+  if (!DU.NeverNegative && IsSigned != CmpPreferredSign)
     return false;
 
   Value *Op = Cmp->getOperand(Cmp->getOperand(0) == DU.NarrowDef ? 1 : 0);
@@ -1627,7 +1628,7 @@ bool WidenIV::widenLoopCompare(WidenIV::NarrowIVDefUse DU) {
 
   // Widen the other operand of the compare, if necessary.
   if (CastWidth < IVWidth) {
-    Value *ExtOp = createExtendInst(Op, WideType, Cmp->isSigned(), Cmp);
+    Value *ExtOp = createExtendInst(Op, WideType, CmpPreferredSign, Cmp);
     DU.NarrowUse->replaceUsesOfWith(Op, ExtOp);
   }
   return true;
diff --git a/llvm/test/Transforms/IndVarSimplify/iv-ext-samesign.ll b/llvm/test/Transforms/IndVarSimplify/iv-ext-samesign.ll
new file mode 100644
index 000000000000000..1207f47c5e3c90c
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/iv-ext-samesign.ll
@@ -0,0 +1,716 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=indvars -S | FileCheck %s
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+
+define i32 @iv_zext_zext_sgt_slt(i32 %iter.count, ptr %ptr) {
+; CHECK-LABEL: define i32 @iv_zext_zext_sgt_slt(
+; CHECK-SAME: i32 [[ITER_COUNT:%.*]], ptr [[PTR:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[ITER_COUNT]], -1
+; CHECK-NEXT:    br label %[[OUTER_LOOP:.*]]
+; CHECK:       [[PH_LOOPEXIT:.*]]:
+; CHECK-NEXT:    br label %[[PH:.*]]
+; CHECK:       [[PH]]:
+; CHECK-NEXT:    [[INDVARS_IV_NEXT2:%.*]] = add i32 [[INDVARS_IV1:%.*]], -1
+; CHECK-NEXT:    br label %[[OUTER_LOOP]]
+; CHECK:       [[OUTER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV1]] = phi i32 [ [[INDVARS_IV_NEXT2]], %[[PH]] ], [ [[TMP0]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[IV_OUTER:%.*]] = phi i32 [ [[IV_OUTER_1:%.*]], %[[PH]] ], [ [[ITER_COUNT]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[IV_OUTER_1]] = add nsw i32 [[IV_OUTER]], -1
+; CHECK-NEXT:    [[EXT_OUTER:%.*]] = zext nneg i32 [[IV_OUTER_1]] to i64
+; CHECK-NEXT:    [[GEP_OUTER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[EXT_OUTER]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_OUTER]], align 1
+; CHECK-NEXT:    [[EXIT_COND_OUTER:%.*]] = icmp sgt i32 [[IV_OUTER]], 1
+; CHECK-NEXT:    br i1 [[EXIT_COND_OUTER]], label %[[INNER_LOOP_PREHEADER:.*]], label %[[PH]]
+; CHECK:       [[INNER_LOOP_PREHEADER]]:
+; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[INDVARS_IV1]] to i64
+; CHECK-NEXT:    br label %[[INNER_LOOP:.*]]
+; CHECK:       [[INNER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, %[[INNER_LOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], %[[INNER_LOOP]] ]
+; CHECK-NEXT:    [[GEP_INNER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_INNER]], align 1
+; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[INNER_LOOP]], label %[[PH_LOOPEXIT]]
+; CHECK:       [[EXIT:.*:]]
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  br label %outer.loop
+
+ph:
+  br label %outer.loop
+
+outer.loop:
+  %iv.outer = phi i32 [ %iv.outer.1, %ph ], [ %iter.count, %entry ]
+  %iv.outer.1 = add nsw i32 %iv.outer, -1
+  %ext.outer = zext nneg i32 %iv.outer.1 to i64
+  %gep.outer = getelementptr i8, ptr %ptr, i64 %ext.outer
+  store i8 0, ptr %gep.outer
+  %exit.cond.outer = icmp sgt i32 %iv.outer, 1
+  br i1 %exit.cond.outer, label %inner.loop, label %ph
+
+inner.loop:
+  %iv.inner = phi i32 [ %iv.next, %inner.loop ], [ 0, %outer.loop ]
+  %ext.inner = zext nneg i32 %iv.inner to i64
+  %gep.inner = getelementptr i8, ptr %ptr, i64 %ext.inner
+  store i8 0, ptr %gep.inner
+  %iv.next = add nuw nsw i32 %iv.inner, 1
+  %exit.cond.inner = icmp slt i32 %iv.next, %iv.outer.1
+  br i1 %exit.cond.inner, label %inner.loop, label %ph
+
+exit:
+  ret i32 0
+}
+
+define i32 @iv_zext_zext_gt_slt(i32 %iter.count, ptr %ptr) {
+; CHECK-LABEL: define i32 @iv_zext_zext_gt_slt(
+; CHECK-SAME: i32 [[ITER_COUNT:%.*]], ptr [[PTR:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[ITER_COUNT]] to i64
+; CHECK-NEXT:    br label %[[OUTER_LOOP:.*]]
+; CHECK:       [[PH_LOOPEXIT:.*]]:
+; CHECK-NEXT:    br label %[[PH:.*]]
+; CHECK:       [[PH]]:
+; CHECK-NEXT:    br label %[[OUTER_LOOP]]
+; CHECK:       [[OUTER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV1:%.*]] = phi i64 [ [[INDVARS_IV_NEXT2:%.*]], %[[PH]] ], [ [[TMP0]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[INDVARS_IV_NEXT2]] = add nsw i64 [[INDVARS_IV1]], -1
+; CHECK-NEXT:    [[GEP_OUTER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[INDVARS_IV_NEXT2]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_OUTER]], align 1
+; CHECK-NEXT:    [[EXIT_COND_OUTER:%.*]] = icmp samesign ugt i64 [[INDVARS_IV1]], 1
+; CHECK-NEXT:    br i1 [[EXIT_COND_OUTER]], label %[[INNER_LOOP_PREHEADER:.*]], label %[[PH]]
+; CHECK:       [[INNER_LOOP_PREHEADER]]:
+; CHECK-NEXT:    br label %[[INNER_LOOP:.*]]
+; CHECK:       [[INNER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, %[[INNER_LOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], %[[INNER_LOOP]] ]
+; CHECK-NEXT:    [[GEP_INNER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_INNER]], align 1
+; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[EXIT_COND_INNER:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[INDVARS_IV_NEXT2]]
+; CHECK-NEXT:    br i1 [[EXIT_COND_INNER]], label %[[INNER_LOOP]], label %[[PH_LOOPEXIT]]
+; CHECK:       [[EXIT:.*:]]
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  br label %outer.loop
+
+ph:
+  br label %outer.loop
+
+outer.loop:
+  %iv.outer = phi i32 [ %iv.outer.1, %ph ], [ %iter.count, %entry ]
+  %iv.outer.1 = add nsw i32 %iv.outer, -1
+  %ext.outer = zext nneg i32 %iv.outer.1 to i64
+  %gep.outer = getelementptr i8, ptr %ptr, i64 %ext.outer
+  store i8 0, ptr %gep.outer
+  %exit.cond.outer = icmp samesign ugt i32 %iv.outer, 1
+  br i1 %exit.cond.outer, label %inner.loop, label %ph
+
+inner.loop:
+  %iv.inner = phi i32 [ %iv.next, %inner.loop ], [ 0, %outer.loop ]
+  %ext.inner = zext nneg i32 %iv.inner to i64
+  %gep.inner = getelementptr i8, ptr %ptr, i64 %ext.inner
+  store i8 0, ptr %gep.inner
+  %iv.next = add nuw nsw i32 %iv.inner, 1
+  %exit.cond.inner = icmp slt i32 %iv.next, %iv.outer.1
+  br i1 %exit.cond.inner, label %inner.loop, label %ph
+
+exit:
+  ret i32 0
+}
+
+define i32 @iv_zext_zext_gt_slt_exitlimit(i32 %iter.count, i32 %exit.limit, ptr %ptr) {
+; CHECK-LABEL: define i32 @iv_zext_zext_gt_slt_exitlimit(
+; CHECK-SAME: i32 [[ITER_COUNT:%.*]], i32 [[EXIT_LIMIT:%.*]], ptr [[PTR:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[ITER_COUNT]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[EXIT_LIMIT]] to i64
+; CHECK-NEXT:    br label %[[OUTER_LOOP:.*]]
+; CHECK:       [[PH_LOOPEXIT:.*]]:
+; CHECK-NEXT:    br label %[[PH:.*]]
+; CHECK:       [[PH]]:
+; CHECK-NEXT:    br label %[[OUTER_LOOP]]
+; CHECK:       [[OUTER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV1:%.*]] = phi i64 [ [[INDVARS_IV_NEXT2:%.*]], %[[PH]] ], [ [[TMP0]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[INDVARS_IV_NEXT2]] = add nsw i64 [[INDVARS_IV1]], -1
+; CHECK-NEXT:    [[GEP_OUTER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[INDVARS_IV_NEXT2]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_OUTER]], align 1
+; CHECK-NEXT:    [[EXIT_COND_OUTER:%.*]] = icmp samesign ugt i64 [[INDVARS_IV1]], [[TMP1]]
+; CHECK-NEXT:    br i1 [[EXIT_COND_OUTER]], label %[[INNER_LOOP_PREHEADER:.*]], label %[[PH]]
+; CHECK:       [[INNER_LOOP_PREHEADER]]:
+; CHECK-NEXT:    br label %[[INNER_LOOP:.*]]
+; CHECK:       [[INNER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, %[[INNER_LOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], %[[INNER_LOOP]] ]
+; CHECK-NEXT:    [[GEP_INNER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_INNER]], align 1
+; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[EXIT_COND_INNER:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[INDVARS_IV_NEXT2]]
+; CHECK-NEXT:    br i1 [[EXIT_COND_INNER]], label %[[INNER_LOOP]], label %[[PH_LOOPEXIT]]
+; CHECK:       [[EXIT:.*:]]
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  br label %outer.loop
+
+ph:
+  br label %outer.loop
+
+outer.loop:
+  %iv.outer = phi i32 [ %iv.outer.1, %ph ], [ %iter.count, %entry ]
+  %iv.outer.1 = add nsw i32 %iv.outer, -1
+  %ext.outer = zext nneg i32 %iv.outer.1 to i64
+  %gep.outer = getelementptr i8, ptr %ptr, i64 %ext.outer
+  store i8 0, ptr %gep.outer
+  %exit.cond.outer = icmp samesign ugt i32 %iv.outer, %exit.limit
+  br i1 %exit.cond.outer, label %inner.loop, label %ph
+
+inner.loop:
+  %iv.inner = phi i32 [ %iv.next, %inner.loop ], [ 0, %outer.loop ]
+  %ext.inner = zext nneg i32 %iv.inner to i64
+  %gep.inner = getelementptr i8, ptr %ptr, i64 %ext.inner
+  store i8 0, ptr %gep.inner
+  %iv.next = add nuw nsw i32 %iv.inner, 1
+  %exit.cond.inner = icmp slt i32 %iv.next, %iv.outer.1
+  br i1 %exit.cond.inner, label %inner.loop, label %ph
+
+exit:
+  ret i32 0
+}
+
+define i32 @iv_zext_zext_sgt_lt(i32 %iter.count, ptr %ptr) {
+; CHECK-LABEL: define i32 @iv_zext_zext_sgt_lt(
+; CHECK-SAME: i32 [[ITER_COUNT:%.*]], ptr [[PTR:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[ITER_COUNT]], -1
+; CHECK-NEXT:    br label %[[OUTER_LOOP:.*]]
+; CHECK:       [[PH_LOOPEXIT:.*]]:
+; CHECK-NEXT:    br label %[[PH:.*]]
+; CHECK:       [[PH]]:
+; CHECK-NEXT:    [[INDVARS_IV_NEXT2:%.*]] = add i32 [[INDVARS_IV1:%.*]], -1
+; CHECK-NEXT:    br label %[[OUTER_LOOP]]
+; CHECK:       [[OUTER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV1]] = phi i32 [ [[INDVARS_IV_NEXT2]], %[[PH]] ], [ [[TMP0]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[IV_OUTER:%.*]] = phi i32 [ [[IV_OUTER_1:%.*]], %[[PH]] ], [ [[ITER_COUNT]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[IV_OUTER_1]] = add nsw i32 [[IV_OUTER]], -1
+; CHECK-NEXT:    [[EXT_OUTER:%.*]] = zext nneg i32 [[IV_OUTER_1]] to i64
+; CHECK-NEXT:    [[GEP_OUTER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[EXT_OUTER]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_OUTER]], align 1
+; CHECK-NEXT:    [[EXIT_COND_OUTER:%.*]] = icmp sgt i32 [[IV_OUTER]], 1
+; CHECK-NEXT:    br i1 [[EXIT_COND_OUTER]], label %[[INNER_LOOP_PREHEADER:.*]], label %[[PH]]
+; CHECK:       [[INNER_LOOP_PREHEADER]]:
+; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[INDVARS_IV1]] to i64
+; CHECK-NEXT:    br label %[[INNER_LOOP:.*]]
+; CHECK:       [[INNER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, %[[INNER_LOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], %[[INNER_LOOP]] ]
+; CHECK-NEXT:    [[GEP_INNER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_INNER]], align 1
+; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[INNER_LOOP]], label %[[PH_LOOPEXIT]]
+; CHECK:       [[EXIT:.*:]]
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  br label %outer.loop
+
+ph:
+  br label %outer.loop
+
+outer.loop:
+  %iv.outer = phi i32 [ %iv.outer.1, %ph ], [ %iter.count, %entry ]
+  %iv.outer.1 = add nsw i32 %iv.outer, -1
+  %ext.outer = zext nneg i32 %iv.outer.1 to i64
+  %gep.outer = getelementptr i8, ptr %ptr, i64 %ext.outer
+  store i8 0, ptr %gep.outer
+  %exit.cond.outer = icmp sgt i32 %iv.outer, 1
+  br i1 %exit.cond.outer, label %inner.loop, label %ph
+
+inner.loop:
+  %iv.inner = phi i32 [ %iv.next, %inner.loop ], [ 0, %outer.loop ]
+  %ext.inner = zext nneg i32 %iv.inner to i64
+  %gep.inner = getelementptr i8, ptr %ptr, i64 %ext.inner
+  store i8 0, ptr %gep.inner
+  %iv.next = add nuw nsw i32 %iv.inner, 1
+  %exit.cond.inner = icmp samesign ult i32 %iv.next, %iv.outer.1
+  br i1 %exit.cond.inner, label %inner.loop, label %ph
+
+exit:
+  ret i32 0
+}
+
+define i32 @iv_zext_zext_sgt_lt_exitlimit(i32 %iter.count, i32 %exit.limit, ptr %ptr) {
+; CHECK-LABEL: define i32 @iv_zext_zext_sgt_lt_exitlimit(
+; CHECK-SAME: i32 [[ITER_COUNT:%.*]], i32 [[EXIT_LIMIT:%.*]], ptr [[PTR:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[OUTER_LOOP:.*]]
+; CHECK:       [[PH_LOOPEXIT:.*]]:
+; CHECK-NEXT:    br label %[[PH:.*]]
+; CHECK:       [[PH]]:
+; CHECK-NEXT:    br label %[[OUTER_LOOP]]
+; CHECK:       [[OUTER_LOOP]]:
+; CHECK-NEXT:    [[IV_OUTER:%.*]] = phi i32 [ [[IV_OUTER_1:%.*]], %[[PH]] ], [ [[ITER_COUNT]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[IV_OUTER_1]] = add nsw i32 [[IV_OUTER]], -1
+; CHECK-NEXT:    [[EXT_OUTER:%.*]] = zext nneg i32 [[IV_OUTER_1]] to i64
+; CHECK-NEXT:    [[GEP_OUTER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[EXT_OUTER]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_OUTER]], align 1
+; CHECK-NEXT:    [[EXIT_COND_OUTER:%.*]] = icmp sgt i32 [[IV_OUTER]], [[EXIT_LIMIT]]
+; CHECK-NEXT:    br i1 [[EXIT_COND_OUTER]], label %[[INNER_LOOP_PREHEADER:.*]], label %[[PH]]
+; CHECK:       [[INNER_LOOP_PREHEADER]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[IV_OUTER_1]] to i64
+; CHECK-NEXT:    br label %[[INNER_LOOP:.*]]
+; CHECK:       [[INNER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, %[[INNER_LOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], %[[INNER_LOOP]] ]
+; CHECK-NEXT:    [[GEP_INNER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_INNER]], align 1
+; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[EXIT_COND_INNER:%.*]] = icmp samesign ult i64 [[INDVARS_IV_NEXT]], [[TMP1]]
+; CHECK-NEXT:    br i1 [[EXIT_COND_INNER]], label %[[INNER_LOOP]], label %[[PH_LOOPEXIT]]
+; CHECK:       [[EXIT:.*:]]
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  br label %outer.loop
+
+ph:
+  br label %outer.loop
+
+outer.loop:
+  %iv.outer = phi i32 [ %iv.outer.1, %ph ], [ %iter.count, %entry ]
+  %iv.outer.1 = add nsw i32 %iv.outer, -1
+  %ext.outer = zext nneg i32 %iv.outer.1 to i64
+  %gep.outer = getelementptr i8, ptr %ptr, i64 %ext.outer
+  store i8 0, ptr %gep.outer
+  %exit.cond.outer = icmp sgt i32 %iv.outer, %exit.limit
+  br i1 %exit.cond.outer, label %inner.loop, label %ph
+
+inner.loop:
+  %iv.inner = phi i32 [ %iv.next, %inner.loop ], [ 0, %outer.loop ]
+  %ext.inner = zext nneg i32 %iv.inner to i64
+  %gep.inner = getelementptr i8, ptr %ptr, i64 %ext.inner
+  store i8 0, ptr %gep.inner
+  %iv.next = add nuw nsw i32 %iv.inner, 1
+  %exit.cond.inner = icmp samesign ult i32 %iv.next, %iv.outer.1
+  br i1 %exit.cond.inner, label %inner.loop, label %ph
+
+exit:
+  ret i32 0
+}
+
+define i32 @iv_zext_zext_gt_lt(i32 %iter.count, ptr %ptr) {
+; CHECK-LABEL: define i32 @iv_zext_zext_gt_lt(
+; CHECK-SAME: i32 [[ITER_COUNT:%.*]], ptr [[PTR:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[ITER_COUNT]], -1
+; CHECK-NEXT:    br label %[[OUTER_LOOP:.*]]
+; CHECK:       [[PH_LOOPEXIT:.*]]:
+; CHECK-NEXT:    br label %[[PH:.*]]
+; CHECK:       [[PH]]:
+; CHECK-NEXT:    [[INDVARS_IV_NEXT2:%.*]] = add i32 [[INDVARS_IV1:%.*]], -1
+; CHECK-NEXT:    br label %[[OUTER_LOOP]]
+; CHECK:       [[OUTER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV1]] = phi i32 [ [[INDVARS_IV_NEXT2]], %[[PH]] ], [ [[TMP0]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[IV_OUTER:%.*]] = phi i32 [ [[IV_OUTER_1:%.*]], %[[PH]] ], [ [[ITER_COUNT]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[IV_OUTER_1]] = add nsw i32 [[IV_OUTER]], -1
+; CHECK-NEXT:    [[EXT_OUTER:%.*]] = zext nneg i32 [[IV_OUTER_1]] to i64
+; CHECK-NEXT:    [[GEP_OUTER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[EXT_OUTER]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_OUTER]], align 1
+; CHECK-NEXT:    [[EXIT_COND_OUTER:%.*]] = icmp samesign ugt i32 [[IV_OUTER]], 1
+; CHECK-NEXT:    br i1 [[EXIT_COND_OUTER]], label %[[INNER_LOOP_PREHEADER:.*]], label %[[PH]]
+; CHECK:       [[INNER_LOOP_PREHEADER]]:
+; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[INDVARS_IV1]] to i64
+; CHECK-NEXT:    br label %[[INNER_LOOP:.*]]
+; CHECK:       [[INNER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, %[[INNER_LOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], %[[INNER_LOOP]] ]
+; CHECK-NEXT:    [[GEP_INNER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_INNER]], align 1
+; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[INNER_LOOP]], label %[[PH_LOOPEXIT]]
+; CHECK:       [[EXIT:.*:]]
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  br label %outer.loop
+
+ph:
+  br label %outer.loop
+
+outer.loop:
+  %iv.outer = phi i32 [ %iv.outer.1, %ph ], [ %iter.count, %entry ]
+  %iv.outer.1 = add nsw i32 %iv.outer, -1
+  %ext.outer = zext nneg i32 %iv.outer.1 to i64
+  %gep.outer = getelementptr i8, ptr %ptr, i64 %ext.outer
+  store i8 0, ptr %gep.outer
+  %exit.cond.outer = icmp samesign ugt i32 %iv.outer, 1
+  br i1 %exit.cond.outer, label %inner.loop, label %ph
+
+inner.loop:
+  %iv.inner = phi i32 [ %iv.next, %inner.loop ], [ 0, %outer.loop ]
+  %ext.inner = zext nneg i32 %iv.inner to i64
+  %gep.inner = getelementptr i8, ptr %ptr, i64 %ext.inner
+  store i8 0, ptr %gep.inner
+  %iv.next = add nuw nsw i32 %iv.inner, 1
+  %exit.cond.inner = icmp samesign ult i32 %iv.next, %iv.outer.1
+  br i1 %exit.cond.inner, label %inner.loop, label %ph
+
+exit:
+  ret i32 0
+}
+
+define i32 @iv_sext_sext_sgt_slt(i32 %iter.count, ptr %ptr) {
+; CHECK-LABEL: define i32 @iv_sext_sext_sgt_slt(
+; CHECK-SAME: i32 [[ITER_COUNT:%.*]], ptr [[PTR:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[ITER_COUNT]], -1
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[ITER_COUNT]] to i64
+; CHECK-NEXT:    br label %[[OUTER_LOOP:.*]]
+; CHECK:       [[PH_LOOPEXIT:.*]]:
+; CHECK-NEXT:    br label %[[PH:.*]]
+; CHECK:       [[PH]]:
+; CHECK-NEXT:    [[INDVARS_IV_NEXT2:%.*]] = add i32 [[INDVARS_IV1:%.*]], -1
+; CHECK-NEXT:    br label %[[OUTER_LOOP]]
+; CHECK:       [[OUTER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV3:%.*]] = phi i64 [ [[INDVARS_IV_NEXT4:%.*]], %[[PH]] ], [ [[TMP1]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[INDVARS_IV1]] = phi i32 [ [[INDVARS_IV_NEXT2]], %[[PH]] ], [ [[TMP0]], %[[ENTRY]] ]
+; CHECK-NEXT:    [[INDVARS_IV_NEXT4]] = add nsw i64 [[INDVARS_IV3]], -1
+; CHECK-NEXT:    [[GEP_OUTER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[INDVARS_IV_NEXT4]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_OUTER]], align 1
+; CHECK-NEXT:    [[EXIT_COND_OUTER:%.*]] = icmp sgt i64 [[INDVARS_IV3]], 1
+; CHECK-NEXT:    br i1 [[EXIT_COND_OUTER]], label %[[INNER_LOOP_PREHEADER:.*]], label %[[PH]]
+; CHECK:       [[INNER_LOOP_PREHEADER]]:
+; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[INDVARS_IV1]] to i64
+; CHECK-NEXT:    br label %[[INNER_LOOP:.*]]
+; CHECK:       [[INNER_LOOP]]:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, %[[INNER_LOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], %[[INNER_LOOP]] ]
+; CHECK-NEXT:    [[GEP_INNER:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    store i8 0, ptr [[GEP_INNER]], align 1
+; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[INNER_LOOP]], label %[[PH_LOOPEXIT]]
+; CHECK:       [[EXIT:.*:]]
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  br label %outer.loop
+
+ph:
+  br label %outer.loop
+
+outer.loop:
+  %iv.outer = phi i32 [ %iv.outer.1, %ph ], [ %iter.count, %entry ]
+  %iv.outer.1 = add nsw i32 %iv.outer, -1
+  %ext.outer = sext i32 %iv.outer.1 to i64
+  %gep.outer = getelementptr i...
[truncated]

@artagnon artagnon merged commit d0f472c into llvm:main Feb 6, 2025
10 checks passed
@artagnon artagnon deleted the siv-widen-loop-compare-samesign-dup branch February 6, 2025 11:13
@llvm-ci
Copy link
Collaborator

llvm-ci commented Feb 6, 2025

LLVM Buildbot has detected a new failure on builder arc-builder running on arc-worker while building llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/3/builds/11368

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: 1200 seconds without output running [b'ninja', b'check-all'], attempting to kill
0.810 [59/18/1] Linking CXX executable tools/clang/unittests/Basic/BasicTests
1.926 [58/18/2] Linking CXX executable tools/clang/unittests/Format/FormatTests
5.782 [57/18/3] Linking CXX executable tools/clang/unittests/Lex/LexTests
6.266 [56/18/4] Linking CXX executable tools/clang/unittests/libclang/libclangTests
9.441 [55/18/5] Linking CXX executable tools/clang/unittests/Rewrite/RewriteTests
11.814 [54/18/6] Linking CXX executable tools/clang/unittests/CrossTU/CrossTUTests
12.476 [53/18/7] Linking CXX executable tools/clang/unittests/libclang/CrashTests/libclangCrashTests
13.306 [52/18/8] Linking CXX executable tools/clang/unittests/Tooling/Syntax/SyntaxTests
14.188 [51/18/9] Linking CXX executable tools/clang/unittests/InstallAPI/InstallAPITests
command timed out: 1200 seconds without output running [b'ninja', b'check-all'], attempting to kill
process killed by signal 9
program finished with exit code -1
elapsedTime=1214.943815

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.

3 participants