Skip to content

Commit

Permalink
Value-number GVNHoist loads by result type as well as pointer address.
Browse files Browse the repository at this point in the history
Avoids merge errors when opaque pointers are loaded into different types.

Reviewed by: jcranmer-intel, hiraditya
Differential Revision: https://reviews.llvm.org/D122521
  • Loading branch information
clin111 committed Mar 30, 2022
1 parent 85eae45 commit c28ce74
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 3 deletions.
8 changes: 5 additions & 3 deletions llvm/lib/Transforms/Scalar/GVNHoist.cpp
Expand Up @@ -124,7 +124,7 @@ using HoistingPointInfo = std::pair<BasicBlock *, SmallVecInsn>;
using HoistingPointList = SmallVector<HoistingPointInfo, 4>;

// A map from a pair of VNs to all the instructions with those VNs.
using VNType = std::pair<unsigned, unsigned>;
using VNType = std::pair<unsigned, uintptr_t>;

using VNtoInsns = DenseMap<VNType, SmallVector<Instruction *, 4>>;

Expand Down Expand Up @@ -159,7 +159,7 @@ using InValuesType =

// An invalid value number Used when inserting a single value number into
// VNtoInsns.
enum : unsigned { InvalidVN = ~2U };
enum : uintptr_t { InvalidVN = ~(uintptr_t)2 };

// Records all scalar instructions candidate for code hoisting.
class InsnInfo {
Expand All @@ -185,7 +185,9 @@ class LoadInfo {
void insert(LoadInst *Load, GVNPass::ValueTable &VN) {
if (Load->isSimple()) {
unsigned V = VN.lookupOrAdd(Load->getPointerOperand());
VNtoLoads[{V, InvalidVN}].push_back(Load);
// With opaque pointers we may have loads from the same pointer with
// different result types, which should be disambiguated.
VNtoLoads[{V, (uintptr_t)Load->getType()}].push_back(Load);
}
}

Expand Down
119 changes: 119 additions & 0 deletions llvm/test/Transforms/GVNHoist/opaque-diff-type.ll
@@ -0,0 +1,119 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -opaque-pointers -passes="gvn-hoist" -S %s | FileCheck %s

; Checks that gvn-hoist does not try to merge loads of the same source pointer
; when the results are different types.

define linkonce_odr void @i16i32(ptr %arg) {
; CHECK-LABEL: @i16i32(
; CHECK-NEXT: bb:
; CHECK-NEXT: br i1 false, label [[BB1:%.*]], label [[BB2:%.*]]
; CHECK: bb1:
; CHECK-NEXT: [[T:%.*]] = load i16, ptr [[ARG:%.*]], align 4
; CHECK-NEXT: br label [[BB2]]
; CHECK: bb2:
; CHECK-NEXT: [[T3:%.*]] = load i32, ptr [[ARG]], align 8
; CHECK-NEXT: ret void
;
bb:
br i1 false, label %bb1, label %bb2

bb1: ; preds = %bb
%t = load i16, ptr %arg, align 4
br label %bb2

bb2: ; preds = %bb1, %bb
%t3 = load i32, ptr %arg, align 8
ret void
}

define linkonce_odr void @i32f32(ptr %arg) {
; CHECK-LABEL: @i32f32(
; CHECK-NEXT: bb:
; CHECK-NEXT: br i1 false, label [[BB1:%.*]], label [[BB2:%.*]]
; CHECK: bb1:
; CHECK-NEXT: [[T:%.*]] = load i32, ptr [[ARG:%.*]], align 4
; CHECK-NEXT: br label [[BB2]]
; CHECK: bb2:
; CHECK-NEXT: [[T3:%.*]] = load float, ptr [[ARG]], align 8
; CHECK-NEXT: ret void
;
bb:
br i1 false, label %bb1, label %bb2

bb1: ; preds = %bb
%t = load i32, ptr %arg, align 4
br label %bb2

bb2: ; preds = %bb1, %bb
%t3 = load float, ptr %arg, align 8
ret void
}

define linkonce_odr void @i64ptr(ptr %arg) {
; CHECK-LABEL: @i64ptr(
; CHECK-NEXT: bb:
; CHECK-NEXT: br i1 false, label [[BB1:%.*]], label [[BB2:%.*]]
; CHECK: bb1:
; CHECK-NEXT: [[T:%.*]] = load i64, ptr [[ARG:%.*]], align 4
; CHECK-NEXT: br label [[BB2]]
; CHECK: bb2:
; CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[ARG]], align 8
; CHECK-NEXT: ret void
;
bb:
br i1 false, label %bb1, label %bb2

bb1: ; preds = %bb
%t = load i64, ptr %arg, align 4
br label %bb2

bb2: ; preds = %bb1, %bb
%t3 = load ptr, ptr %arg, align 8
ret void
}

define linkonce_odr void @ptrptr_diff_aspace(ptr %arg) {
; CHECK-LABEL: @ptrptr_diff_aspace(
; CHECK-NEXT: bb:
; CHECK-NEXT: br i1 false, label [[BB1:%.*]], label [[BB2:%.*]]
; CHECK: bb1:
; CHECK-NEXT: [[T:%.*]] = load ptr addrspace(4), ptr [[ARG:%.*]], align 4
; CHECK-NEXT: br label [[BB2]]
; CHECK: bb2:
; CHECK-NEXT: [[T3:%.*]] = load ptr addrspace(2), ptr [[ARG]], align 8
; CHECK-NEXT: ret void
;
bb:
br i1 false, label %bb1, label %bb2

bb1: ; preds = %bb
%t = load ptr addrspace(4), ptr %arg, align 4
br label %bb2

bb2: ; preds = %bb1, %bb
%t3 = load ptr addrspace(2), ptr %arg, align 8
ret void
}

define linkonce_odr void @ptrptr(ptr %arg) {
; CHECK-LABEL: @ptrptr(
; CHECK-NEXT: bb:
; CHECK-NEXT: [[T3:%.*]] = load ptr, ptr [[ARG:%.*]], align 4
; CHECK-NEXT: br i1 false, label [[BB1:%.*]], label [[BB2:%.*]]
; CHECK: bb1:
; CHECK-NEXT: br label [[BB2]]
; CHECK: bb2:
; CHECK-NEXT: ret void
;
bb:
br i1 false, label %bb1, label %bb2

bb1: ; preds = %bb
%t = load ptr, ptr %arg, align 4
br label %bb2

bb2: ; preds = %bb1, %bb
%t3 = load ptr, ptr %arg, align 8
ret void
}

0 comments on commit c28ce74

Please sign in to comment.