460 lines · plain
1; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<target-ir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s2 3define void @test(ptr %loc) {4; CHECK-LABEL: @test5; CHECK-LABEL: entry:6; CHECK: store i32 0, ptr %loc7; CHECK-LABEL: loop:8entry:9 br label %loop10 11loop:12 %iv = phi i32 [0, %entry], [%iv.next, %loop]13 store i32 0, ptr %loc14 %iv.next = add i32 %iv, 115 %cmp = icmp slt i32 %iv, 20016 br i1 %cmp, label %loop, label %exit17 18exit:19 ret void20}21 22define void @test_multiexit(ptr %loc, i1 %earlycnd) {23; CHECK-LABEL: @test_multiexit24; CHECK-LABEL: entry:25; CHECK: store i32 0, ptr %loc26; CHECK-LABEL: loop:27entry:28 br label %loop29 30loop:31 %iv = phi i32 [0, %entry], [%iv.next, %backedge]32 store i32 0, ptr %loc33 %iv.next = add i32 %iv, 134 br i1 %earlycnd, label %exit1, label %backedge35 36backedge:37 %cmp = icmp slt i32 %iv, 20038 br i1 %cmp, label %loop, label %exit239 40exit1:41 ret void42exit2:43 ret void44}45 46define ptr @false_negative_2use(ptr %loc) {47; CHECK-LABEL: @false_negative_2use48; CHECK-LABEL: entry:49; CHECK: store i32 0, ptr %loc50; CHECK-LABEL: loop:51entry:52 br label %loop53 54loop:55 %iv = phi i32 [0, %entry], [%iv.next, %loop]56 store i32 0, ptr %loc57 %iv.next = add i32 %iv, 158 %cmp = icmp slt i32 %iv, 20059 br i1 %cmp, label %loop, label %exit60 61exit:62 ret ptr %loc63}64 65define void @neg_lv_value(ptr %loc) {66; CHECK-LABEL: @neg_lv_value67; CHECK-LABEL: exit:68; CHECK: store i32 %iv.lcssa, ptr %loc69entry:70 br label %loop71 72loop:73 %iv = phi i32 [0, %entry], [%iv.next, %loop]74 store i32 %iv, ptr %loc75 %iv.next = add i32 %iv, 176 %cmp = icmp slt i32 %iv, 20077 br i1 %cmp, label %loop, label %exit78 79exit:80 ret void81}82 83define void @neg_lv_addr(ptr %loc) {84; CHECK-LABEL: @neg_lv_addr85; CHECK-LABEL: loop:86; CHECK: store i32 0, ptr %p87; CHECK-LABEL: exit:88entry:89 br label %loop90 91loop:92 %iv = phi i32 [0, %entry], [%iv.next, %loop]93 %p = getelementptr i32, ptr %loc, i32 %iv94 store i32 0, ptr %p95 %iv.next = add i32 %iv, 196 %cmp = icmp slt i32 %iv, 20097 br i1 %cmp, label %loop, label %exit98 99exit:100 ret void101}102 103define void @neg_mod(ptr %loc) {104; CHECK-LABEL: @neg_mod105; CHECK-LABEL: exit:106; CHECK: store i32 %iv.lcssa, ptr %loc107entry:108 br label %loop109 110loop:111 %iv = phi i32 [0, %entry], [%iv.next, %loop]112 store i32 0, ptr %loc113 store i32 %iv, ptr %loc114 %iv.next = add i32 %iv, 1115 %cmp = icmp slt i32 %iv, 200116 br i1 %cmp, label %loop, label %exit117 118exit:119 ret void120}121 122; Hoisting the store is actually valid here, as it dominates the load.123define void @neg_ref(ptr %loc) {124; CHECK-LABEL: @neg_ref125; CHECK-LABEL: exit1:126; CHECK: store i32 0, ptr %loc127; CHECK-LABEL: exit2:128; CHECK: store i32 0, ptr %loc129entry:130 br label %loop131 132loop:133 %iv = phi i32 [0, %entry], [%iv.next, %backedge]134 store i32 0, ptr %loc135 %v = load i32, ptr %loc136 %earlycnd = icmp eq i32 %v, 198137 br i1 %earlycnd, label %exit1, label %backedge138 139backedge:140 %iv.next = add i32 %iv, 1141 %cmp = icmp slt i32 %iv, 200142 br i1 %cmp, label %loop, label %exit2143 144exit1:145 ret void146exit2:147 ret void148}149 150; Hoisting the store here leads to a miscompile.151define void @neg_ref2(ptr %loc) {152; CHECK-LABEL: @neg_ref2153; CHECK-LABEL: exit1:154; CHECK: store i32 0, ptr %loc155; CHECK-LABEL: exit2:156; CHECK: store i32 0, ptr %loc157entry:158 store i32 198, ptr %loc159 br label %loop160 161loop:162 %iv = phi i32 [0, %entry], [%iv.next, %backedge]163 %v = load i32, ptr %loc164 store i32 0, ptr %loc165 %earlycnd = icmp eq i32 %v, 198166 br i1 %earlycnd, label %exit1, label %backedge167 168backedge:169 %iv.next = add i32 %iv, 1170 %cmp = icmp slt i32 %iv, 200171 br i1 %cmp, label %loop, label %exit2172 173exit1:174 ret void175exit2:176 ret void177}178 179declare void @modref()180 181define void @neg_modref(ptr %loc) {182; CHECK-LABEL: @neg_modref183; CHECK-LABEL: loop:184; CHECK: store i32 0, ptr %loc185; CHECK-LABEL: exit:186entry:187 br label %loop188 189loop:190 %iv = phi i32 [0, %entry], [%iv.next, %loop]191 store i32 0, ptr %loc192 call void @modref()193 %iv.next = add i32 %iv, 1194 %cmp = icmp slt i32 %iv, 200195 br i1 %cmp, label %loop, label %exit196 197exit:198 ret void199}200 201define void @neg_fence(ptr %loc) {202; CHECK-LABEL: @neg_fence203; CHECK-LABEL: loop:204; CHECK: store i32 0, ptr %loc205; CHECK-LABEL: exit:206entry:207 br label %loop208 209loop:210 %iv = phi i32 [0, %entry], [%iv.next, %loop]211 store i32 0, ptr %loc212 fence seq_cst213 %iv.next = add i32 %iv, 1214 %cmp = icmp slt i32 %iv, 200215 br i1 %cmp, label %loop, label %exit216 217exit:218 ret void219}220 221define void @neg_volatile(ptr %loc) {222; CHECK-LABEL: @neg_volatile223; CHECK-LABEL: loop:224; CHECK: store volatile i32 0, ptr %loc225; CHECK-LABEL: exit:226entry:227 br label %loop228 229loop:230 %iv = phi i32 [0, %entry], [%iv.next, %loop]231 store volatile i32 0, ptr %loc232 %iv.next = add i32 %iv, 1233 %cmp = icmp slt i32 %iv, 200234 br i1 %cmp, label %loop, label %exit235 236exit:237 ret void238}239 240define void @neg_release(ptr %loc) {241; CHECK-LABEL: @neg_release242; CHECK-LABEL: loop:243; CHECK: store atomic i32 0, ptr %loc release, align 4244; CHECK-LABEL: exit:245entry:246 br label %loop247 248loop:249 %iv = phi i32 [0, %entry], [%iv.next, %loop]250 store atomic i32 0, ptr %loc release, align 4251 %iv.next = add i32 %iv, 1252 %cmp = icmp slt i32 %iv, 200253 br i1 %cmp, label %loop, label %exit254 255exit:256 ret void257}258 259define void @neg_seq_cst(ptr %loc) {260; CHECK-LABEL: @neg_seq_cst261; CHECK-LABEL: loop:262; CHECK: store atomic i32 0, ptr %loc seq_cst, align 4263; CHECK-LABEL: exit:264entry:265 br label %loop266 267loop:268 %iv = phi i32 [0, %entry], [%iv.next, %loop]269 store atomic i32 0, ptr %loc seq_cst, align 4270 %iv.next = add i32 %iv, 1271 %cmp = icmp slt i32 %iv, 200272 br i1 %cmp, label %loop, label %exit273 274exit:275 ret void276}277 278declare void @maythrow() inaccessiblememonly279 280define void @neg_early_exit(ptr %loc) {281; CHECK-LABEL: @neg_early_exit282; CHECK-LABEL: body:283; CHECK: store i32 0, ptr %loc284; CHECK-LABEL: exit:285entry:286 br label %loop287 288loop:289 %iv = phi i32 [0, %entry], [%iv.next, %body]290 %is_null = icmp eq ptr %loc, null291 br i1 %is_null, label %exit, label %body292body:293 call void @maythrow()294 store i32 0, ptr %loc295 %iv.next = add i32 %iv, 1296 %cmp = icmp slt i32 %iv, 200297 br i1 %cmp, label %loop, label %exit298 299exit:300 ret void301}302 303define void @neg_early_throw(ptr %loc) {304; CHECK-LABEL: @neg_early_throw305; CHECK-LABEL: loop:306; CHECK: store i32 0, ptr %loc307; CHECK-LABEL: exit:308entry:309 br label %loop310 311loop:312 %iv = phi i32 [0, %entry], [%iv.next, %loop]313 call void @maythrow()314 store i32 0, ptr %loc315 %iv.next = add i32 %iv, 1316 %cmp = icmp slt i32 %iv, 200317 br i1 %cmp, label %loop, label %exit318 319exit:320 ret void321}322 323define void @test_late_throw(ptr %loc) {324; CHECK-LABEL: @test_late_throw325; CHECK-LABEL: entry:326; CHECK: store i32 0, ptr %loc327; CHECK-LABEL: loop:328entry:329 br label %loop330 331loop:332 %iv = phi i32 [0, %entry], [%iv.next, %loop]333 store i32 0, ptr %loc334 call void @maythrow()335 %iv.next = add i32 %iv, 1336 %cmp = icmp slt i32 %iv, 200337 br i1 %cmp, label %loop, label %exit338 339exit:340 ret void341}342 343; TODO: could validly hoist the store here since we know what value344; the load must observe.345define i32 @test_dominated_read(ptr %loc) {346; CHECK-LABEL: @test_dominated_read347; CHECK-LABEL: entry:348; CHECK: store i32 0, ptr %loc349; CHECK-LABEL: loop:350entry:351 br label %loop352 353loop:354 %iv = phi i32 [0, %entry], [%iv.next, %loop]355 store i32 0, ptr %loc356 %reload = load i32, ptr %loc357 %iv.next = add i32 %iv, 1358 %cmp = icmp slt i32 %iv, 200359 br i1 %cmp, label %loop, label %exit360 361exit:362 ret i32 %reload363}364 365; TODO: could validly hoist the store since we already hoisted the load and366; it's no longer in the loop.367define i32 @test_dominating_read(ptr %loc) {368; CHECK-LABEL: @test_dominating_read369; CHECK-LABEL: exit:370; CHECK: store i32 0, ptr %loc371entry:372 br label %loop373 374loop:375 %iv = phi i32 [0, %entry], [%iv.next, %loop]376 %reload = load i32, ptr %loc377 store i32 0, ptr %loc378 %iv.next = add i32 %iv, 1379 %cmp = icmp slt i32 %iv, 200380 br i1 %cmp, label %loop, label %exit381 382exit:383 ret i32 %reload384}385 386declare void @readonly() readonly387 388; TODO: can legally hoist since value read by call is known389define void @test_dominated_readonly(ptr %loc) {390; CHECK-LABEL: @test_dominated_readonly391; CHECK-LABEL: loop:392; CHECK: store i32 0, ptr %loc393; CHECK-LABEL: exit:394entry:395 br label %loop396 397loop:398 %iv = phi i32 [0, %entry], [%iv.next, %loop]399 store i32 0, ptr %loc400 call void @readonly()401 %iv.next = add i32 %iv, 1402 %cmp = icmp slt i32 %iv, 200403 br i1 %cmp, label %loop, label %exit404 405exit:406 ret void407}408 409; While technically possible to hoist the store to %loc, this runs across410; a funemental limitation of alias sets since both stores and the call are411; within the same alias set and we can't distinguish them cheaply.412define void @test_aliasset_fn(ptr %loc, ptr %loc2) {413; CHECK-LABEL: @test_aliasset_fn414; CHECK-LABEL: loop:415; CHECK: store i32 0, ptr %loc416; CHECK-LABEL: exit:417entry:418 br label %loop419 420loop:421 %iv = phi i32 [0, %entry], [%iv.next, %loop]422 store i32 0, ptr %loc423 call void @readonly()424 store i32 %iv, ptr %loc2425 %iv.next = add i32 %iv, 1426 %cmp = icmp slt i32 %iv, 200427 br i1 %cmp, label %loop, label %exit428 429exit:430 ret void431}432 433 434; If we can't tell if the value is read before the write, we can't hoist the435; write over the potential read (since we don't know the value read)436define void @neg_may_read(ptr %loc, i1 %maybe) {437; CHECK-LABEL: @neg_may_read438; CHECK-LABEL: loop:439; CHECK: store i32 0, ptr %loc440; CHECK-LABEL: exit:441entry:442 br label %loop443 444loop:445 %iv = phi i32 [0, %entry], [%iv.next, %merge]446 ;; maybe is a placeholder for an unanalyzable condition447 br i1 %maybe, label %taken, label %merge448taken:449 call void @readonly()450 br label %merge451merge:452 store i32 0, ptr %loc453 %iv.next = add i32 %iv, 1454 %cmp = icmp slt i32 %iv, 200455 br i1 %cmp, label %loop, label %exit456 457exit:458 ret void459}460