From: Nikita Popov Date: Fri, 11 Feb 2022 12:01:17 +0000 (+0100) Subject: [GVN] Store source element type for GEP expressions X-Git-Tag: upstream/15.0.7~16876 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2a1b1f1b1be86732ff345c6f6dbad7c64743a0d5;p=platform%2Fupstream%2Fllvm.git [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. --- diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index c3008a6..ddfaf9c 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -129,6 +129,8 @@ static cl::opt 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 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(I)) + e.type = GEP->getSourceElementType(); + else + e.type = I->getType(); e.opcode = I->getOpcode(); if (const GCRelocateInst *GCR = dyn_cast(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 0000000..f382b79 --- /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 +}