210 lines · plain
1; RUN: opt -mtriple=nvptx64-nvidia-cuda -passes=load-store-vectorizer -S -o - %s | FileCheck %s2 3; Check that the load/store vectorizer is willing to move loads/stores across4; intervening instructions only if it's safe.5;6; - Loads can be moved across instructions that don't write or throw.7; - Stores can only be moved across instructions which don't read, write, or8; throw.9 10declare void @fn()11declare void @fn_nounwind() #012declare void @fn_nounwind_writeonly() #113declare void @fn_nounwind_readonly() #214declare void @fn_writeonly() #315declare void @fn_readonly() #416declare void @fn_readnone() #517 18; CHECK-LABEL: @load_fn19; CHECK: load20; CHECK: call void @fn()21; CHECK: load22define void @load_fn(ptr %p) #0 {23 %p.1 = getelementptr i32, ptr %p, i32 124 25 %v0 = load i32, ptr %p, align 826 call void @fn()27 %v1 = load i32, ptr %p.1, align 428 ret void29}30 31; CHECK-LABEL: @load_fn_nounwind32; CHECK: load33; CHECK: call void @fn_nounwind()34; CHECK: load35define void @load_fn_nounwind(ptr %p) #0 {36 %p.1 = getelementptr i32, ptr %p, i32 137 38 %v0 = load i32, ptr %p, align 839 call void @fn_nounwind() #040 %v1 = load i32, ptr %p.1, align 441 ret void42}43 44; CHECK-LABEL: @load_fn_nounwind_writeonly45; CHECK: load46; CHECK: call void @fn_nounwind_writeonly()47; CHECK: load48define void @load_fn_nounwind_writeonly(ptr %p) #0 {49 %p.1 = getelementptr i32, ptr %p, i32 150 51 %v0 = load i32, ptr %p, align 852 call void @fn_nounwind_writeonly() #153 %v1 = load i32, ptr %p.1, align 454 ret void55}56 57; CHECK-LABEL: @load_fn_nounwind_readonly58; CHECK-DAG: load <2 x i32>59; CHECK-DAG: call void @fn_nounwind_readonly()60define void @load_fn_nounwind_readonly(ptr %p) #0 {61 %p.1 = getelementptr i32, ptr %p, i32 162 63 %v0 = load i32, ptr %p, align 864 call void @fn_nounwind_readonly() #265 %v1 = load i32, ptr %p.1, align 466 ret void67}68 69; CHECK-LABEL: @load_fn_readonly70; CHECK: load71; CHECK: call void @fn_readonly72; CHECK: load73define void @load_fn_readonly(ptr %p) #0 {74 %p.1 = getelementptr i32, ptr %p, i32 175 76 %v0 = load i32, ptr %p, align 877 call void @fn_readonly() #478 %v1 = load i32, ptr %p.1, align 479 ret void80}81 82; CHECK-LABEL: @load_fn_writeonly83; CHECK: load84; CHECK: call void @fn_writeonly()85; CHECK: load86define void @load_fn_writeonly(ptr %p) #0 {87 %p.1 = getelementptr i32, ptr %p, i32 188 89 %v0 = load i32, ptr %p, align 890 call void @fn_writeonly() #391 %v1 = load i32, ptr %p.1, align 492 ret void93}94 95; CHECK-LABEL: @load_fn_readnone96; CHECK-DAG: load <2 x i32>97; CHECK-DAG: call void @fn_readnone()98define void @load_fn_readnone(ptr %p) #0 {99 %p.1 = getelementptr i32, ptr %p, i32 1100 101 %v0 = load i32, ptr %p, align 8102 call void @fn_readnone() #5103 %v1 = load i32, ptr %p.1, align 4104 ret void105}106 107; ------------------------------------------------108; Same tests, but now for stores instead of loads.109; ------------------------------------------------110 111; CHECK-LABEL: @store_fn112; CHECK: store113; CHECK: call void @fn()114; CHECK: store115define void @store_fn(ptr %p) #0 {116 %p.1 = getelementptr i32, ptr %p, i32 1117 118 store i32 0, ptr %p119 call void @fn()120 store i32 0, ptr %p.1121 ret void122}123 124; CHECK-LABEL: @store_fn_nounwind125; CHECK: store126; CHECK: call void @fn_nounwind()127; CHECK: store128define void @store_fn_nounwind(ptr %p) #0 {129 %p.1 = getelementptr i32, ptr %p, i32 1130 131 store i32 0, ptr %p132 call void @fn_nounwind() #0133 store i32 0, ptr %p.1134 ret void135}136 137; CHECK-LABEL: @store_fn_nounwind_writeonly138; CHECK: store139; CHECK: call void @fn_nounwind_writeonly()140; CHECK: store141define void @store_fn_nounwind_writeonly(ptr %p) #0 {142 %p.1 = getelementptr i32, ptr %p, i32 1143 144 store i32 0, ptr %p145 call void @fn_nounwind_writeonly() #1146 store i32 0, ptr %p.1147 ret void148}149 150; CHECK-LABEL: @store_fn_nounwind_readonly151; CHECK: store152; CHECK: call void @fn_nounwind_readonly()153; CHECK: store154define void @store_fn_nounwind_readonly(ptr %p) #0 {155 %p.1 = getelementptr i32, ptr %p, i32 1156 157 store i32 0, ptr %p158 call void @fn_nounwind_readonly() #2159 store i32 0, ptr %p.1160 ret void161}162 163; CHECK-LABEL: @store_fn_readonly164; CHECK: store165; CHECK: call void @fn_readonly166; CHECK: store167define void @store_fn_readonly(ptr %p) #0 {168 %p.1 = getelementptr i32, ptr %p, i32 1169 170 store i32 0, ptr %p171 call void @fn_readonly() #4172 store i32 0, ptr %p.1173 ret void174}175 176; CHECK-LABEL: @store_fn_writeonly177; CHECK: store178; CHECK: call void @fn_writeonly()179; CHECK: store180define void @store_fn_writeonly(ptr %p) #0 {181 %p.1 = getelementptr i32, ptr %p, i32 1182 183 store i32 0, ptr %p184 call void @fn_writeonly() #3185 store i32 0, ptr %p.1186 ret void187}188 189; This is the only store idiom we can vectorize.190; CHECK-LABEL: @store_fn_readnone191; CHECK-DAG: store <2 x i32>192; CHECK-DAG: call void @fn_readnone()193define void @store_fn_readnone(ptr %p) #0 {194 %p.1 = getelementptr i32, ptr %p, i32 1195 196 store i32 0, ptr %p, align 8197 call void @fn_readnone() #5198 store i32 0, ptr %p.1, align 8199 ret void200}201 202 203attributes #0 = { nounwind willreturn }204attributes #1 = { nounwind willreturn writeonly }205attributes #2 = { nounwind readonly willreturn }206attributes #3 = { writeonly }207attributes #4 = { readonly }208; readnone implies nounwind, so no need to test separately209attributes #5 = { nounwind willreturn readnone }210