[llvm] [InstCombine] Relax singleUse for GEP(p, add(x, constant)) to 2 GEPs (PR #209551)

Abhay Kanhere via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 14 15:47:17 PDT 2026


https://github.com/AbhayKanhere updated https://github.com/llvm/llvm-project/pull/209551

>From 7d2ce7618d3e010f56ba7842610b46a7e550eea4 Mon Sep 17 00:00:00 2001
From: Abhay Kanhere <a_kanhere at apple.com>
Date: Tue, 14 Jul 2026 09:33:23 -0700
Subject: [PATCH 1/2] [InstCombine] Relax singleUse for GEP(p,add(x,constant))
 to 2 GEPs

Bound checks for memory safety involve checking index expression before
access.
e.g.
  for ( i =0 ;i <n ; i++ )  {
   if( i - k > bound)
         llvm.trap()
    a[ i - k-1] ...
    a[ i - k]
   }

   so invariably, the index expression is no longer singleUse and this prevents
fold of GEP(p,ADD(x,y))) -> GEP( GEP(p,x),y). This later prevents optimizations
such as wideing the load or store

SingleUse check here is not a correctness check.
   Here we relax the requirement of singleUse for constant 'y'. This enables
later optimizations such as aggressive instcombine widening with simplified
GEP with constant offsets.
---
 .../InstCombine/InstructionCombining.cpp      |  6 +-
 .../InstCombine/gep-addlike-multiuse.ll       | 64 +++++++++++++++++++
 2 files changed, 68 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/Transforms/InstCombine/gep-addlike-multiuse.ll

diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 1e24ff8d51057..a149c45e12615 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -3652,9 +3652,11 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
     };
 
     // Try to replace ADD + GEP with GEP + GEP.
+    // Relax singleUse condition for constant added to GEP without risking
+    // infinite loop.
     Value *Idx1, *Idx2;
