1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4@test.data = private unnamed_addr addrspace(2) constant [8 x i32] [i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7], align 4 5 6define void @test_load(ptr addrspace(1) %out, i64 %x) { 7; CHECK-LABEL: @test_load( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i32], ptr addrspace(2) @test.data, i64 0, i64 [[X:%.*]] 10; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(2) [[ARRAYIDX]], align 4 11; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]] 12; CHECK-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4 13; CHECK-NEXT: ret void 14; 15entry: 16 %data = alloca [8 x i32], align 4 17 call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false) 18 %arrayidx = getelementptr inbounds [8 x i32], ptr %data, i64 0, i64 %x 19 %0 = load i32, ptr %arrayidx, align 4 20 %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x 21 store i32 %0, ptr addrspace(1) %arrayidx1, align 4 22 ret void 23} 24 25; Same as previous test, but with gep nusw nuw instead of inbounds. 26define void @test_load_gep_nusw_nuw(ptr addrspace(1) %out, i64 %x) { 27; CHECK-LABEL: @test_load_gep_nusw_nuw( 28; CHECK-NEXT: entry: 29; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr nusw nuw [8 x i32], ptr addrspace(2) @test.data, i64 0, i64 [[X:%.*]] 30; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(2) [[ARRAYIDX]], align 4 31; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr nusw nuw i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]] 32; CHECK-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4 33; CHECK-NEXT: ret void 34; 35entry: 36 %data = alloca [8 x i32], align 4 37 call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false) 38 %arrayidx = getelementptr nusw nuw [8 x i32], ptr %data, i64 0, i64 %x 39 %0 = load i32, ptr %arrayidx, align 4 40 %arrayidx1 = getelementptr nusw nuw i32, ptr addrspace(1) %out, i64 %x 41 store i32 %0, ptr addrspace(1) %arrayidx1, align 4 42 ret void 43} 44 45define void @test_load_bitcast_chain(ptr addrspace(1) %out, i64 %x) { 46; CHECK-LABEL: @test_load_bitcast_chain( 47; CHECK-NEXT: entry: 48; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr addrspace(2) @test.data, i64 [[X:%.*]] 49; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(2) [[ARRAYIDX]], align 4 50; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]] 51; CHECK-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4 52; CHECK-NEXT: ret void 53; 54entry: 55 %data = alloca [8 x i32], align 4 56 call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false) 57 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %x 58 %0 = load i32, ptr %arrayidx, align 4 59 %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x 60 store i32 %0, ptr addrspace(1) %arrayidx1, align 4 61 ret void 62} 63 64define void @test_call(ptr addrspace(1) %out, i64 %x) { 65; CHECK-LABEL: @test_call( 66; CHECK-NEXT: entry: 67; CHECK-NEXT: [[DATA:%.*]] = alloca [8 x i32], align 4 68; CHECK-NEXT: call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 4 dereferenceable(32) [[DATA]], ptr addrspace(2) noundef align 4 dereferenceable(32) @test.data, i64 32, i1 false) 69; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i32], ptr [[DATA]], i64 0, i64 [[X:%.*]] 70; CHECK-NEXT: [[TMP0:%.*]] = call i32 @foo(ptr nonnull [[ARRAYIDX]]) 71; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]] 72; CHECK-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4 73; CHECK-NEXT: ret void 74; 75entry: 76 %data = alloca [8 x i32], align 4 77 call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false) 78 %arrayidx = getelementptr inbounds [8 x i32], ptr %data, i64 0, i64 %x 79 %0 = call i32 @foo(ptr %arrayidx) 80 %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x 81 store i32 %0, ptr addrspace(1) %arrayidx1, align 4 82 ret void 83} 84 85define void @test_call_no_null_opt(ptr addrspace(1) %out, i64 %x) #0 { 86; CHECK-LABEL: @test_call_no_null_opt( 87; CHECK-NEXT: entry: 88; CHECK-NEXT: [[DATA:%.*]] = alloca [8 x i32], align 4 89; CHECK-NEXT: call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 4 dereferenceable(32) [[DATA]], ptr addrspace(2) noundef align 4 dereferenceable(32) @test.data, i64 32, i1 false) 90; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i32], ptr [[DATA]], i64 0, i64 [[X:%.*]] 91; CHECK-NEXT: [[TMP0:%.*]] = call i32 @foo(ptr [[ARRAYIDX]]) 92; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]] 93; CHECK-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4 94; CHECK-NEXT: ret void 95; 96entry: 97 %data = alloca [8 x i32], align 4 98 call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false) 99 %arrayidx = getelementptr inbounds [8 x i32], ptr %data, i64 0, i64 %x 100 %0 = call i32 @foo(ptr %arrayidx) 101 %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x 102 store i32 %0, ptr addrspace(1) %arrayidx1, align 4 103 ret void 104} 105 106define void @test_load_and_call(ptr addrspace(1) %out, i64 %x, i64 %y) { 107; CHECK-LABEL: @test_load_and_call( 108; CHECK-NEXT: entry: 109; CHECK-NEXT: [[DATA:%.*]] = alloca [8 x i32], align 4 110; CHECK-NEXT: call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 4 dereferenceable(32) [[DATA]], ptr addrspace(2) noundef align 4 dereferenceable(32) @test.data, i64 32, i1 false) 111; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i32], ptr [[DATA]], i64 0, i64 [[X:%.*]] 112; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 113; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]] 114; CHECK-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4 115; CHECK-NEXT: [[TMP1:%.*]] = call i32 @foo(ptr nonnull [[ARRAYIDX]]) 116; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT]], i64 [[Y:%.*]] 117; CHECK-NEXT: store i32 [[TMP1]], ptr addrspace(1) [[ARRAYIDX2]], align 4 118; CHECK-NEXT: ret void 119; 120entry: 121 %data = alloca [8 x i32], align 4 122 call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false) 123 %arrayidx = getelementptr inbounds [8 x i32], ptr %data, i64 0, i64 %x 124 %0 = load i32, ptr %arrayidx, align 4 125 %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x 126 store i32 %0, ptr addrspace(1) %arrayidx1, align 4 127 %1 = call i32 @foo(ptr %arrayidx) 128 %arrayidx2 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %y 129 store i32 %1, ptr addrspace(1) %arrayidx2, align 4 130 ret void 131} 132 133define void @test_load_and_call_no_null_opt(ptr addrspace(1) %out, i64 %x, i64 %y) #0 { 134; CHECK-LABEL: @test_load_and_call_no_null_opt( 135; CHECK-NEXT: entry: 136; CHECK-NEXT: [[DATA:%.*]] = alloca [8 x i32], align 4 137; CHECK-NEXT: call void @llvm.memcpy.p0.p2.i64(ptr noundef nonnull align 4 dereferenceable(32) [[DATA]], ptr addrspace(2) noundef align 4 dereferenceable(32) @test.data, i64 32, i1 false) 138; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [8 x i32], ptr [[DATA]], i64 0, i64 [[X:%.*]] 139; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 140; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT:%.*]], i64 [[X]] 141; CHECK-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[ARRAYIDX1]], align 4 142; CHECK-NEXT: [[TMP1:%.*]] = call i32 @foo(ptr [[ARRAYIDX]]) 143; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[OUT]], i64 [[Y:%.*]] 144; CHECK-NEXT: store i32 [[TMP1]], ptr addrspace(1) [[ARRAYIDX2]], align 4 145; CHECK-NEXT: ret void 146; 147entry: 148 %data = alloca [8 x i32], align 4 149 call void @llvm.memcpy.p0.p2.i64(ptr align 4 %data, ptr addrspace(2) align 4 @test.data, i64 32, i1 false) 150 %arrayidx = getelementptr inbounds [8 x i32], ptr %data, i64 0, i64 %x 151 %0 = load i32, ptr %arrayidx, align 4 152 %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %x 153 store i32 %0, ptr addrspace(1) %arrayidx1, align 4 154 %1 = call i32 @foo(ptr %arrayidx) 155 %arrayidx2 = getelementptr inbounds i32, ptr addrspace(1) %out, i64 %y 156 store i32 %1, ptr addrspace(1) %arrayidx2, align 4 157 ret void 158} 159 160declare void @llvm.memcpy.p0.p2.i64(ptr nocapture writeonly, ptr addrspace(2) nocapture readonly, i64, i1) 161declare i32 @foo(ptr %x) 162 163attributes #0 = { null_pointer_is_valid } 164