From b32e341e87fe2970acfec273b12500a849601d28 Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Tue, 24 Jun 2025 15:36:37 +0000 Subject: [PATCH 1/5] [InstCombine] Add test for freeze of GEP with recurrence offset (NFC) The freeze should be pushed through the GEP to the ptr like in: https://godbolt.org/z/jrcozT8rz --- llvm/test/Transforms/InstCombine/freeze.ll | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll index 8875ce1c566f3..50483d8e41ada 100644 --- a/llvm/test/Transforms/InstCombine/freeze.ll +++ b/llvm/test/Transforms/InstCombine/freeze.ll @@ -877,6 +877,39 @@ exit: ; preds = %loop ret void } +; The recurrence for the GEP offset can't produce undef so the freeze should be +; pushed through to the ptr, but this is not currently supported. +define void @fold_phi_gep_phi_offset(ptr %init, ptr %end, i64 noundef %n) { +; CHECK-LABEL: @fold_phi_phi_gep( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = phi ptr [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT_FR:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF:%.*]] = phi i64 [ [[N:%.*]], [[ENTRY]] ], [ [[OFF_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF_NEXT]] = shl i64 [[OFF]], 3 +; CHECK-NEXT: [[I_NEXT:%.*]] = getelementptr i8, ptr [[I]], i64 [[OFF_NEXT]] +; CHECK-NEXT: [[I_NEXT_FR]] = freeze ptr [[I_NEXT]] +; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[I_NEXT_FR]], [[END:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: ; preds = %loop, %entry + %i = phi ptr [ %init, %entry ], [ %i.next.fr, %loop ] + %off = phi i64 [ %n, %entry ], [ %off.next, %loop ] + %off.next = shl i64 %off, 3 + %i.next = getelementptr i8, ptr %i, i64 %off.next + %i.next.fr = freeze ptr %i.next + %cond = icmp eq ptr %i.next.fr, %end + br i1 %cond, label %loop, label %exit + +exit: ; preds = %loop + ret void +} + define void @fold_phi_multiple_insts(i32 %init, i32 %n) { ; CHECK-LABEL: @fold_phi_multiple_insts( ; CHECK-NEXT: entry: From ded4097cb781af3a272f6e3ff45a3421ce164cf0 Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Wed, 25 Jun 2025 07:50:32 +0000 Subject: [PATCH 2/5] update CHECK-LABEL --- llvm/test/Transforms/InstCombine/freeze.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll index 50483d8e41ada..f0c5eff71c086 100644 --- a/llvm/test/Transforms/InstCombine/freeze.ll +++ b/llvm/test/Transforms/InstCombine/freeze.ll @@ -880,7 +880,7 @@ exit: ; preds = %loop ; The recurrence for the GEP offset can't produce undef so the freeze should be ; pushed through to the ptr, but this is not currently supported. define void @fold_phi_gep_phi_offset(ptr %init, ptr %end, i64 noundef %n) { -; CHECK-LABEL: @fold_phi_phi_gep( +; CHECK-LABEL: @fold_phi_gep_phi_offset( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: From 2ca19f1adad02b2b3b22b67e78d0ac9514a23012 Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Wed, 25 Jun 2025 10:41:25 +0000 Subject: [PATCH 3/5] address comments --- llvm/test/Transforms/InstCombine/freeze.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll index f0c5eff71c086..a99094ea453c3 100644 --- a/llvm/test/Transforms/InstCombine/freeze.ll +++ b/llvm/test/Transforms/InstCombine/freeze.ll @@ -877,8 +877,8 @@ exit: ; preds = %loop ret void } -; The recurrence for the GEP offset can't produce undef so the freeze should be -; pushed through to the ptr, but this is not currently supported. +; The recurrence for the GEP offset can't produce poison so the freeze should +; be pushed through to the ptr, but this is not currently supported. define void @fold_phi_gep_phi_offset(ptr %init, ptr %end, i64 noundef %n) { ; CHECK-LABEL: @fold_phi_gep_phi_offset( ; CHECK-NEXT: entry: From a82060e2a3d70bd7262f792d2e0c2e9c07ff65df Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Wed, 25 Jun 2025 10:49:58 +0000 Subject: [PATCH 4/5] add test for GEP that can produce poison --- llvm/test/Transforms/InstCombine/freeze.ll | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll index a99094ea453c3..e92a947ac004a 100644 --- a/llvm/test/Transforms/InstCombine/freeze.ll +++ b/llvm/test/Transforms/InstCombine/freeze.ll @@ -910,6 +910,38 @@ exit: ; preds = %loop ret void } +; GEP can produce poison, check freeze isn't moved. +define void @cant_fold_phi_gep_phi_offset(ptr %init, ptr %end, i64 %n) { +; CHECK-LABEL: @cant_fold_phi_gep_phi_offset( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = phi ptr [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT_FR:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF:%.*]] = phi i64 [ [[N:%.*]], [[ENTRY]] ], [ [[OFF_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF_NEXT]] = shl i64 [[OFF]], 3 +; CHECK-NEXT: [[I_NEXT:%.*]] = getelementptr inbounds i8, ptr [[I]], i64 [[OFF_NEXT]] +; CHECK-NEXT: [[I_NEXT_FR]] = freeze ptr [[I_NEXT]] +; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[I_NEXT_FR]], [[END:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: ; preds = %loop, %entry + %i = phi ptr [ %init, %entry ], [ %i.next.fr, %loop ] + %off = phi i64 [ %n, %entry ], [ %off.next, %loop ] + %off.next = shl i64 %off, 3 + %i.next = getelementptr inbounds i8, ptr %i, i64 %off.next + %i.next.fr = freeze ptr %i.next + %cond = icmp eq ptr %i.next.fr, %end + br i1 %cond, label %loop, label %exit + +exit: ; preds = %loop + ret void +} + define void @fold_phi_multiple_insts(i32 %init, i32 %n) { ; CHECK-LABEL: @fold_phi_multiple_insts( ; CHECK-NEXT: entry: From b251c121f58af6596251c1e63313026b07d53f35 Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Wed, 25 Jun 2025 13:17:45 +0000 Subject: [PATCH 5/5] address comments --- llvm/test/Transforms/InstCombine/freeze.ll | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll index e92a947ac004a..9733f1b732c3f 100644 --- a/llvm/test/Transforms/InstCombine/freeze.ll +++ b/llvm/test/Transforms/InstCombine/freeze.ll @@ -910,6 +910,39 @@ exit: ; preds = %loop ret void } +; Offset is still guaranteed not to be poison, so the freeze could be moved +; here if we strip inbounds from the GEP, but this is not currently supported. +define void @fold_phi_gep_inbounds_phi_offset(ptr %init, ptr %end, i64 noundef %n) { +; CHECK-LABEL: @fold_phi_gep_inbounds_phi_offset( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = phi ptr [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT_FR:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF:%.*]] = phi i64 [ [[N:%.*]], [[ENTRY]] ], [ [[OFF_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[OFF_NEXT]] = shl i64 [[OFF]], 3 +; CHECK-NEXT: [[I_NEXT:%.*]] = getelementptr inbounds i8, ptr [[I]], i64 [[OFF_NEXT]] +; CHECK-NEXT: [[I_NEXT_FR]] = freeze ptr [[I_NEXT]] +; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[I_NEXT_FR]], [[END:%.*]] +; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: ; preds = %loop, %entry + %i = phi ptr [ %init, %entry ], [ %i.next.fr, %loop ] + %off = phi i64 [ %n, %entry ], [ %off.next, %loop ] + %off.next = shl i64 %off, 3 + %i.next = getelementptr inbounds i8, ptr %i, i64 %off.next + %i.next.fr = freeze ptr %i.next + %cond = icmp eq ptr %i.next.fr, %end + br i1 %cond, label %loop, label %exit + +exit: ; preds = %loop + ret void +} + ; GEP can produce poison, check freeze isn't moved. define void @cant_fold_phi_gep_phi_offset(ptr %init, ptr %end, i64 %n) { ; CHECK-LABEL: @cant_fold_phi_gep_phi_offset(