1 ; RUN: opt -S -early-cse < %s | FileCheck %s 2 3 declare void @clobber_and_use(i32) 4 5 define void @f_0(i32* %ptr) { 6 ; CHECK-LABEL: @f_0( 7 ; CHECK: %val0 = load i32, i32* %ptr, !invariant.load !0 8 ; CHECK: call void @clobber_and_use(i32 %val0) 9 ; CHECK: call void @clobber_and_use(i32 %val0) 10 ; CHECK: call void @clobber_and_use(i32 %val0) 11 ; CHECK: ret void 12 13 %val0 = load i32, i32* %ptr, !invariant.load !{} 14 call void @clobber_and_use(i32 %val0) 15 %val1 = load i32, i32* %ptr, !invariant.load !{} 16 call void @clobber_and_use(i32 %val1) 17 %val2 = load i32, i32* %ptr, !invariant.load !{} 18 call void @clobber_and_use(i32 %val2) 19 ret void 20 } 21 22 define void @f_1(i32* %ptr) { 23 ; We can forward invariant loads to non-invariant loads, since once an 24 ; invariant load has executed, the location loaded from is known to be 25 ; unchanging. 26 27 ; CHECK-LABEL: @f_1( 28 ; CHECK: %val0 = load i32, i32* %ptr, !invariant.load !0 29 ; CHECK: call void @clobber_and_use(i32 %val0) 30 ; CHECK: call void @clobber_and_use(i32 %val0) 31 32 %val0 = load i32, i32* %ptr, !invariant.load !{} 33 call void @clobber_and_use(i32 %val0) 34 %val1 = load i32, i32* %ptr 35 call void @clobber_and_use(i32 %val1) 36 ret void 37 } 38 39 define void @f_2(i32* %ptr) { 40 ; Negative test -- we can't forward a non-invariant load into an 41 ; invariant load. 42 43 ; CHECK-LABEL: @f_2( 44 ; CHECK: %val0 = load i32, i32* %ptr 45 ; CHECK: call void @clobber_and_use(i32 %val0) 46 ; CHECK: %val1 = load i32, i32* %ptr, !invariant.load !0 47 ; CHECK: call void @clobber_and_use(i32 %val1) 48 49 %val0 = load i32, i32* %ptr 50 call void @clobber_and_use(i32 %val0) 51 %val1 = load i32, i32* %ptr, !invariant.load !{} 52 call void @clobber_and_use(i32 %val1) 53 ret void 54 } 55 56 define void @f_3(i1 %cond, i32* %ptr) { 57 ; CHECK-LABEL: @f_3( 58 %val0 = load i32, i32* %ptr, !invariant.load !{} 59 call void @clobber_and_use(i32 %val0) 60 br i1 %cond, label %left, label %right 61 62 ; CHECK: %val0 = load i32, i32* %ptr, !invariant.load !0 63 ; CHECK: left: 64 ; CHECK-NEXT: call void @clobber_and_use(i32 %val0) 65 66 left: 67 %val1 = load i32, i32* %ptr 68 call void @clobber_and_use(i32 %val1) 69 ret void 70 71 right: 72 ret void 73 } 74 75 define void @f_4(i1 %cond, i32* %ptr) { 76 ; Negative test -- can't forward %val0 to %va1 because that'll break 77 ; def-dominates-use. 78 79 ; CHECK-LABEL: @f_4( 80 br i1 %cond, label %left, label %merge 81 82 left: 83 ; CHECK: left: 84 ; CHECK-NEXT: %val0 = load i32, i32* %ptr, !invariant.load ! 85 ; CHECK-NEXT: call void @clobber_and_use(i32 %val0) 86 87 %val0 = load i32, i32* %ptr, !invariant.load !{} 88 call void @clobber_and_use(i32 %val0) 89 br label %merge 90 91 merge: 92 ; CHECK: merge: 93 ; CHECK-NEXT: %val1 = load i32, i32* %ptr 94 ; CHECK-NEXT: call void @clobber_and_use(i32 %val1) 95 96 %val1 = load i32, i32* %ptr 97 call void @clobber_and_use(i32 %val1) 98 ret void 99 } 100