-    if (match(GEP.getOperand(1),
-              m_OneUse(m_AddLike(m_Value(Idx1), m_Value(Idx2))))) {
+    if (match(GEP.getOperand(1), m_AddLike(m_Value(Idx1), m_Value(Idx2))) &&
+        (GEP.getOperand(1)->hasOneUse() || match(Idx2, m_ConstantInt()))) {
       //   %idx = add i64 %idx1, %idx2
       //   %gep = getelementptr i32, ptr %ptr, i64 %idx
       // as:
diff --git a/llvm/test/Transforms/InstCombine/gep-addlike-multiuse.ll b/llvm/test/Transforms/InstCombine/gep-addlike-multiuse.ll
new file mode 100644
index 0000000000000..278d412e427f7
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/gep-addlike-multiuse.ll
@@ -0,0 +1,64 @@
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+; Bounds-checked array access `a[i + k]`: the index `add i, k` feeds BOTH the
+; bounds-check compare (which dominates the access) AND the element GEP, so it
+; is inherently multi-use. When the addend `k` is a constant we still split it
+; out of the GEP: the inner `gep base, %idx` is shared with sibling accesses
+; (CSE) and the exposed constant offset enables later optimizations
+; (e.g. AggressiveInstCombine load-widening) 
+
+define ptr @boundscheck_const_addend(ptr %base, i64 %idx, i64 %n) {
+; CHECK-LABEL: define ptr @boundscheck_const_addend(
+; CHECK-SAME: ptr [[BASE:%.*]], i64 [[IDX:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:    [[OFF:%.*]] = add nsw i64 [[IDX]], 3
+; CHECK-NEXT:    [[OOB:%.*]] = icmp ult i64 [[OFF]], [[N]]
+; CHECK-NEXT:    br i1 [[OOB]], label %[[OK:.*]], label %[[TRAP:.*]]
+; CHECK:       [[OK]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[IDX]]
+; CHECK-NEXT:    [[P:%.*]] = getelementptr i8, ptr [[TMP1]], i64 3
+; CHECK-NEXT:    ret ptr [[P]]
+; CHECK:       [[TRAP]]:
+; CHECK-NEXT:    call void @llvm.trap()
+; CHECK-NEXT:    unreachable
+;
+  %off = add nsw i64 %idx, 3
+  %oob = icmp uge i64 %off, %n
+  br i1 %oob, label %trap, label %ok
+
+ok:
+  %p = getelementptr inbounds i8, ptr %base, i64 %off
+  ret ptr %p
+
+trap:
+  call void @llvm.trap()
+  unreachable
+}
+
+; Negative: a multi-use add with a *variable* addend must NOT split unless profitable
+define ptr @boundscheck_var_addend(ptr %base, i64 %idx, i64 %v, i64 %n) {
+; CHECK-LABEL: define ptr @boundscheck_var_addend(
+; CHECK-SAME: ptr [[BASE:%.*]], i64 [[IDX:%.*]], i64 [[V:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:    [[OFF:%.*]] = add nsw i64 [[IDX]], [[V]]
+; CHECK-NEXT:    [[OOB:%.*]] = icmp ult i64 [[OFF]], [[N]]
+; CHECK-NEXT:    br i1 [[OOB]], label %[[OK:.*]], label %[[TRAP:.*]]
+; CHECK:       [[OK]]:
+; CHECK-NEXT:    [[P:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[OFF]]
+; CHECK-NEXT:    ret ptr [[P]]
+; CHECK:       [[TRAP]]:
+; CHECK-NEXT:    call void @llvm.trap()
+; CHECK-NEXT:    unreachable
+;
+  %off = add nsw i64 %idx, %v
+  %oob = icmp uge i64 %off, %n
+  br i1 %oob, label %trap, label %ok
+
+ok:
+  %p = getelementptr inbounds i8, ptr %base, i64 %off
+  ret ptr %p
+
+trap:
+  call void @llvm.trap()
+  unreachable
+}
+
+declare void @llvm.trap()

>From 478cb8633310f2a836c8b6cccc1807e26c34b8b5 Mon Sep 17 00:00:00 2001
From: Abhay Kanhere <a_kanhere at apple.com>
Date: Tue, 14 Jul 2026 15:45:50 -0700
Subject: [PATCH 2/2] [tests] update tests

Updated following tests, verified the changes are due to allowing GEP fold with constant so
as expected:
llvm/test/Transforms/InstCombine/gepofconstgepi8.ll
llvm/test/Transforms/InstCombine/getelementptr.ll
llvm/test/Transforms/LoopUnroll/WebAssembly/basic-unrolling.ll
llvm/test/Transforms/LoopUnroll/runtime-unroll-remainder.ll
llvm/test/Transforms/LoopVectorize/loop-scalars.ll
llvm/test/Transforms/PhaseOrdering/AArch64/Oz-and-forced-vectorize.ll
---
 .../Transforms/InstCombine/gepofconstgepi8.ll |  4 +--
 .../Transforms/InstCombine/getelementptr.ll   |  6 ++--
 .../LoopUnroll/WebAssembly/basic-unrolling.ll | 31 +++++++++-------
 .../LoopUnroll/runtime-unroll-remainder.ll    | 35 +++++++++++--------
 .../Transforms/LoopVectorize/loop-scalars.ll  | 22 ++++++------
 .../AArch64/Oz-and-forced-vectorize.ll        |  7 ++--
 6 files changed, 59 insertions(+), 46 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/gepofconstgepi8.ll b/llvm/test/Transforms/InstCombine/gepofconstgepi8.ll
index 64484dd72ad3f..9e652b568d5bf 100644
--- a/llvm/test/Transforms/InstCombine/gepofconstgepi8.ll
+++ b/llvm/test/Transforms/InstCombine/gepofconstgepi8.ll
@@ -241,10 +241,10 @@ define ptr @test_nonzero_multiuse_index(ptr %base, i64 %a) {
 ; CHECK-LABEL: define ptr @test_nonzero_multiuse_index(
 ; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4
 ; CHECK-NEXT:    [[INDEX:%.*]] = add i64 [[A]], 2
 ; CHECK-NEXT:    call void @use64(i64 [[INDEX]])
-; CHECK-NEXT:    [[P2:%.*]] = getelementptr [4 x i8], ptr [[P1]], i64 [[INDEX]]
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr [4 x i8], ptr [[BASE]], i64 [[A]]
+; CHECK-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 4
 ; CHECK-NEXT:    ret ptr [[P2]]
 ;
 entry:
diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll
index da3ae69d41a8e..18e9f62fe51af 100644
--- a/llvm/test/Transforms/InstCombine/getelementptr.ll
+++ b/llvm/test/Transforms/InstCombine/getelementptr.ll
@@ -696,10 +696,10 @@ define i32 @test28() nounwind  {
 ; CHECK-NEXT:    [[INDVAR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[BB10]] ]
 ; CHECK-NEXT:    [[T12_REC:%.*]] = xor i32 [[INDVAR]], -1
 ; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[T12_REC]] to i64
-; CHECK-NEXT:    [[TMP1:%.*]] = add nsw i64 [[TMP0]], 1
-; CHECK-NEXT:    [[T12:%.*]] = getelementptr inbounds i8, ptr [[ORIENTATIONS]], i64 [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[ORIENTATIONS]], i64 [[TMP0]]
+; CHECK-NEXT:    [[T12:%.*]] = getelementptr i8, ptr [[TMP1]], i64 1
 ; CHECK-NEXT:    [[T16:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @.str1, ptr nonnull [[T12]]) #[[ATTR0]]
-; CHECK-NEXT:    [[T84:%.*]] = icmp eq i64 [[TMP1]], 0
+; CHECK-NEXT:    [[T84:%.*]] = icmp eq i32 [[INDVAR]], 0
 ; CHECK-NEXT:    [[INDVAR_NEXT]] = add i32 [[INDVAR]], 1
 ; CHECK-NEXT:    br i1 [[T84]], label [[BB17:%.*]], label [[BB10]]
 ; CHECK:       bb17:
diff --git a/llvm/test/Transforms/LoopUnroll/WebAssembly/basic-unrolling.ll b/llvm/test/Transforms/LoopUnroll/WebAssembly/basic-unrolling.ll
index 7f17fe284b803..7c157e394cb98 100644
--- a/llvm/test/Transforms/LoopUnroll/WebAssembly/basic-unrolling.ll
+++ b/llvm/test/Transforms/LoopUnroll/WebAssembly/basic-unrolling.ll
@@ -76,23 +76,26 @@ define hidden void @compile_time_partial(ptr nocapture %a, ptr nocapture readonl
 ; CHECK-NEXT:    [[ADD:%.*]] = add i16 [[I]], 1
 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[A:%.*]], i32 [[I_07]]
 ; CHECK-NEXT:    store i16 [[ADD]], ptr [[ARRAYIDX2]], align 2
-; CHECK-NEXT:    [[INC:%.*]] = or disjoint i32 [[I_07]], 1
-; CHECK-NEXT:    [[ARRAYIDX_1:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[B]], i32 [[INC]]
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[B]], i32 [[I_07]]
+; CHECK-NEXT:    [[ARRAYIDX_1:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i32 2
 ; CHECK-NEXT:    [[I_1:%.*]] = load i16, ptr [[ARRAYIDX_1]], align 2
 ; CHECK-NEXT:    [[ADD_1:%.*]] = add i16 [[I_1]], 1
-; CHECK-NEXT:    [[ARRAYIDX2_1:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[A]], i32 [[INC]]
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[A]], i32 [[I_07]]
+; CHECK-NEXT:    [[ARRAYIDX2_1:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i32 2
 ; CHECK-NEXT:    store i16 [[ADD_1]], ptr [[ARRAYIDX2_1]], align 2
-; CHECK-NEXT:    [[INC_1:%.*]] = or disjoint i32 [[I_07]], 2
-; CHECK-NEXT:    [[ARRAYIDX_2:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[B]], i32 [[INC_1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[B]], i32 [[I_07]]
+; CHECK-NEXT:    [[ARRAYIDX_2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP2]], i32 4
 ; CHECK-NEXT:    [[I_2:%.*]] = load i16, ptr [[ARRAYIDX_2]], align 2
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add i16 [[I_2]], 1
-; CHECK-NEXT:    [[ARRAYIDX2_2:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[A]], i32 [[INC_1]]
+; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[A]], i32 [[I_07]]
+; CHECK-NEXT:    [[ARRAYIDX2_2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP3]], i32 4
 ; CHECK-NEXT:    store i16 [[ADD_2]], ptr [[ARRAYIDX2_2]], align 2
-; CHECK-NEXT:    [[INC_2:%.*]] = or disjoint i32 [[I_07]], 3
-; CHECK-NEXT:    [[ARRAYIDX_3:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[B]], i32 [[INC_2]]
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[B]], i32 [[I_07]]
+; CHECK-NEXT:    [[ARRAYIDX_3:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP4]], i32 6
 ; CHECK-NEXT:    [[I_3:%.*]] = load i16, ptr [[ARRAYIDX_3]], align 2
 ; CHECK-NEXT:    [[ADD_3:%.*]] = add i16 [[I_3]], 1
-; CHECK-NEXT:    [[ARRAYIDX2_3:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[A]], i32 [[INC_2]]
+; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds nuw [2 x i8], ptr [[A]], i32 [[I_07]]
+; CHECK-NEXT:    [[ARRAYIDX2_3:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP5]], i32 6
 ; CHECK-NEXT:    store i16 [[ADD_3]], ptr [[ARRAYIDX2_3]], align 2
 ; CHECK-NEXT:    [[INC_3]] = add nuw nsw i32 [[I_07]], 4
 ; CHECK-NEXT:    [[EXITCOND_NOT_3:%.*]] = icmp eq i32 [[INC_3]], 1000
@@ -155,13 +158,15 @@ define hidden void @runtime(ptr nocapture %a, ptr nocapture readonly %b, ptr noc
 ; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[I1]], [[I]]
 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [4 x i8], ptr [[A]], i32 [[I_09]]
 ; CHECK-NEXT:    store i32 [[MUL]], ptr [[ARRAYIDX2]], align 4
-; CHECK-NEXT:    [[INC:%.*]] = or disjoint i32 [[I_09]], 1
-; CHECK-NEXT:    [[ARRAYIDX_1:%.*]] = getelementptr inbounds [4 x i8], ptr [[B]], i32 [[INC]]
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr [4 x i8], ptr [[B]], i32 [[I_09]]
+; CHECK-NEXT:    [[ARRAYIDX_1:%.*]] = getelementptr i8, ptr [[TMP1]], i32 4
 ; CHECK-NEXT:    [[I_1:%.*]] = load i32, ptr [[ARRAYIDX_1]], align 4
-; CHECK-NEXT:    [[ARRAYIDX1_1:%.*]] = getelementptr inbounds [4 x i8], ptr [[C]], i32 [[INC]]
+; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr [4 x i8], ptr [[C]], i32 [[I_09]]
+; CHECK-NEXT:    [[ARRAYIDX1_1:%.*]] = getelementptr i8, ptr [[TMP2]], i32 4
 ; CHECK-NEXT:    [[I1_1:%.*]] = load i32, ptr [[ARRAYIDX1_1]], align 4
 ; CHECK-NEXT:    [[MUL_1:%.*]] = mul nsw i32 [[I1_1]], [[I_1]]
-; CHECK-NEXT:    [[ARRAYIDX2_1:%.*]] = getelementptr inbounds [4 x i8], ptr [[A]], i32 [[INC]]
+; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr [4 x i8], ptr [[A]], i32 [[I_09]]
+; CHECK-NEXT:    [[ARRAYIDX2_1:%.*]] = getelementptr i8, ptr [[TMP3]], i32 4
 ; CHECK-NEXT:    store i32 [[MUL_1]], ptr [[ARRAYIDX2_1]], align 4
 ; CHECK-NEXT:    [[INC_1]] = add nuw i32 [[I_09]], 2
 ; CHECK-NEXT:    [[NITER_NEXT_1]] = add i32 [[NITER]], 2
diff --git a/llvm/test/Transforms/LoopUnroll/runtime-unroll-remainder.ll b/llvm/test/Transforms/LoopUnroll/runtime-unroll-remainder.ll
index 3c9c3bd10a93c..0a9958cc59891 100644
--- a/llvm/test/Transforms/LoopUnroll/runtime-unroll-remainder.ll
+++ b/llvm/test/Transforms/LoopUnroll/runtime-unroll-remainder.ll
@@ -34,20 +34,22 @@ define i32 @unroll(ptr nocapture readonly %a, ptr nocapture readonly %b, i32 %N)
 ; CHECK-NEXT:    [[EPIL_ITER_CMP_NOT:%.*]] = icmp eq i64 [[XTRAITER]], 1
 ; CHECK-NEXT:    br i1 [[EPIL_ITER_CMP_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_EPILOG_LCSSA:%.*]], label [[FOR_BODY_EPIL_1:%.*]]
 ; CHECK:       for.body.epil.1:
-; CHECK-NEXT:    [[INDVARS_IV_NEXT_EPIL:%.*]] = add nuw nsw i64 [[INDVARS_IV_EPIL_INIT]], 1
-; CHECK-NEXT:    [[ARRAYIDX_EPIL_1:%.*]] = getelementptr inbounds [4 x i8], ptr [[A]], i64 [[INDVARS_IV_NEXT_EPIL]]
+; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr [4 x i8], ptr [[A]], i64 [[INDVARS_IV_EPIL_INIT]]
+; CHECK-NEXT:    [[ARRAYIDX_EPIL_1:%.*]] = getelementptr i8, ptr [[TMP16]], i64 4
 ; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[ARRAYIDX_EPIL_1]], align 4
-; CHECK-NEXT:    [[ARRAYIDX2_EPIL_1:%.*]] = getelementptr inbounds [4 x i8], ptr [[B]], i64 [[INDVARS_IV_NEXT_EPIL]]
+; CHECK-NEXT:    [[TMP18:%.*]] = getelementptr [4 x i8], ptr [[B]], i64 [[INDVARS_IV_EPIL_INIT]]
+; CHECK-NEXT:    [[ARRAYIDX2_EPIL_1:%.*]] = getelementptr i8, ptr [[TMP18]], i64 4
 ; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[ARRAYIDX2_EPIL_1]], align 4
 ; CHECK-NEXT:    [[MUL_EPIL_1:%.*]] = mul nsw i32 [[TMP4]], [[TMP3]]
 ; CHECK-NEXT:    [[ADD_EPIL_1:%.*]] = add nsw i32 [[MUL_EPIL_1]], [[ADD_EPIL]]
 ; CHECK-NEXT:    [[EPIL_ITER_CMP_1_NOT:%.*]] = icmp eq i64 [[XTRAITER]], 2
 ; CHECK-NEXT:    br i1 [[EPIL_ITER_CMP_1_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_EPILOG_LCSSA]], label [[FOR_BODY_EPIL_2:%.*]]
 ; CHECK:       for.body.epil.2:
-; CHECK-NEXT:    [[INDVARS_IV_NEXT_EPIL_1:%.*]] = add nuw nsw i64 [[INDVARS_IV_EPIL_INIT]], 2
-; CHECK-NEXT:    [[ARRAYIDX_EPIL_2:%.*]] = getelementptr inbounds [4 x i8], ptr [[A]], i64 [[INDVARS_IV_NEXT_EPIL_1]]
+; CHECK-NEXT:    [[TMP20:%.*]] = getelementptr [4 x i8], ptr [[A]], i64 [[INDVARS_IV_EPIL_INIT]]
+; CHECK-NEXT:    [[ARRAYIDX_EPIL_2:%.*]] = getelementptr i8, ptr [[TMP20]], i64 8
 ; CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX_EPIL_2]], align 4
-; CHECK-NEXT:    [[ARRAYIDX2_EPIL_2:%.*]] = getelementptr inbounds [4 x i8], ptr [[B]], i64 [[INDVARS_IV_NEXT_EPIL_1]]
+; CHECK-NEXT:    [[TMP22:%.*]] = getelementptr [4 x i8], ptr [[B]], i64 [[INDVARS_IV_EPIL_INIT]]
+; CHECK-NEXT:    [[ARRAYIDX2_EPIL_2:%.*]] = getelementptr i8, ptr [[TMP22]], i64 8
 ; CHECK-NEXT:    [[TMP6:%.*]] = load i32, ptr [[ARRAYIDX2_EPIL_2]], align 4
 ; CHECK-NEXT:    [[MUL_EPIL_2:%.*]] = mul nsw i32 [[TMP6]], [[TMP5]]
 ; CHECK-NEXT:    [[ADD_EPIL_2:%.*]] = add nsw i32 [[MUL_EPIL_2]], [[ADD_EPIL_1]]
@@ -71,24 +73,27 @@ define i32 @unroll(ptr nocapture readonly %a, ptr nocapture readonly %b, i32 %N)
 ; CHECK-NEXT:    [[TMP8:%.*]] = load i32, ptr [[ARRAYIDX2]], align 4
 ; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[TMP8]], [[TMP7]]
 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[MUL]], [[C_010]]
-; CHECK-NEXT:    [[INDVARS_IV_NEXT:%.*]] = or disjoint i64 [[INDVARS_IV]], 1
-; CHECK-NEXT:    [[ARRAYIDX_1:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[A]], i64 [[INDVARS_IV_NEXT]]
+; CHECK-NEXT:    [[TMP24:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[A]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[ARRAYIDX_1:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP24]], i64 4
 ; CHECK-NEXT:    [[TMP9:%.*]] = load i32, ptr [[ARRAYIDX_1]], align 4
-; CHECK-NEXT:    [[ARRAYIDX2_1:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[B]], i64 [[INDVARS_IV_NEXT]]
+; CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[B]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[ARRAYIDX2_1:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP15]], i64 4
 ; CHECK-NEXT:    [[TMP10:%.*]] = load i32, ptr [[ARRAYIDX2_1]], align 4
 ; CHECK-NEXT:    [[MUL_1:%.*]] = mul nsw i32 [[TMP10]], [[TMP9]]
 ; CHECK-NEXT:    [[ADD_1:%.*]] = add nsw i32 [[MUL_1]], [[ADD]]
-; CHECK-NEXT:    [[INDVARS_IV_NEXT_1:%.*]] = or disjoint i64 [[INDVARS_IV]], 2
-; CHECK-NEXT:    [[ARRAYIDX_2:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[A]], i64 [[INDVARS_IV_NEXT_1]]
+; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[A]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[ARRAYIDX_2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP17]], i64 8
 ; CHECK-NEXT:    [[TMP11:%.*]] = load i32, ptr [[ARRAYIDX_2]], align 4
-; CHECK-NEXT:    [[ARRAYIDX2_2:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[B]], i64 [[INDVARS_IV_NEXT_1]]
+; CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[B]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[ARRAYIDX2_2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP19]], i64 8
 ; CHECK-NEXT:    [[TMP12:%.*]] = load i32, ptr [[ARRAYIDX2_2]], align 4
 ; CHECK-NEXT:    [[MUL_2:%.*]] = mul nsw i32 [[TMP12]], [[TMP11]]
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i32 [[MUL_2]], [[ADD_1]]
-; CHECK-NEXT:    [[INDVARS_IV_NEXT_2:%.*]] = or disjoint i64 [[INDVARS_IV]], 3
-; CHECK-NEXT:    [[ARRAYIDX_3:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[A]], i64 [[INDVARS_IV_NEXT_2]]
+; CHECK-NEXT:    [[TMP21:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[A]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[ARRAYIDX_3:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP21]], i64 12
 ; CHECK-NEXT:    [[TMP13:%.*]] = load i32, ptr [[ARRAYIDX_3]], align 4
-; CHECK-NEXT:    [[ARRAYIDX2_3:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[B]], i64 [[INDVARS_IV_NEXT_2]]
+; CHECK-NEXT:    [[TMP23:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[B]], i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[ARRAYIDX2_3:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP23]], i64 12
 ; CHECK-NEXT:    [[TMP14:%.*]] = load i32, ptr [[ARRAYIDX2_3]], align 4
 ; CHECK-NEXT:    [[MUL_3:%.*]] = mul nsw i32 [[TMP14]], [[TMP13]]
 ; CHECK-NEXT:    [[ADD_3]] = add nsw i32 [[MUL_3]], [[ADD_2]]
diff --git a/llvm/test/Transforms/LoopVectorize/loop-scalars.ll b/llvm/test/Transforms/LoopVectorize/loop-scalars.ll
index 1cfe27f3f8db1..b4d31fe9d3d70 100644
--- a/llvm/test/Transforms/LoopVectorize/loop-scalars.ll
+++ b/llvm/test/Transforms/LoopVectorize/loop-scalars.ll
@@ -73,11 +73,12 @@ define void @scalar_store(ptr %a, ptr %b, i64 %n) {
 ; CHECK:       vector.body:
 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
 ; CHECK-NEXT:    [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 1
-; CHECK-NEXT:    [[TMP3:%.*]] = or disjoint i64 [[OFFSET_IDX]], 2
 ; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [4 x i8], ptr [[B:%.*]], i64 [[OFFSET_IDX]]
-; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [4 x i8], ptr [[B]], i64 [[TMP3]]
+; CHECK-NEXT:    [[TMP10:%.*]] = getelementptr [4 x i8], ptr [[B]], i64 [[OFFSET_IDX]]
+; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr i8, ptr [[TMP10]], i64 8
 ; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [8 x i8], ptr [[A:%.*]], i64 [[OFFSET_IDX]]
-; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [8 x i8], ptr [[A]], i64 [[TMP3]]
+; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr [8 x i8], ptr [[A]], i64 [[OFFSET_IDX]]
+; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr i8, ptr [[TMP9]], i64 16
 ; CHECK-NEXT:    store ptr [[TMP4]], ptr [[TMP6]], align 8
 ; CHECK-NEXT:    store ptr [[TMP5]], ptr [[TMP7]], align 8
 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
@@ -133,12 +134,13 @@ define void @expansion(ptr %a, ptr %b, i64 %n) {
 ; CHECK:       vector.body:
 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
 ; CHECK-NEXT:    [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 1
-; CHECK-NEXT:    [[TMP3:%.*]] = or disjoint i64 [[OFFSET_IDX]], 2
-; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [8 x i8], ptr [[B:%.*]], i64 [[OFFSET_IDX]]
-; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [8 x i8], ptr [[B]], i64 [[TMP3]]
 ; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [8 x i8], ptr [[A:%.*]], i64 [[OFFSET_IDX]]
-; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [8 x i8], ptr [[A]], i64 [[TMP3]]
-; CHECK-NEXT:    store ptr [[TMP4]], ptr [[TMP6]], align 8
+; CHECK-NEXT:    [[TMP10:%.*]] = getelementptr [8 x i8], ptr [[A]], i64 [[OFFSET_IDX]]
+; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr i8, ptr [[TMP10]], i64 16
+; CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [8 x i8], ptr [[A1:%.*]], i64 [[OFFSET_IDX]]
+; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr [8 x i8], ptr [[A1]], i64 [[OFFSET_IDX]]
+; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr i8, ptr [[TMP9]], i64 16
+; CHECK-NEXT:    store ptr [[TMP6]], ptr [[TMP11]], align 8
 ; CHECK-NEXT:    store ptr [[TMP5]], ptr [[TMP7]], align 8
 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
 ; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
@@ -151,8 +153,8 @@ define void @expansion(ptr %a, ptr %b, i64 %n) {
 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
 ; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ]
-; CHECK-NEXT:    [[VAR0:%.*]] = getelementptr inbounds [8 x i8], ptr [[B]], i64 [[I]]
-; CHECK-NEXT:    [[VAR3:%.*]] = getelementptr inbounds [8 x i8], ptr [[A]], i64 [[I]]
+; CHECK-NEXT:    [[VAR0:%.*]] = getelementptr inbounds [8 x i8], ptr [[A]], i64 [[I]]
+; CHECK-NEXT:    [[VAR3:%.*]] = getelementptr inbounds [8 x i8], ptr [[A1]], i64 [[I]]
 ; CHECK-NEXT:    store ptr [[VAR0]], ptr [[VAR3]], align 8
 ; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i64 [[I]], 2
 ; CHECK-NEXT:    [[COND:%.*]] = icmp slt i64 [[I_NEXT]], [[N]]
diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/Oz-and-forced-vectorize.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/Oz-and-forced-vectorize.ll
index 049d1baf5c615..e6cb6b39a3904 100644
--- a/llvm/test/Transforms/PhaseOrdering/AArch64/Oz-and-forced-vectorize.ll
+++ b/llvm/test/Transforms/PhaseOrdering/AArch64/Oz-and-forced-vectorize.ll
@@ -39,10 +39,11 @@ define void @foo(ptr noalias nocapture %ptrA, ptr noalias nocapture readonly %pt
 ; CHECK-NEXT:    [[TMP7:%.*]] = extractelement <2 x i1> [[TMP0]], i64 1
 ; CHECK-NEXT:    br i1 [[TMP7]], label %[[PRED_STORE_IF3:.*]], label %[[PRED_STORE_CONTINUE4]]
 ; CHECK:       [[PRED_STORE_IF3]]:
-; CHECK-NEXT:    [[TMP8:%.*]] = or disjoint i64 [[INDEX]], 1
-; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[PTRB]], i64 [[TMP8]]
+; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[PTRB]], i64 [[INDEX]]
+; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP8]], i64 4
 ; CHECK-NEXT:    [[TMP10:%.*]] = load float, ptr [[TMP9]], align 4
-; CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[PTRA]], i64 [[TMP8]]
+; CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[PTRA]], i64 [[INDEX]]
+; CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP15]], i64 4
 ; CHECK-NEXT:    [[TMP12:%.*]] = load float, ptr [[TMP11]], align 4
 ; CHECK-NEXT:    [[TMP13:%.*]] = fmul float [[TMP10]], [[TMP12]]
 ; CHECK-NEXT:    store float [[TMP13]], ptr [[TMP11]], align 4



More information about the llvm-commits mailing list