1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=newgvn -enable-phi-of-ops=true -S -o - %s | FileCheck %s 3 4define void @hoisted-load(ptr %p, ptr %q) { 5; CHECK-LABEL: @hoisted-load( 6; CHECK-NEXT: bb56: 7; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1 8; CHECK-NEXT: br label [[BB57:%.*]] 9; CHECK: bb57: 10; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i1 [ true, [[BB56:%.*]] ], [ [[N62:%.*]], [[BB229:%.*]] ] 11; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229]] ], [ true, [[BB56]] ] 12; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ 0, [[BB56]] ], [ [[INC:%.*]], [[BB229]] ] 13; CHECK-NEXT: [[N62]] = icmp ne i8 [[N60]], 2 14; CHECK-NEXT: br i1 [[PHIOFOPS]], label [[BB229]], label [[BB237:%.*]] 15; CHECK: bb229: 16; CHECK-NEXT: [[INC]] = add i8 [[IDX]], 1 17; CHECK-NEXT: store i8 [[INC]], ptr [[Q:%.*]], align 1 18; CHECK-NEXT: br label [[BB57]] 19; CHECK: bb237: 20; CHECK-NEXT: ret void 21; 22bb56: 23 %n60 = load i8, ptr %p 24 br label %bb57 25 26bb57: 27 %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ] 28 %idx = phi i8 [0, %bb56], [%inc, %bb229] 29 %n62 = icmp ne i8 %n60, 2 30 %n63 = or i1 %n59, %n62 31 br i1 %n63, label %bb229, label %bb237 32 33bb229: 34 %inc = add i8 %idx, 1 35 store i8 %inc, ptr %q 36 br label %bb57 37 38bb237: 39 ret void 40} 41 42define void @store-in-loop(ptr %p, ptr %q) { 43; CHECK-LABEL: @store-in-loop( 44; CHECK-NEXT: bb56: 45; CHECK-NEXT: br label [[BB57:%.*]] 46; CHECK: bb57: 47; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ] 48; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ 0, [[BB56]] ], [ [[INC:%.*]], [[BB229]] ] 49; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1 50; CHECK-NEXT: [[N62:%.*]] = icmp ne i8 [[N60]], 2 51; CHECK-NEXT: [[N63:%.*]] = or i1 [[N59]], [[N62]] 52; CHECK-NEXT: br i1 [[N63]], label [[BB229]], label [[BB237:%.*]] 53; CHECK: bb229: 54; CHECK-NEXT: [[INC]] = add i8 [[IDX]], 1 55; CHECK-NEXT: store i8 [[INC]], ptr [[Q:%.*]], align 1 56; CHECK-NEXT: br label [[BB57]] 57; CHECK: bb237: 58; CHECK-NEXT: ret void 59; 60bb56: 61 br label %bb57 62 63bb57: 64 %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ] 65 %idx = phi i8 [0, %bb56], [%inc, %bb229] 66 %n60 = load i8, ptr %p 67 %n62 = icmp ne i8 %n60, 2 68 %n63 = or i1 %n59, %n62 69 br i1 %n63, label %bb229, label %bb237 70 71bb229: 72 %inc = add i8 %idx, 1 73 store i8 %inc, ptr %q 74 br label %bb57 75 76bb237: 77 ret void 78} 79 80; TODO: we should support this case 81define void @no-alias-store-in-loop(ptr noalias %p, ptr noalias %q) { 82; CHECK-LABEL: @no-alias-store-in-loop( 83; CHECK-NEXT: bb56: 84; CHECK-NEXT: br label [[BB57:%.*]] 85; CHECK: bb57: 86; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ] 87; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ 0, [[BB56]] ], [ [[INC:%.*]], [[BB229]] ] 88; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1 89; CHECK-NEXT: [[N62:%.*]] = icmp ne i8 [[N60]], 2 90; CHECK-NEXT: [[N63:%.*]] = or i1 [[N59]], [[N62]] 91; CHECK-NEXT: br i1 [[N63]], label [[BB229]], label [[BB237:%.*]] 92; CHECK: bb229: 93; CHECK-NEXT: [[INC]] = add i8 [[IDX]], 1 94; CHECK-NEXT: store i8 [[INC]], ptr [[Q:%.*]], align 1 95; CHECK-NEXT: br label [[BB57]] 96; CHECK: bb237: 97; CHECK-NEXT: ret void 98; 99bb56: 100 br label %bb57 101 102bb57: 103 %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ] 104 %idx = phi i8 [0, %bb56], [%inc, %bb229] 105 %n60 = load i8, ptr %p 106 %n62 = icmp ne i8 %n60, 2 107 %n63 = or i1 %n59, %n62 108 br i1 %n63, label %bb229, label %bb237 109 110bb229: 111 %inc = add i8 %idx, 1 112 store i8 %inc, ptr %q 113 br label %bb57 114 115bb237: 116 ret void 117} 118 119define void @function-in-loop(ptr %p) { 120; CHECK-LABEL: @function-in-loop( 121; CHECK-NEXT: bb56: 122; CHECK-NEXT: br label [[BB57:%.*]] 123; CHECK: bb57: 124; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ] 125; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1 126; CHECK-NEXT: [[N62:%.*]] = icmp ne i8 [[N60]], 2 127; CHECK-NEXT: [[N63:%.*]] = or i1 [[N59]], [[N62]] 128; CHECK-NEXT: br i1 [[N63]], label [[BB229]], label [[BB237:%.*]] 129; CHECK: bb229: 130; CHECK-NEXT: call void @f() 131; CHECK-NEXT: br label [[BB57]] 132; CHECK: bb237: 133; CHECK-NEXT: ret void 134; 135bb56: 136 br label %bb57 137 138bb57: 139 %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ] 140 %n60 = load i8, ptr %p 141 %n62 = icmp ne i8 %n60, 2 142 %n63 = or i1 %n59, %n62 143 br i1 %n63, label %bb229, label %bb237 144 145bb229: 146 call void @f() 147 br label %bb57 148 149bb237: 150 ret void 151} 152 153; TODO: we should support this case 154define void @nowrite-function-in-loop(ptr %p) { 155; CHECK-LABEL: @nowrite-function-in-loop( 156; CHECK-NEXT: bb56: 157; CHECK-NEXT: br label [[BB57:%.*]] 158; CHECK: bb57: 159; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ] 160; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1 161; CHECK-NEXT: [[N62:%.*]] = icmp ne i8 [[N60]], 2 162; CHECK-NEXT: [[N63:%.*]] = or i1 [[N59]], [[N62]] 163; CHECK-NEXT: br i1 [[N63]], label [[BB229]], label [[BB237:%.*]] 164; CHECK: bb229: 165; CHECK-NEXT: call void @f() #[[ATTR0:[0-9]+]] 166; CHECK-NEXT: br label [[BB57]] 167; CHECK: bb237: 168; CHECK-NEXT: ret void 169; 170bb56: 171 br label %bb57 172 173bb57: 174 %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ] 175 %n60 = load i8, ptr %p 176 %n62 = icmp ne i8 %n60, 2 177 %n63 = or i1 %n59, %n62 178 br i1 %n63, label %bb229, label %bb237 179 180bb229: 181 call void @f() inaccessiblememonly 182 br label %bb57 183 184bb237: 185 ret void 186} 187 188declare void @f() 189 190define void @issfeoperand(ptr nocapture readonly %array, i1 %cond1, i1 %cond2, ptr nocapture readonly %p1, ptr nocapture writeonly %p2, ptr nocapture writeonly %p3) local_unnamed_addr #0 { 191; CHECK-LABEL: @issfeoperand( 192; CHECK-NEXT: for.body: 193; CHECK-NEXT: br i1 [[COND1:%.*]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 194; CHECK: cond.true: 195; CHECK-NEXT: [[ARRAYIDX31:%.*]] = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr [[ARRAY:%.*]], i64 109, i64 0, i64 0, i64 undef 196; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX31]], align 1 197; CHECK-NEXT: br label [[COND_FALSE]] 198; CHECK: cond.false: 199; CHECK-NEXT: [[PHI1:%.*]] = phi i8 [ [[LD1]], [[COND_TRUE]] ], [ 0, [[FOR_BODY:%.*]] ] 200; CHECK-NEXT: [[ARRAYIDX42:%.*]] = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr [[ARRAY]], i64 109, i64 0, i64 0, i64 undef 201; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX42]], align 1 202; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[LD2]], [[PHI1]] 203; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP1]] to i32 204; CHECK-NEXT: store i32 [[ZEXT]], ptr [[P2:%.*]], align 4 205; CHECK-NEXT: br i1 [[COND2:%.*]], label [[COND_END:%.*]], label [[EXIT:%.*]] 206; CHECK: cond.end: 207; CHECK-NEXT: [[LD3:%.*]] = load i16, ptr [[P1:%.*]], align 2 208; CHECK-NEXT: [[SEXT:%.*]] = sext i16 [[LD3]] to i32 209; CHECK-NEXT: br label [[EXIT]] 210; CHECK: exit: 211; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[SEXT]], [[COND_END]] ], [ 0, [[COND_FALSE]] ] 212; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[LD2]], 0 213; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP2]], i32 [[PHI2]], i32 0 214; CHECK-NEXT: store i32 [[SEL]], ptr [[P3:%.*]], align 4 215; CHECK-NEXT: ret void 216; 217for.body: 218 br i1 %cond1, label %cond.true, label %cond.false 219 220cond.true: ; preds = %for.body 221 %arrayidx31 = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr %array, i64 109, i64 0, i64 0, i64 undef 222 %ld1 = load i8, ptr %arrayidx31, align 1 223 br label %cond.false 224 225cond.false: ; preds = %cond.true, %for.body 226 %phi1 = phi i8 [ %ld1, %cond.true ], [ 0, %for.body ] 227 %arrayidx42 = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr %array, i64 109, i64 0, i64 0, i64 undef 228 %ld2 = load i8, ptr %arrayidx42, align 1 229 %cmp1 = icmp ult i8 %ld2, %phi1 230 %zext = zext i1 %cmp1 to i32 231 store i32 %zext, ptr %p2, align 4 232 br i1 %cond2, label %cond.end, label %exit 233 234cond.end: ; preds = %cond.false 235 %ld3 = load i16, ptr %p1, align 2 236 %sext = sext i16 %ld3 to i32 237 br label %exit 238 239exit: ; preds = %cond.end, %cond.false 240 %phi2 = phi i32 [ %sext, %cond.end ], [ 0, %cond.false ] 241 %cmp2 = icmp eq i8 %ld2, 0 242 %sel = select i1 %cmp2, i32 %phi2, i32 0 243 store i32 %sel, ptr %p3, align 4 244 ret void 245} 246