[llvm] 2a1b1f1 - [GVN] Store source element type for GEP expressions

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 11 04:03:38 PST 2022


Author: Nikita Popov
Date: 2022-02-11T13:03:30+01:00
New Revision: 2a1b1f1b1be86732ff345c6f6dbad7c64743a0d5

URL: https://github.com/llvm/llvm-project/commit/2a1b1f1b1be86732ff345c6f6dbad7c64743a0d5
DIFF: https://github.com/llvm/llvm-project/commit/2a1b1f1b1be86732ff345c6f6dbad7c64743a0d5.diff

LOG: [GVN] Store source element type for GEP expressions

To avoid incorrectly merging GEPs with different source types
under opaque pointers.

To avoid increasing the Expression structure size, this reuses the
existing type member. The code does not rely on this to be the
expression result type, it's only used as a disambiguator.

Added: 
    llvm/test/Transforms/GVN/opaque-ptr.ll

Modified: 
    llvm/lib/Transforms/Scalar/GVN.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index c3008a689657..ddfaf9c2c9fb 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -129,6 +129,8 @@ static cl::opt<uint32_t> MaxBBSpeculations(
 struct llvm::GVNPass::Expression {
   uint32_t opcode;
   bool commutative = false;
+  // The type is not necessarily the result type of the expression, it may be
+  // any additional type needed to disambiguate the expression.
   Type *type = nullptr;
   SmallVector<uint32_t, 4> varargs;
 
@@ -310,7 +312,13 @@ struct llvm::gvn::AvailableValueInBlock {
 
 GVNPass::Expression GVNPass::ValueTable::createExpr(Instruction *I) {
   Expression e;
-  e.type = I->getType();
+  // For GEPs, disambiguate based on the source element type, which is not
+  // implied by the result type with opaque pointers. (Conversely, the source
+  // element type together with the operand types does imply the result type.)
+  if (const auto *GEP = dyn_cast<GetElementPtrInst>(I))
+    e.type = GEP->getSourceElementType();
+  else
+    e.type = I->getType();
   e.opcode = I->getOpcode();
   if (const GCRelocateInst *GCR = dyn_cast<GCRelocateInst>(I)) {
     // gc.relocate is 'special' call: its second and third operands are

diff  --git a/llvm/test/Transforms/GVN/opaque-ptr.ll b/llvm/test/Transforms/GVN/opaque-ptr.ll
new file mode 100644
index 000000000000..f382b799b6fb
--- /dev/null
+++ b/llvm/test/Transforms/GVN/opaque-ptr.ll
@@ -0,0 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -gvn -opaque-pointers < %s | FileCheck %s
+
+declare void @use(ptr)
+
+define void @test(ptr %p) {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 1
+; CHECK-NEXT:    [[GEP3:%.*]] = getelementptr i64, ptr [[P]], i64 1
+; CHECK-NEXT:    call void @use(ptr [[GEP1]])
+; CHECK-NEXT:    call void @use(ptr [[GEP1]])
+; CHECK-NEXT:    call void @use(ptr [[GEP3]])
+; CHECK-NEXT:    ret void
+;
+  %gep1 = getelementptr i32, ptr %p, i64 1
+  %gep2 = getelementptr i32, ptr %p, i64 1
+  %gep3 = getelementptr i64, ptr %p, i64 1
+  call void @use(ptr %gep1)
+  call void @use(ptr %gep2)
+  call void @use(ptr %gep3)
+  ret void
+}


        


More information about the llvm-commits mailing list