[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