Value-number GVNHoist loads by result type as well as pointer address.

Avoids merge errors when opaque pointers are loaded into different types.

Reviewed by: jcranmer-intel, hiraditya
Differential Revision: https://reviews.llvm.org/D122521
This commit is contained in:
Chang-Sun Lin Jr 2022-03-30 11:31:17 -07:00
parent 85eae45520
commit c28ce745cf
2 changed files with 124 additions and 3 deletions

View File

@ -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>>;
@ -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 {
@ -185,7 +185,9 @@ public:
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);
}
}

View File

@ -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
}