[llvm] [LLVM][IR] When evaluating GEP offsets don't assume ConstantInt is a scalar. (PR #117162)

Paul Walker via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 21 09:15:02 PST 2024


https://github.com/paulwalker-arm updated https://github.com/llvm/llvm-project/pull/117162

>From 1e78b2fea60d3740f3c0624ef1a1d80512562027 Mon Sep 17 00:00:00 2001
From: Paul Walker <paul.walker at arm.com>
Date: Tue, 19 Nov 2024 12:48:44 +0000
Subject: [PATCH] [LLVM][IR] When evaluating GEP offsets don't assume
 ConstantInt is a scalar.

---
 llvm/lib/Analysis/ConstantFolding.cpp                  | 2 +-
 llvm/lib/IR/Operator.cpp                               | 9 ++++++---
 llvm/test/Transforms/GVN/opaque-ptr.ll                 | 9 +++++++++
 llvm/test/Transforms/InstCombine/gep-vector-indices.ll | 1 +
 llvm/test/Transforms/InstSimplify/gep.ll               | 1 +
 5 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 1971c28fc4c4de..47b96e00c7765a 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -881,7 +881,7 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
   Type *IntIdxTy = DL.getIndexType(Ptr->getType());
 
   for (unsigned i = 1, e = Ops.size(); i != e; ++i)
-    if (!isa<ConstantInt>(Ops[i]))
+    if (!isa<ConstantInt>(Ops[i]) || !Ops[i]->getType()->isIntegerTy())
       return nullptr;
 
   unsigned BitWidth = DL.getTypeSizeInBits(IntIdxTy);
diff --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp
index 199eb4d90f5565..24aeb5003b6094 100644
--- a/llvm/lib/IR/Operator.cpp
+++ b/llvm/lib/IR/Operator.cpp
@@ -126,7 +126,8 @@ bool GEPOperator::accumulateConstantOffset(
     APInt &Offset, function_ref<bool(Value &, APInt &)> ExternalAnalysis) {
   // Fast path for canonical getelementptr i8 form.
   if (SourceType->isIntegerTy(8) && !ExternalAnalysis) {
-    if (auto *CI = dyn_cast<ConstantInt>(Index.front())) {
+    auto *CI = dyn_cast<ConstantInt>(Index.front());
+    if (CI && CI->getType()->isIntegerTy()) {
       Offset += CI->getValue().sextOrTrunc(Offset.getBitWidth());
       return true;
     }
@@ -163,7 +164,8 @@ bool GEPOperator::accumulateConstantOffset(
     Value *V = GTI.getOperand();
     StructType *STy = GTI.getStructTypeOrNull();
     // Handle ConstantInt if possible.
-    if (auto ConstOffset = dyn_cast<ConstantInt>(V)) {
+    auto *ConstOffset = dyn_cast<ConstantInt>(V);
+    if (ConstOffset && ConstOffset->getType()->isIntegerTy()) {
       if (ConstOffset->isZero())
         continue;
       // if the type is scalable and the constant is not zero (vscale * n * 0 =
@@ -222,7 +224,8 @@ bool GEPOperator::collectOffset(
     Value *V = GTI.getOperand();
     StructType *STy = GTI.getStructTypeOrNull();
     // Handle ConstantInt if possible.
-    if (auto ConstOffset = dyn_cast<ConstantInt>(V)) {
+    auto *ConstOffset = dyn_cast<ConstantInt>(V);
+    if (ConstOffset && ConstOffset->getType()->isIntegerTy()) {
       if (ConstOffset->isZero())
         continue;
       // If the type is scalable and the constant is not zero (vscale * n * 0 =
diff --git a/llvm/test/Transforms/GVN/opaque-ptr.ll b/llvm/test/Transforms/GVN/opaque-ptr.ll
index 4a0f9d319501c8..8a7e4205848598 100644
--- a/llvm/test/Transforms/GVN/opaque-ptr.ll
+++ b/llvm/test/Transforms/GVN/opaque-ptr.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt -S -passes=gvn < %s | FileCheck %s
+; RUN: opt -S -passes=gvn -use-constant-int-for-fixed-length-splat < %s | FileCheck %s
 
 declare void @use(ptr)
 declare void @use.i32(i32)
@@ -58,6 +59,10 @@ define void @gep_cse_offset_canonicalization(ptr %p, i64 %idx, i64 %idx2) {
 ; CHECK-NEXT:    call void @use(ptr [[GEP6]])
 ; CHECK-NEXT:    call void @use(ptr [[GEP6_SAME]])
 ; CHECK-NEXT:    call void @use(ptr [[GEP6_DIFFERENT]])
+; CHECK-NEXT:    %gep7 = getelementptr <16 x i32>, ptr %p, i64 1
+; CHECK-NEXT:    %gep7.different = getelementptr <16 x i32>, ptr %p, <16 x i64> splat (i64 1)
+; CHECK-NEXT:    call void @use(ptr %gep7)
+; CHECK-NEXT:    call void @use(<16 x ptr> %gep7.different)
 ; CHECK-NEXT:    ret void
 ;
   %gep1 = getelementptr i64, ptr %p, i64 1
@@ -101,6 +106,10 @@ define void @gep_cse_offset_canonicalization(ptr %p, i64 %idx, i64 %idx2) {
   call void @use(ptr %gep6)
   call void @use(ptr %gep6.same)
   call void @use(ptr %gep6.different)
+  %gep7 = getelementptr <16 x i32>, ptr %p, i64 1
+  %gep7.different = getelementptr <16 x i32>, ptr %p, <16 x i64> splat (i64 1)
+  call void @use(ptr %gep7)
+  call void @use(<16 x ptr> %gep7.different)
   ret void
 }
 
diff --git a/llvm/test/Transforms/InstCombine/gep-vector-indices.ll b/llvm/test/Transforms/InstCombine/gep-vector-indices.ll
index e9534e45ec141d..9f33f4e9c206a0 100644
--- a/llvm/test/Transforms/InstCombine/gep-vector-indices.ll
+++ b/llvm/test/Transforms/InstCombine/gep-vector-indices.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt -passes=instcombine %s -S | FileCheck %s
+; RUN: opt -passes=instcombine -use-constant-int-for-fixed-length-splat %s -S | FileCheck %s
 
 define ptr @vector_splat_indices_v2i64_ext0(ptr %a) {
 ; CHECK-LABEL: @vector_splat_indices_v2i64_ext0(
diff --git a/llvm/test/Transforms/InstSimplify/gep.ll b/llvm/test/Transforms/InstSimplify/gep.ll
index b23494fc56aa4e..a330f5cbc92681 100644
--- a/llvm/test/Transforms/InstSimplify/gep.ll
+++ b/llvm/test/Transforms/InstSimplify/gep.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt -S -passes=instsimplify < %s | FileCheck %s
+; RUN: opt -S -passes=instsimplify -use-constant-int-for-fixed-length-splat < %s | FileCheck %s
 
 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
 



More information about the llvm-commits mailing list