From ef131e81d8e08d09f4d9c9487eb9f6cc6f8c9efc Mon Sep 17 00:00:00 2001
From: Andreu Carminati <andreu.carminati@amd.com>
Date: Wed, 6 Nov 2024 15:14:18 +0000
Subject: [PATCH] [AIE2] Implement TTI hook to disable GEP to PHI folding

---
 llvm/lib/Target/AIE/AIE2TargetTransformInfo.h |  9 ++++
 .../AIE/aie2/aie2-prevent-gep-phi-folding.ll  | 47 +++++++++++++++++++
 2 files changed, 56 insertions(+)
 create mode 100644 llvm/test/CodeGen/AIE/aie2/aie2-prevent-gep-phi-folding.ll

diff --git a/llvm/lib/Target/AIE/AIE2TargetTransformInfo.h b/llvm/lib/Target/AIE/AIE2TargetTransformInfo.h
index 5adee9b9a00b..ab11c13be61e 100644
--- a/llvm/lib/Target/AIE/AIE2TargetTransformInfo.h
+++ b/llvm/lib/Target/AIE/AIE2TargetTransformInfo.h
@@ -62,6 +62,15 @@ class AIE2TTIImpl : public BasicTTIImplBase<AIE2TTIImpl> {
   bool isProfitableOuterLSR(const Loop &L) const;
   std::optional<Instruction *> instCombineIntrinsic(InstCombiner &IC,
                                                     IntrinsicInst &II) const;
+
+  // By returning false here, we will prevent the following type
+  // of code from reaching the backend when GEPs are used as incoming values:
+  // for.body:     ; preds = %for.body, %for.preheader
+  //   %phi0 = phi ptr [ %in0, %for.body ], [ %out0, %for.preheader ]
+  //   %phi1 = phi ptr [ %phi0, %for.body ], [ %out1, %for.preheader ]
+  // This type of code can lead to additional pointer arithmetics and
+  // and pointer moves (especially due to the pre-pipeliner).
+  bool isProfitableFoldGEPIntoPHI() const { return false; }
 };
 
 } // end namespace llvm
diff --git a/llvm/test/CodeGen/AIE/aie2/aie2-prevent-gep-phi-folding.ll b/llvm/test/CodeGen/AIE/aie2/aie2-prevent-gep-phi-folding.ll
new file mode 100644
index 000000000000..542d1bac275a
--- /dev/null
+++ b/llvm/test/CodeGen/AIE/aie2/aie2-prevent-gep-phi-folding.ll
@@ -0,0 +1,47 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+;
+; This file is licensed under the Apache License v2.0 with LLVM Exceptions.
+; See https://llvm.org/LICENSE.txt for license information.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+; (c) Copyright 2024 Advanced Micro Devices, Inc. or its affiliates
+; RUN: opt -mtriple=aie2 -passes=instcombine -S < %s | FileCheck %s
+
+%struct = type { i32, i32 }
+
+define i32 @dontFoldGEPs(ptr %dm, i1 %arg4, i64 %arg9, i64 %arg19) {
+; CHECK-LABEL: define i32 @dontFoldGEPs(
+; CHECK-SAME: ptr [[DM:%.*]], i1 [[ARG4:%.*]], i64 [[ARG9:%.*]], i64 [[ARG19:%.*]]) {
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[DM]], align 8
+; CHECK-NEXT:    br i1 [[ARG4]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP0:%.*]] = trunc i64 [[ARG9]] to i20
+; CHECK-NEXT:    [[TMP10:%.*]] = getelementptr inbounds [[STRUCT2:%.*]], ptr [[TMP1]], i20 [[TMP0]]
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[ARG19]] to i20
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [[STRUCT2]], ptr [[TMP1]], i20 [[TMP2]]
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[TMP10]], [[BB1]] ], [ [[TMP4]], [[BB2]] ]
+; CHECK-NEXT:    [[TMP25:%.*]] = load i32, ptr [[PHI]], align 4
+; CHECK-NEXT:    ret i32 [[TMP25]]
+;
+bb:
+  %0 = load ptr, ptr %dm, align 8
+  br i1 %arg4, label %bb1, label %bb2
+
+bb1:
+  %1 = getelementptr inbounds %struct, ptr %0, i64 %arg9
+  br label %bb3
+
+bb2:
+  %2 = getelementptr inbounds %struct, ptr %0, i64 %arg19
+  br label %bb3
+
+bb3:
+  %phi = phi ptr [ %1, %bb1 ], [ %2, %bb2 ]
+  %3 = load i32, ptr %phi, align 4
+  ret i32 %3
+}