1; RUN: opt -S -early-cse < %s | FileCheck %s 2 3declare void @clobber_and_use(i32) 4 5define 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 22define 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 39define 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 56define 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 66left: 67 %val1 = load i32, i32* %ptr 68 call void @clobber_and_use(i32 %val1) 69 ret void 70 71right: 72 ret void 73} 74 75define 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 82left: 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 91merge: 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