llvm-project/llvm/test/Transforms/GVN/non-integral-pointers.ll
Eli Friedman 11aa3707e3 StoreInst should store Align, not MaybeAlign
This is D77454, except for stores.  All the infrastructure work was done
for loads, so the remaining changes necessary are relatively small.

Differential Revision: https://reviews.llvm.org/D79968
2020-05-15 12:26:58 -07:00

288 lines
14 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -gvn -S < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4"
target triple = "x86_64-unknown-linux-gnu"
define void @f0(i1 %alwaysFalse, i64 %val, i64* %loc) {
; CHECK-LABEL: @f0(
; CHECK-NEXT: entry:
; CHECK-NEXT: store i64 [[VAL:%.*]], i64* [[LOC:%.*]], align 8
; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
; CHECK: neverTaken:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i64* [[LOC]] to i8 addrspace(4)**
; CHECK-NEXT: [[PTR:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)** [[LOC_BC]], align 8
; CHECK-NEXT: store i8 5, i8 addrspace(4)* [[PTR]], align 1
; CHECK-NEXT: ret void
; CHECK: alwaysTaken:
; CHECK-NEXT: ret void
;
entry:
store i64 %val, i64* %loc
br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
neverTaken:
%loc.bc = bitcast i64* %loc to i8 addrspace(4)**
%ptr = load i8 addrspace(4)*, i8 addrspace(4)** %loc.bc
store i8 5, i8 addrspace(4)* %ptr
ret void
alwaysTaken:
ret void
}
define i64 @f1(i1 %alwaysFalse, i8 addrspace(4)* %val, i8 addrspace(4)** %loc) {
; CHECK-LABEL: @f1(
; CHECK-NEXT: entry:
; CHECK-NEXT: store i8 addrspace(4)* [[VAL:%.*]], i8 addrspace(4)** [[LOC:%.*]], align 8
; CHECK-NEXT: br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
; CHECK: neverTaken:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)** [[LOC]] to i64*
; CHECK-NEXT: [[INT:%.*]] = load i64, i64* [[LOC_BC]], align 8
; CHECK-NEXT: ret i64 [[INT]]
; CHECK: alwaysTaken:
; CHECK-NEXT: ret i64 42
;
entry:
store i8 addrspace(4)* %val, i8 addrspace(4)** %loc
br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
neverTaken:
%loc.bc = bitcast i8 addrspace(4)** %loc to i64*
%int = load i64, i64* %loc.bc
ret i64 %int
alwaysTaken:
ret i64 42
}
;; Note: For terseness, we stop using the %alwaysfalse trick for the
;; tests below and just exercise the bits of forwarding logic directly.
declare void @llvm.memset.p4i8.i64(i8 addrspace(4)* nocapture, i8, i64, i1) nounwind
; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)
define i8 addrspace(4)* @neg_forward_memset(i8 addrspace(4)* addrspace(4)* %loc) {
; CHECK-LABEL: @neg_forward_memset(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
; CHECK-NEXT: call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8 7, i64 8, i1 false)
; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], align 8
; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
;
entry:
%loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8 7, i64 8, i1 false)
%ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
ret i8 addrspace(4)* %ref
}
define <1 x i8 addrspace(4)*> @neg_forward_memset_vload(<1 x i8 addrspace(4)*> addrspace(4)* %loc) {
; CHECK-LABEL: @neg_forward_memset_vload(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast <1 x i8 addrspace(4)*> addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
; CHECK-NEXT: call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8 7, i64 8, i1 false)
; CHECK-NEXT: [[REF:%.*]] = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* [[LOC]], align 8
; CHECK-NEXT: ret <1 x i8 addrspace(4)*> [[REF]]
;
entry:
%loc.bc = bitcast <1 x i8 addrspace(4)*> addrspace(4)* %loc to i8 addrspace(4)*
call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8 7, i64 8, i1 false)
%ref = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* %loc
ret <1 x i8 addrspace(4)*> %ref
}
; Can forward since we can do so w/o breaking types
define i8 addrspace(4)* @forward_memset_zero(i8 addrspace(4)* addrspace(4)* %loc) {
; CHECK-LABEL: @forward_memset_zero(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
; CHECK-NEXT: call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8 0, i64 8, i1 false)
; CHECK-NEXT: ret i8 addrspace(4)* null
;
entry:
%loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8 0, i64 8, i1 false)
%ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
ret i8 addrspace(4)* %ref
}
; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)
define i8 addrspace(4)* @neg_forward_store(i8 addrspace(4)* addrspace(4)* %loc) {
; CHECK-LABEL: @neg_forward_store(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i64 addrspace(4)*
; CHECK-NEXT: store i64 5, i64 addrspace(4)* [[LOC_BC]], align 8
; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], align 8
; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
;
entry:
%loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i64 addrspace(4)*
store i64 5, i64 addrspace(4)* %loc.bc
%ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
ret i8 addrspace(4)* %ref
}
define <1 x i8 addrspace(4)*> @neg_forward_store_vload(<1 x i8 addrspace(4)*> addrspace(4)* %loc) {
; CHECK-LABEL: @neg_forward_store_vload(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast <1 x i8 addrspace(4)*> addrspace(4)* [[LOC:%.*]] to i64 addrspace(4)*
; CHECK-NEXT: store i64 5, i64 addrspace(4)* [[LOC_BC]], align 8
; CHECK-NEXT: [[REF:%.*]] = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* [[LOC]], align 8
; CHECK-NEXT: ret <1 x i8 addrspace(4)*> [[REF]]
;
entry:
%loc.bc = bitcast <1 x i8 addrspace(4)*> addrspace(4)* %loc to i64 addrspace(4)*
store i64 5, i64 addrspace(4)* %loc.bc
%ref = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* %loc
ret <1 x i8 addrspace(4)*> %ref
}
; Nulls have known bit patterns, so we can forward
define i8 addrspace(4)* @forward_store_zero(i8 addrspace(4)* addrspace(4)* %loc) {
; CHECK-LABEL: @forward_store_zero(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i64 addrspace(4)*
; CHECK-NEXT: store i64 0, i64 addrspace(4)* [[LOC_BC]], align 8
; CHECK-NEXT: ret i8 addrspace(4)* null
;
entry:
%loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i64 addrspace(4)*
store i64 0, i64 addrspace(4)* %loc.bc
%ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
ret i8 addrspace(4)* %ref
}
; Nulls have known bit patterns, so we can forward
define i8 addrspace(4)* @forward_store_zero2(i8 addrspace(4)* addrspace(4)* %loc) {
; CHECK-LABEL: @forward_store_zero2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i32> addrspace(4)*
; CHECK-NEXT: store <2 x i32> zeroinitializer, <2 x i32> addrspace(4)* [[LOC_BC]], align 8
; CHECK-NEXT: ret i8 addrspace(4)* null
;
entry:
%loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i32> addrspace(4)*
store <2 x i32> zeroinitializer, <2 x i32> addrspace(4)* %loc.bc
%ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
ret i8 addrspace(4)* %ref
}
@NonZeroConstant = constant <4 x i64> <i64 3, i64 3, i64 3, i64 3>
@ZeroConstant = constant <4 x i64> zeroinitializer
; Can't forward as the load might be dead. (Pretend we wrote out the alwaysfalse idiom above.)
define i8 addrspace(4)* @neg_forward_memcopy(i8 addrspace(4)* addrspace(4)* %loc) {
; CHECK-LABEL: @neg_forward_memcopy(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
; CHECK-NEXT: call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8* bitcast (<4 x i64>* @NonZeroConstant to i8*), i64 8, i1 false)
; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], align 8
; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
;
entry:
%loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
%src.bc = bitcast <4 x i64>* @NonZeroConstant to i8*
call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8* %src.bc, i64 8, i1 false)
%ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
ret i8 addrspace(4)* %ref
}
define <1 x i8 addrspace(4)*> @neg_forward_memcpy_vload(<1 x i8 addrspace(4)*> addrspace(4)* %loc) {
; CHECK-LABEL: @neg_forward_memcpy_vload(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast <1 x i8 addrspace(4)*> addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
; CHECK-NEXT: call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8* bitcast (<4 x i64>* @NonZeroConstant to i8*), i64 8, i1 false)
; CHECK-NEXT: [[REF:%.*]] = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* [[LOC]], align 8
; CHECK-NEXT: ret <1 x i8 addrspace(4)*> [[REF]]
;
entry:
%loc.bc = bitcast <1 x i8 addrspace(4)*> addrspace(4)* %loc to i8 addrspace(4)*
%src.bc = bitcast <4 x i64>* @NonZeroConstant to i8*
call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8* %src.bc, i64 8, i1 false)
%ref = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* %loc
ret <1 x i8 addrspace(4)*> %ref
}
; Can forward since we can do so w/o breaking types
; TODO: missed optimization
define i8 addrspace(4)* @forward_memcpy_zero(i8 addrspace(4)* addrspace(4)* %loc) {
; CHECK-LABEL: @forward_memcpy_zero(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
; CHECK-NEXT: call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8* bitcast (<4 x i64>* @ZeroConstant to i8*), i64 8, i1 false)
; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], align 8
; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
;
entry:
%loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
%src.bc = bitcast <4 x i64>* @ZeroConstant to i8*
call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8* %src.bc, i64 8, i1 false)
%ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
ret i8 addrspace(4)* %ref
}
declare void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* nocapture, i8* nocapture, i64, i1) nounwind
; Same as the neg_forward_store cases, but for non defs.
; (Pretend we wrote out the alwaysfalse idiom above.)
define i8 addrspace(4)* @neg_store_clobber(i8 addrspace(4)* addrspace(4)* %loc) {
; CHECK-LABEL: @neg_store_clobber(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i64> addrspace(4)*
; CHECK-NEXT: store <2 x i64> <i64 4, i64 4>, <2 x i64> addrspace(4)* [[LOC_BC]], align 16
; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], i64 1
; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC_OFF]], align 8
; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
;
entry:
%loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i64> addrspace(4)*
store <2 x i64> <i64 4, i64 4>, <2 x i64> addrspace(4)* %loc.bc
%loc.off = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc, i64 1
%ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc.off
ret i8 addrspace(4)* %ref
}
declare void @use(<2 x i64>) inaccessiblememonly
; Same as the neg_forward_store cases, but for non defs.
; (Pretend we wrote out the alwaysfalse idiom above.)
define i8 addrspace(4)* @neg_load_clobber(i8 addrspace(4)* addrspace(4)* %loc) {
; CHECK-LABEL: @neg_load_clobber(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i64> addrspace(4)*
; CHECK-NEXT: [[V:%.*]] = load <2 x i64>, <2 x i64> addrspace(4)* [[LOC_BC]], align 16
; CHECK-NEXT: call void @use(<2 x i64> [[V]])
; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], i64 1
; CHECK-NEXT: [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC_OFF]], align 8
; CHECK-NEXT: ret i8 addrspace(4)* [[REF]]
;
entry:
%loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i64> addrspace(4)*
%v = load <2 x i64>, <2 x i64> addrspace(4)* %loc.bc
call void @use(<2 x i64> %v)
%loc.off = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc, i64 1
%ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc.off
ret i8 addrspace(4)* %ref
}
define i8 addrspace(4)* @store_clobber_zero(i8 addrspace(4)* addrspace(4)* %loc) {
; CHECK-LABEL: @store_clobber_zero(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i64> addrspace(4)*
; CHECK-NEXT: store <2 x i64> zeroinitializer, <2 x i64> addrspace(4)* [[LOC_BC]], align 16
; CHECK-NEXT: [[LOC_OFF:%.*]] = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], i64 1
; CHECK-NEXT: ret i8 addrspace(4)* null
;
entry:
%loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i64> addrspace(4)*
store <2 x i64> zeroinitializer, <2 x i64> addrspace(4)* %loc.bc
%loc.off = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc, i64 1
%ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc.off
ret i8 addrspace(4)* %ref
}