1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=gvn-hoist -S < %s | FileCheck %s 3target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 4target triple = "x86_64-unknown-linux-gnu" 5 6@GlobalVar = internal global float 1.000000e+00 7 8; Check that all scalar expressions are hoisted. 9define float @scalarsHoisting(float %d, float %min, float %max, float %a) { 10; CHECK-LABEL: @scalarsHoisting( 11; CHECK-NEXT: entry: 12; CHECK-NEXT: [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]] 13; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00 14; CHECK-NEXT: [[SUB:%.*]] = fsub float [[MIN:%.*]], [[A:%.*]] 15; CHECK-NEXT: [[MUL:%.*]] = fmul float [[SUB]], [[DIV]] 16; CHECK-NEXT: [[SUB1:%.*]] = fsub float [[MAX:%.*]], [[A]] 17; CHECK-NEXT: [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]] 18; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 19; CHECK: if.then: 20; CHECK-NEXT: br label [[IF_END:%.*]] 21; CHECK: if.else: 22; CHECK-NEXT: br label [[IF_END]] 23; CHECK: if.end: 24; CHECK-NEXT: [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL]], [[IF_ELSE]] ] 25; CHECK-NEXT: [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL2]], [[IF_ELSE]] ] 26; CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]] 27; CHECK-NEXT: ret float [[ADD]] 28; 29entry: 30 %div = fdiv float 1.000000e+00, %d 31 %cmp = fcmp oge float %div, 0.000000e+00 32 br i1 %cmp, label %if.then, label %if.else 33 34if.then: ; preds = %entry 35 %sub = fsub float %min, %a 36 %mul = fmul float %sub, %div 37 %sub1 = fsub float %max, %a 38 %mul2 = fmul float %sub1, %div 39 br label %if.end 40 41if.else: ; preds = %entry 42 %sub3 = fsub float %max, %a 43 %mul4 = fmul float %sub3, %div 44 %sub5 = fsub float %min, %a 45 %mul6 = fmul float %sub5, %div 46 br label %if.end 47 48if.end: ; preds = %if.else, %if.then 49 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ] 50 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ] 51 %add = fadd float %tmax.0, %tmin.0 52 ret float %add 53} 54 55; Check that all loads and scalars depending on the loads are hoisted. 56; Check that getelementptr computation gets hoisted before the load. 57define float @readsAndScalarsHoisting(float %d, ptr %min, ptr %max, ptr %a) { 58; CHECK-LABEL: @readsAndScalarsHoisting( 59; CHECK-NEXT: entry: 60; CHECK-NEXT: [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]] 61; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00 62; CHECK-NEXT: [[TMP0:%.*]] = getelementptr float, ptr [[MIN:%.*]], i32 1 63; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[TMP0]], align 4 64; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[A:%.*]], align 4 65; CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[MAX:%.*]], align 4 66; CHECK-NEXT: [[SUB:%.*]] = fsub float [[TMP1]], [[TMP2]] 67; CHECK-NEXT: [[MUL:%.*]] = fmul float [[SUB]], [[DIV]] 68; CHECK-NEXT: [[SUB1:%.*]] = fsub float [[TMP3]], [[TMP2]] 69; CHECK-NEXT: [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]] 70; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 71; CHECK: if.then: 72; CHECK-NEXT: [[A:%.*]] = getelementptr float, ptr [[MIN]], i32 1 73; CHECK-NEXT: br label [[IF_END:%.*]] 74; CHECK: if.else: 75; CHECK-NEXT: [[B:%.*]] = getelementptr float, ptr [[MIN]], i32 1 76; CHECK-NEXT: br label [[IF_END]] 77; CHECK: if.end: 78; CHECK-NEXT: [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL]], [[IF_ELSE]] ] 79; CHECK-NEXT: [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL2]], [[IF_ELSE]] ] 80; CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]] 81; CHECK-NEXT: ret float [[ADD]] 82; 83entry: 84 %div = fdiv float 1.000000e+00, %d 85 %cmp = fcmp oge float %div, 0.000000e+00 86 br i1 %cmp, label %if.then, label %if.else 87 88if.then: ; preds = %entry 89 %A = getelementptr float, ptr %min, i32 1 90 %0 = load float, ptr %A, align 4 91 %1 = load float, ptr %a, align 4 92 %sub = fsub float %0, %1 93 %mul = fmul float %sub, %div 94 %2 = load float, ptr %max, align 4 95 %sub1 = fsub float %2, %1 96 %mul2 = fmul float %sub1, %div 97 br label %if.end 98 99if.else: ; preds = %entry 100 %3 = load float, ptr %max, align 4 101 %4 = load float, ptr %a, align 4 102 %sub3 = fsub float %3, %4 103 %mul4 = fmul float %sub3, %div 104 %B = getelementptr float, ptr %min, i32 1 105 %5 = load float, ptr %B, align 4 106 %sub5 = fsub float %5, %4 107 %mul6 = fmul float %sub5, %div 108 br label %if.end 109 110if.end: ; preds = %if.else, %if.then 111 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ] 112 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ] 113 %add = fadd float %tmax.0, %tmin.0 114 ret float %add 115} 116 117; Check that we do not hoist loads after a store: the first two loads will be 118; hoisted, and then the third load will not be hoisted. 119define float @readsAndWrites(float %d, ptr %min, ptr %max, ptr %a) { 120; CHECK-LABEL: @readsAndWrites( 121; CHECK-NEXT: entry: 122; CHECK-NEXT: [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]] 123; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00 124; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4 125; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4 126; CHECK-NEXT: [[SUB:%.*]] = fsub float [[TMP0]], [[TMP1]] 127; CHECK-NEXT: [[MUL:%.*]] = fmul float [[SUB]], [[DIV]] 128; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 129; CHECK: if.then: 130; CHECK-NEXT: store float [[TMP0]], ptr @GlobalVar, align 4 131; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4 132; CHECK-NEXT: [[SUB1:%.*]] = fsub float [[TMP2]], [[TMP1]] 133; CHECK-NEXT: [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]] 134; CHECK-NEXT: br label [[IF_END:%.*]] 135; CHECK: if.else: 136; CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[MAX]], align 4 137; CHECK-NEXT: [[SUB3:%.*]] = fsub float [[TMP3]], [[TMP1]] 138; CHECK-NEXT: [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]] 139; CHECK-NEXT: br label [[IF_END]] 140; CHECK: if.end: 141; CHECK-NEXT: [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL]], [[IF_ELSE]] ] 142; CHECK-NEXT: [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL4]], [[IF_ELSE]] ] 143; CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]] 144; CHECK-NEXT: ret float [[ADD]] 145; 146entry: 147 %div = fdiv float 1.000000e+00, %d 148 %cmp = fcmp oge float %div, 0.000000e+00 149 br i1 %cmp, label %if.then, label %if.else 150 151if.then: ; preds = %entry 152 %0 = load float, ptr %min, align 4 153 %1 = load float, ptr %a, align 4 154 store float %0, ptr @GlobalVar 155 %sub = fsub float %0, %1 156 %mul = fmul float %sub, %div 157 %2 = load float, ptr %max, align 4 158 %sub1 = fsub float %2, %1 159 %mul2 = fmul float %sub1, %div 160 br label %if.end 161 162if.else: ; preds = %entry 163 %3 = load float, ptr %max, align 4 164 %4 = load float, ptr %a, align 4 165 %sub3 = fsub float %3, %4 166 %mul4 = fmul float %sub3, %div 167 %5 = load float, ptr %min, align 4 168 %sub5 = fsub float %5, %4 169 %mul6 = fmul float %sub5, %div 170 br label %if.end 171 172if.end: ; preds = %if.else, %if.then 173 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ] 174 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ] 175 %add = fadd float %tmax.0, %tmin.0 176 ret float %add 177} 178 179; Check that we do hoist loads when the store is above the insertion point. 180define float @readsAndWriteAboveInsertPt(float %d, ptr %min, ptr %max, ptr %a) { 181; CHECK-LABEL: @readsAndWriteAboveInsertPt( 182; CHECK-NEXT: entry: 183; CHECK-NEXT: [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]] 184; CHECK-NEXT: store float 0.000000e+00, ptr @GlobalVar, align 4 185; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00 186; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4 187; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4 188; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4 189; CHECK-NEXT: [[SUB:%.*]] = fsub float [[TMP0]], [[TMP1]] 190; CHECK-NEXT: [[MUL:%.*]] = fmul float [[SUB]], [[DIV]] 191; CHECK-NEXT: [[SUB1:%.*]] = fsub float [[TMP2]], [[TMP1]] 192; CHECK-NEXT: [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]] 193; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 194; CHECK: if.then: 195; CHECK-NEXT: br label [[IF_END:%.*]] 196; CHECK: if.else: 197; CHECK-NEXT: br label [[IF_END]] 198; CHECK: if.end: 199; CHECK-NEXT: [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL]], [[IF_ELSE]] ] 200; CHECK-NEXT: [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL2]], [[IF_ELSE]] ] 201; CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]] 202; CHECK-NEXT: ret float [[ADD]] 203; 204entry: 205 %div = fdiv float 1.000000e+00, %d 206 store float 0.000000e+00, ptr @GlobalVar 207 %cmp = fcmp oge float %div, 0.000000e+00 208 br i1 %cmp, label %if.then, label %if.else 209 210if.then: ; preds = %entry 211 %0 = load float, ptr %min, align 4 212 %1 = load float, ptr %a, align 4 213 %sub = fsub float %0, %1 214 %mul = fmul float %sub, %div 215 %2 = load float, ptr %max, align 4 216 %sub1 = fsub float %2, %1 217 %mul2 = fmul float %sub1, %div 218 br label %if.end 219 220if.else: ; preds = %entry 221 %3 = load float, ptr %max, align 4 222 %4 = load float, ptr %a, align 4 223 %sub3 = fsub float %3, %4 224 %mul4 = fmul float %sub3, %div 225 %5 = load float, ptr %min, align 4 226 %sub5 = fsub float %5, %4 227 %mul6 = fmul float %sub5, %div 228 br label %if.end 229 230if.end: ; preds = %if.else, %if.then 231 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ] 232 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ] 233 %add = fadd float %tmax.0, %tmin.0 234 ret float %add 235} 236 237; Check that dependent expressions are hoisted. 238define float @dependentScalarsHoisting(float %a, float %b, i1 %c) { 239; CHECK-LABEL: @dependentScalarsHoisting( 240; CHECK-NEXT: entry: 241; CHECK-NEXT: [[D:%.*]] = fsub float [[B:%.*]], [[A:%.*]] 242; CHECK-NEXT: [[E:%.*]] = fadd float [[D]], [[A]] 243; CHECK-NEXT: [[F:%.*]] = fdiv float [[E]], [[A]] 244; CHECK-NEXT: [[G:%.*]] = fmul float [[F]], [[A]] 245; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 246; CHECK: if.then: 247; CHECK-NEXT: br label [[IF_END:%.*]] 248; CHECK: if.else: 249; CHECK-NEXT: br label [[IF_END]] 250; CHECK: if.end: 251; CHECK-NEXT: [[R:%.*]] = phi float [ [[G]], [[IF_THEN]] ], [ [[G]], [[IF_ELSE]] ] 252; CHECK-NEXT: ret float [[R]] 253; 254entry: 255 br i1 %c, label %if.then, label %if.else 256 257if.then: 258 %d = fsub float %b, %a 259 %e = fadd float %d, %a 260 %f = fdiv float %e, %a 261 %g = fmul float %f, %a 262 br label %if.end 263 264if.else: 265 %h = fsub float %b, %a 266 %i = fadd float %h, %a 267 %j = fdiv float %i, %a 268 %k = fmul float %j, %a 269 br label %if.end 270 271if.end: 272 %r = phi float [ %g, %if.then ], [ %k, %if.else ] 273 ret float %r 274} 275 276; Check that all independent expressions are hoisted. 277define float @independentScalarsHoisting(float %a, float %b, i1 %c) { 278; CHECK-LABEL: @independentScalarsHoisting( 279; CHECK-NEXT: entry: 280; CHECK-NEXT: [[D:%.*]] = fadd float [[B:%.*]], [[A:%.*]] 281; CHECK-NEXT: [[E:%.*]] = fsub float [[B]], [[A]] 282; CHECK-NEXT: [[F:%.*]] = fdiv float [[B]], [[A]] 283; CHECK-NEXT: [[G:%.*]] = fmul float [[B]], [[A]] 284; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 285; CHECK: if.then: 286; CHECK-NEXT: br label [[IF_END:%.*]] 287; CHECK: if.else: 288; CHECK-NEXT: br label [[IF_END]] 289; CHECK: if.end: 290; CHECK-NEXT: [[P:%.*]] = phi float [ [[D]], [[IF_THEN]] ], [ [[D]], [[IF_ELSE]] ] 291; CHECK-NEXT: [[Q:%.*]] = phi float [ [[E]], [[IF_THEN]] ], [ [[E]], [[IF_ELSE]] ] 292; CHECK-NEXT: [[R:%.*]] = phi float [ [[F]], [[IF_THEN]] ], [ [[F]], [[IF_ELSE]] ] 293; CHECK-NEXT: [[S:%.*]] = phi float [ [[G]], [[IF_THEN]] ], [ [[G]], [[IF_ELSE]] ] 294; CHECK-NEXT: [[T:%.*]] = fadd float [[P]], [[Q]] 295; CHECK-NEXT: [[U:%.*]] = fadd float [[R]], [[S]] 296; CHECK-NEXT: [[V:%.*]] = fadd float [[T]], [[U]] 297; CHECK-NEXT: ret float [[V]] 298; 299entry: 300 br i1 %c, label %if.then, label %if.else 301 302if.then: 303 %d = fadd float %b, %a 304 %e = fsub float %b, %a 305 %f = fdiv float %b, %a 306 %g = fmul float %b, %a 307 br label %if.end 308 309if.else: 310 %i = fadd float %b, %a 311 %h = fsub float %b, %a 312 %j = fdiv float %b, %a 313 %k = fmul float %b, %a 314 br label %if.end 315 316if.end: 317 %p = phi float [ %d, %if.then ], [ %i, %if.else ] 318 %q = phi float [ %e, %if.then ], [ %h, %if.else ] 319 %r = phi float [ %f, %if.then ], [ %j, %if.else ] 320 %s = phi float [ %g, %if.then ], [ %k, %if.else ] 321 %t = fadd float %p, %q 322 %u = fadd float %r, %s 323 %v = fadd float %t, %u 324 ret float %v 325} 326 327; Check that we hoist load and scalar expressions in triangles. 328define float @triangleHoisting(float %d, ptr %min, ptr %max, ptr %a) { 329; CHECK-LABEL: @triangleHoisting( 330; CHECK-NEXT: entry: 331; CHECK-NEXT: [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]] 332; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00 333; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4 334; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4 335; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4 336; CHECK-NEXT: [[SUB5:%.*]] = fsub float [[TMP0]], [[TMP1]] 337; CHECK-NEXT: [[MUL6:%.*]] = fmul float [[SUB5]], [[DIV]] 338; CHECK-NEXT: [[SUB3:%.*]] = fsub float [[TMP2]], [[TMP1]] 339; CHECK-NEXT: [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]] 340; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 341; CHECK: if.then: 342; CHECK-NEXT: br label [[IF_END]] 343; CHECK: if.end: 344; CHECK-NEXT: [[P1:%.*]] = phi float [ [[MUL4]], [[IF_THEN]] ], [ 0.000000e+00, [[ENTRY:%.*]] ] 345; CHECK-NEXT: [[P2:%.*]] = phi float [ [[MUL6]], [[IF_THEN]] ], [ 0.000000e+00, [[ENTRY]] ] 346; CHECK-NEXT: [[X:%.*]] = fadd float [[P1]], [[MUL6]] 347; CHECK-NEXT: [[Y:%.*]] = fadd float [[P2]], [[MUL4]] 348; CHECK-NEXT: [[Z:%.*]] = fadd float [[X]], [[Y]] 349; CHECK-NEXT: ret float [[Z]] 350; 351entry: 352 %div = fdiv float 1.000000e+00, %d 353 %cmp = fcmp oge float %div, 0.000000e+00 354 br i1 %cmp, label %if.then, label %if.end 355 356if.then: ; preds = %entry 357 %0 = load float, ptr %min, align 4 358 %1 = load float, ptr %a, align 4 359 %sub = fsub float %0, %1 360 %mul = fmul float %sub, %div 361 %2 = load float, ptr %max, align 4 362 %sub1 = fsub float %2, %1 363 %mul2 = fmul float %sub1, %div 364 br label %if.end 365 366if.end: ; preds = %entry 367 %p1 = phi float [ %mul2, %if.then ], [ 0.000000e+00, %entry ] 368 %p2 = phi float [ %mul, %if.then ], [ 0.000000e+00, %entry ] 369 %3 = load float, ptr %max, align 4 370 %4 = load float, ptr %a, align 4 371 %sub3 = fsub float %3, %4 372 %mul4 = fmul float %sub3, %div 373 %5 = load float, ptr %min, align 4 374 %sub5 = fsub float %5, %4 375 %mul6 = fmul float %sub5, %div 376 377 %x = fadd float %p1, %mul6 378 %y = fadd float %p2, %mul4 379 %z = fadd float %x, %y 380 ret float %z 381} 382 383; Check that we do not hoist loads past stores within a same basic block. 384define i32 @noHoistInSingleBBWithStore() { 385; CHECK-LABEL: @noHoistInSingleBBWithStore( 386; CHECK-NEXT: entry: 387; CHECK-NEXT: [[D:%.*]] = alloca i32, align 4 388; CHECK-NEXT: [[TMP0:%.*]] = bitcast ptr [[D]] to ptr 389; CHECK-NEXT: [[BF:%.*]] = load i8, ptr [[TMP0]], align 4 390; CHECK-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF]], -3 391; CHECK-NEXT: store i8 [[BF_CLEAR]], ptr [[TMP0]], align 4 392; CHECK-NEXT: [[BF1:%.*]] = load i8, ptr [[TMP0]], align 4 393; CHECK-NEXT: [[BF_CLEAR1:%.*]] = and i8 [[BF1]], 1 394; CHECK-NEXT: store i8 [[BF_CLEAR1]], ptr [[TMP0]], align 4 395; CHECK-NEXT: ret i32 0 396; 397entry: 398 %D = alloca i32, align 4 399 %0 = bitcast ptr %D to ptr 400 %bf = load i8, ptr %0, align 4 401 %bf.clear = and i8 %bf, -3 402 store i8 %bf.clear, ptr %0, align 4 403 %bf1 = load i8, ptr %0, align 4 404 %bf.clear1 = and i8 %bf1, 1 405 store i8 %bf.clear1, ptr %0, align 4 406 ret i32 0 407} 408 409; Check that we do not hoist loads past calls within a same basic block. 410declare void @foo() 411define i32 @noHoistInSingleBBWithCall() { 412; CHECK-LABEL: @noHoistInSingleBBWithCall( 413; CHECK-NEXT: entry: 414; CHECK-NEXT: [[D:%.*]] = alloca i32, align 4 415; CHECK-NEXT: [[TMP0:%.*]] = bitcast ptr [[D]] to ptr 416; CHECK-NEXT: [[BF:%.*]] = load i8, ptr [[TMP0]], align 4 417; CHECK-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF]], -3 418; CHECK-NEXT: call void @foo() 419; CHECK-NEXT: [[BF1:%.*]] = load i8, ptr [[TMP0]], align 4 420; CHECK-NEXT: [[BF_CLEAR1:%.*]] = and i8 [[BF1]], 1 421; CHECK-NEXT: ret i32 0 422; 423entry: 424 %D = alloca i32, align 4 425 %0 = bitcast ptr %D to ptr 426 %bf = load i8, ptr %0, align 4 427 %bf.clear = and i8 %bf, -3 428 call void @foo() 429 %bf1 = load i8, ptr %0, align 4 430 %bf.clear1 = and i8 %bf1, 1 431 ret i32 0 432} 433 434; Check that we do not hoist loads past stores in any branch of a diamond. 435define float @noHoistInDiamondWithOneStore1(float %d, ptr %min, ptr %max, ptr %a) { 436; CHECK-LABEL: @noHoistInDiamondWithOneStore1( 437; CHECK-NEXT: entry: 438; CHECK-NEXT: [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]] 439; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00 440; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 441; CHECK: if.then: 442; CHECK-NEXT: store float 0.000000e+00, ptr @GlobalVar, align 4 443; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4 444; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4 445; CHECK-NEXT: [[SUB:%.*]] = fsub float [[TMP0]], [[TMP1]] 446; CHECK-NEXT: [[MUL:%.*]] = fmul float [[SUB]], [[DIV]] 447; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4 448; CHECK-NEXT: [[SUB1:%.*]] = fsub float [[TMP2]], [[TMP1]] 449; CHECK-NEXT: [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]] 450; CHECK-NEXT: br label [[IF_END:%.*]] 451; CHECK: if.else: 452; CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[MAX]], align 4 453; CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[A]], align 4 454; CHECK-NEXT: [[SUB3:%.*]] = fsub float [[TMP3]], [[TMP4]] 455; CHECK-NEXT: [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]] 456; CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[MIN]], align 4 457; CHECK-NEXT: [[SUB5:%.*]] = fsub float [[TMP5]], [[TMP4]] 458; CHECK-NEXT: [[MUL6:%.*]] = fmul float [[SUB5]], [[DIV]] 459; CHECK-NEXT: br label [[IF_END]] 460; CHECK: if.end: 461; CHECK-NEXT: [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL6]], [[IF_ELSE]] ] 462; CHECK-NEXT: [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL4]], [[IF_ELSE]] ] 463; CHECK-NEXT: [[TMP6:%.*]] = load float, ptr [[MAX]], align 4 464; CHECK-NEXT: [[TMP7:%.*]] = load float, ptr [[A]], align 4 465; CHECK-NEXT: [[SUB6:%.*]] = fsub float [[TMP6]], [[TMP7]] 466; CHECK-NEXT: [[MUL7:%.*]] = fmul float [[SUB6]], [[DIV]] 467; CHECK-NEXT: [[TMP8:%.*]] = load float, ptr [[MIN]], align 4 468; CHECK-NEXT: [[SUB8:%.*]] = fsub float [[TMP8]], [[TMP7]] 469; CHECK-NEXT: [[MUL9:%.*]] = fmul float [[SUB8]], [[DIV]] 470; CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]] 471; CHECK-NEXT: ret float [[ADD]] 472; 473entry: 474 %div = fdiv float 1.000000e+00, %d 475 %cmp = fcmp oge float %div, 0.000000e+00 476 br i1 %cmp, label %if.then, label %if.else 477 478if.then: ; preds = %entry 479 store float 0.000000e+00, ptr @GlobalVar 480 %0 = load float, ptr %min, align 4 481 %1 = load float, ptr %a, align 4 482 %sub = fsub float %0, %1 483 %mul = fmul float %sub, %div 484 %2 = load float, ptr %max, align 4 485 %sub1 = fsub float %2, %1 486 %mul2 = fmul float %sub1, %div 487 br label %if.end 488 489if.else: ; preds = %entry 490 ; There are no side effects on the if.else branch. 491 %3 = load float, ptr %max, align 4 492 %4 = load float, ptr %a, align 4 493 %sub3 = fsub float %3, %4 494 %mul4 = fmul float %sub3, %div 495 %5 = load float, ptr %min, align 4 496 %sub5 = fsub float %5, %4 497 %mul6 = fmul float %sub5, %div 498 br label %if.end 499 500if.end: ; preds = %if.else, %if.then 501 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ] 502 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ] 503 504 %6 = load float, ptr %max, align 4 505 %7 = load float, ptr %a, align 4 506 %sub6 = fsub float %6, %7 507 %mul7 = fmul float %sub6, %div 508 %8 = load float, ptr %min, align 4 509 %sub8 = fsub float %8, %7 510 %mul9 = fmul float %sub8, %div 511 512 %add = fadd float %tmax.0, %tmin.0 513 ret float %add 514} 515 516; Check that we do not hoist loads past stores from half diamond. 517define float @noHoistInHalfDiamondPastStore(float %d, ptr %min, ptr %max, ptr %a) { 518; CHECK-LABEL: @noHoistInHalfDiamondPastStore( 519; CHECK-NEXT: entry: 520; CHECK-NEXT: [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]] 521; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00 522; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4 523; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4 524; CHECK-NEXT: store float 0.000000e+00, ptr @GlobalVar, align 4 525; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 526; CHECK: if.then: 527; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4 528; CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[A]], align 4 529; CHECK-NEXT: [[SUB3:%.*]] = fsub float [[TMP2]], [[TMP3]] 530; CHECK-NEXT: [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]] 531; CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[MIN]], align 4 532; CHECK-NEXT: [[SUB5:%.*]] = fsub float [[TMP4]], [[TMP3]] 533; CHECK-NEXT: [[MUL6:%.*]] = fmul float [[SUB5]], [[DIV]] 534; CHECK-NEXT: br label [[IF_END]] 535; CHECK: if.end: 536; CHECK-NEXT: [[TMAX_0:%.*]] = phi float [ [[MUL4]], [[IF_THEN]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 537; CHECK-NEXT: [[TMIN_0:%.*]] = phi float [ [[MUL6]], [[IF_THEN]] ], [ [[TMP1]], [[ENTRY]] ] 538; CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]] 539; CHECK-NEXT: ret float [[ADD]] 540; 541entry: 542 %div = fdiv float 1.000000e+00, %d 543 %cmp = fcmp oge float %div, 0.000000e+00 544 %0 = load float, ptr %min, align 4 545 %1 = load float, ptr %a, align 4 546 547 ; Loads should not be hoisted above this store. 548 store float 0.000000e+00, ptr @GlobalVar 549 550 br i1 %cmp, label %if.then, label %if.end 551 552if.then: 553 ; There are no side effects on the if.then branch. 554 %2 = load float, ptr %max, align 4 555 %3 = load float, ptr %a, align 4 556 %sub3 = fsub float %2, %3 557 %mul4 = fmul float %sub3, %div 558 %4 = load float, ptr %min, align 4 559 %sub5 = fsub float %4, %3 560 %mul6 = fmul float %sub5, %div 561 br label %if.end 562 563if.end: 564 %tmax.0 = phi float [ %mul4, %if.then ], [ %0, %entry ] 565 %tmin.0 = phi float [ %mul6, %if.then ], [ %1, %entry ] 566 567 %add = fadd float %tmax.0, %tmin.0 568 ret float %add 569} 570 571; Check that we do not hoist loads past a store in any branch of a diamond. 572define float @noHoistInDiamondWithOneStore2(float %d, ptr %min, ptr %max, ptr %a) { 573; CHECK-LABEL: @noHoistInDiamondWithOneStore2( 574; CHECK-NEXT: entry: 575; CHECK-NEXT: [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]] 576; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00 577; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 578; CHECK: if.then: 579; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4 580; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4 581; CHECK-NEXT: [[SUB:%.*]] = fsub float [[TMP0]], [[TMP1]] 582; CHECK-NEXT: [[MUL:%.*]] = fmul float [[SUB]], [[DIV]] 583; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4 584; CHECK-NEXT: [[SUB1:%.*]] = fsub float [[TMP2]], [[TMP1]] 585; CHECK-NEXT: [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]] 586; CHECK-NEXT: br label [[IF_END:%.*]] 587; CHECK: if.else: 588; CHECK-NEXT: store float 0.000000e+00, ptr @GlobalVar, align 4 589; CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[MAX]], align 4 590; CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[A]], align 4 591; CHECK-NEXT: [[SUB3:%.*]] = fsub float [[TMP3]], [[TMP4]] 592; CHECK-NEXT: [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]] 593; CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[MIN]], align 4 594; CHECK-NEXT: [[SUB5:%.*]] = fsub float [[TMP5]], [[TMP4]] 595; CHECK-NEXT: [[MUL6:%.*]] = fmul float [[SUB5]], [[DIV]] 596; CHECK-NEXT: br label [[IF_END]] 597; CHECK: if.end: 598; CHECK-NEXT: [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL6]], [[IF_ELSE]] ] 599; CHECK-NEXT: [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL4]], [[IF_ELSE]] ] 600; CHECK-NEXT: [[TMP6:%.*]] = load float, ptr [[MAX]], align 4 601; CHECK-NEXT: [[TMP7:%.*]] = load float, ptr [[A]], align 4 602; CHECK-NEXT: [[SUB6:%.*]] = fsub float [[TMP6]], [[TMP7]] 603; CHECK-NEXT: [[MUL7:%.*]] = fmul float [[SUB6]], [[DIV]] 604; CHECK-NEXT: [[TMP8:%.*]] = load float, ptr [[MIN]], align 4 605; CHECK-NEXT: [[SUB8:%.*]] = fsub float [[TMP8]], [[TMP7]] 606; CHECK-NEXT: [[MUL9:%.*]] = fmul float [[SUB8]], [[DIV]] 607; CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]] 608; CHECK-NEXT: ret float [[ADD]] 609; 610entry: 611 %div = fdiv float 1.000000e+00, %d 612 %cmp = fcmp oge float %div, 0.000000e+00 613 br i1 %cmp, label %if.then, label %if.else 614 615if.then: ; preds = %entry 616 ; There are no side effects on the if.then branch. 617 %0 = load float, ptr %min, align 4 618 %1 = load float, ptr %a, align 4 619 %sub = fsub float %0, %1 620 %mul = fmul float %sub, %div 621 %2 = load float, ptr %max, align 4 622 %sub1 = fsub float %2, %1 623 %mul2 = fmul float %sub1, %div 624 br label %if.end 625 626if.else: ; preds = %entry 627 store float 0.000000e+00, ptr @GlobalVar 628 %3 = load float, ptr %max, align 4 629 %4 = load float, ptr %a, align 4 630 %sub3 = fsub float %3, %4 631 %mul4 = fmul float %sub3, %div 632 %5 = load float, ptr %min, align 4 633 %sub5 = fsub float %5, %4 634 %mul6 = fmul float %sub5, %div 635 br label %if.end 636 637if.end: ; preds = %if.else, %if.then 638 %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ] 639 %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ] 640 641 %6 = load float, ptr %max, align 4 642 %7 = load float, ptr %a, align 4 643 %sub6 = fsub float %6, %7 644 %mul7 = fmul float %sub6, %div 645 %8 = load float, ptr %min, align 4 646 %sub8 = fsub float %8, %7 647 %mul9 = fmul float %sub8, %div 648 649 %add = fadd float %tmax.0, %tmin.0 650 ret float %add 651} 652 653; Check that we do not hoist loads outside a loop containing stores. 654define float @noHoistInLoopsWithStores(float %d, ptr %min, ptr %max, ptr %a) { 655; CHECK-LABEL: @noHoistInLoopsWithStores( 656; CHECK-NEXT: entry: 657; CHECK-NEXT: [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]] 658; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00 659; CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY:%.*]], label [[IF_ELSE:%.*]] 660; CHECK: do.body: 661; CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4 662; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4 663; CHECK-NEXT: store float 0.000000e+00, ptr @GlobalVar, align 4 664; CHECK-NEXT: [[SUB:%.*]] = fsub float [[TMP0]], [[TMP1]] 665; CHECK-NEXT: [[MUL:%.*]] = fmul float [[SUB]], [[DIV]] 666; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4 667; CHECK-NEXT: [[SUB1:%.*]] = fsub float [[TMP2]], [[TMP1]] 668; CHECK-NEXT: [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]] 669; CHECK-NEXT: br label [[WHILE_COND:%.*]] 670; CHECK: while.cond: 671; CHECK-NEXT: [[CMP1:%.*]] = fcmp oge float [[MUL2]], 0.000000e+00 672; CHECK-NEXT: br i1 [[CMP1]], label [[IF_END:%.*]], label [[DO_BODY]] 673; CHECK: if.else: 674; CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[MAX]], align 4 675; CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[A]], align 4 676; CHECK-NEXT: [[SUB3:%.*]] = fsub float [[TMP3]], [[TMP4]] 677; CHECK-NEXT: [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]] 678; CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[MIN]], align 4 679; CHECK-NEXT: [[SUB5:%.*]] = fsub float [[TMP5]], [[TMP4]] 680; CHECK-NEXT: [[MUL6:%.*]] = fmul float [[SUB5]], [[DIV]] 681; CHECK-NEXT: br label [[IF_END]] 682; CHECK: if.end: 683; CHECK-NEXT: [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[WHILE_COND]] ], [ [[MUL6]], [[IF_ELSE]] ] 684; CHECK-NEXT: [[TMIN_0:%.*]] = phi float [ [[MUL]], [[WHILE_COND]] ], [ [[MUL4]], [[IF_ELSE]] ] 685; CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]] 686; CHECK-NEXT: ret float [[ADD]] 687; 688entry: 689 %div = fdiv float 1.000000e+00, %d 690 %cmp = fcmp oge float %div, 0.000000e+00 691 br i1 %cmp, label %do.body, label %if.else 692 693do.body: 694 %0 = load float, ptr %min, align 4 695 %1 = load float, ptr %a, align 4 696 697 ; It is unsafe to hoist the loads outside the loop because of the store. 698 store float 0.000000e+00, ptr @GlobalVar 699 700 %sub = fsub float %0, %1 701 %mul = fmul float %sub, %div 702 %2 = load float, ptr %max, align 4 703 %sub1 = fsub float %2, %1 704 %mul2 = fmul float %sub1, %div 705 br label %while.cond 706 707while.cond: 708 %cmp1 = fcmp oge float %mul2, 0.000000e+00 709 br i1 %cmp1, label %if.end, label %do.body 710 711if.else: 712 %3 = load float, ptr %max, align 4 713 %4 = load float, ptr %a, align 4 714 %sub3 = fsub float %3, %4 715 %mul4 = fmul float %sub3, %div 716 %5 = load float, ptr %min, align 4 717 %sub5 = fsub float %5, %4 718 %mul6 = fmul float %sub5, %div 719 br label %if.end 720 721if.end: 722 %tmax.0 = phi float [ %mul2, %while.cond ], [ %mul6, %if.else ] 723 %tmin.0 = phi float [ %mul, %while.cond ], [ %mul4, %if.else ] 724 725 %add = fadd float %tmax.0, %tmin.0 726 ret float %add 727} 728 729; Check that we hoist stores: all the instructions from the then branch 730; should be hoisted. 731 732%struct.foo = type { ptr } 733 734define void @hoistStores(ptr %s, ptr %coord, i1 zeroext %delta) { 735; CHECK-LABEL: @hoistStores( 736; CHECK-NEXT: entry: 737; CHECK-NEXT: [[FROMBOOL:%.*]] = zext i1 [[DELTA:%.*]] to i8 738; CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[FROMBOOL]] to i1 739; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[S:%.*]], i32 0, i32 0 740; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 741; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[S]], i32 0, i32 0 742; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 1 743; CHECK-NEXT: store ptr [[TMP3]], ptr [[TMP2]], align 8 744; CHECK-NEXT: [[TMP4:%.*]] = load i16, ptr [[TMP1]], align 2 745; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[COORD:%.*]], align 4 746; CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP4]] to i32 747; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP5]], [[CONV]] 748; CHECK-NEXT: store i32 [[ADD]], ptr [[COORD]], align 4 749; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 750; CHECK: if.then: 751; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[S]], i32 0, i32 0 752; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 1 753; CHECK-NEXT: br label [[IF_END:%.*]] 754; CHECK: if.else: 755; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[S]], i32 0, i32 0 756; CHECK-NEXT: [[INCDEC_PTR2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 1 757; CHECK-NEXT: [[TMP6:%.*]] = load ptr, ptr [[P1]], align 8 758; CHECK-NEXT: [[INCDEC_PTR6:%.*]] = getelementptr inbounds i16, ptr [[TMP6]], i32 1 759; CHECK-NEXT: store ptr [[INCDEC_PTR6]], ptr [[P1]], align 8 760; CHECK-NEXT: [[TMP7:%.*]] = load i16, ptr [[TMP6]], align 2 761; CHECK-NEXT: [[CONV7:%.*]] = zext i16 [[TMP7]] to i32 762; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[CONV7]], 8 763; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[COORD]], align 4 764; CHECK-NEXT: [[ADD8:%.*]] = add i32 [[TMP8]], [[SHL]] 765; CHECK-NEXT: store i32 [[ADD8]], ptr [[COORD]], align 4 766; CHECK-NEXT: br label [[IF_END]] 767; CHECK: if.end: 768; CHECK-NEXT: ret void 769; 770entry: 771 %frombool = zext i1 %delta to i8 772 %tobool = trunc i8 %frombool to i1 773 br i1 %tobool, label %if.then, label %if.else 774 775if.then: ; preds = %entry 776 %p = getelementptr inbounds %struct.foo, ptr %s, i32 0, i32 0 777 %0 = load ptr, ptr %p, align 8 778 %incdec.ptr = getelementptr inbounds i16, ptr %0, i32 1 779 store ptr %incdec.ptr, ptr %p, align 8 780 %1 = load i16, ptr %0, align 2 781 %conv = zext i16 %1 to i32 782 %2 = load i32, ptr %coord, align 4 783 %add = add i32 %2, %conv 784 store i32 %add, ptr %coord, align 4 785 br label %if.end 786 787if.else: ; preds = %entry 788 %p1 = getelementptr inbounds %struct.foo, ptr %s, i32 0, i32 0 789 %3 = load ptr, ptr %p1, align 8 790 %incdec.ptr2 = getelementptr inbounds i16, ptr %3, i32 1 791 store ptr %incdec.ptr2, ptr %p1, align 8 792 %4 = load i16, ptr %3, align 2 793 %conv3 = zext i16 %4 to i32 794 %5 = load i32, ptr %coord, align 4 795 %add4 = add i32 %5, %conv3 796 store i32 %add4, ptr %coord, align 4 797 %6 = load ptr, ptr %p1, align 8 798 %incdec.ptr6 = getelementptr inbounds i16, ptr %6, i32 1 799 store ptr %incdec.ptr6, ptr %p1, align 8 800 %7 = load i16, ptr %6, align 2 801 %conv7 = zext i16 %7 to i32 802 %shl = shl i32 %conv7, 8 803 %8 = load i32, ptr %coord, align 4 804 %add8 = add i32 %8, %shl 805 store i32 %add8, ptr %coord, align 4 806 br label %if.end 807 808if.end: ; preds = %if.else, %if.then 809 ret void 810} 811 812define i32 @mergeAlignments(i1 %b, ptr %y) { 813; CHECK-LABEL: @mergeAlignments( 814; CHECK-NEXT: entry: 815; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[Y:%.*]], align 1 816; CHECK-NEXT: br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 817; CHECK: if.then: 818; CHECK-NEXT: br label [[RETURN:%.*]] 819; CHECK: if.end: 820; CHECK-NEXT: br label [[RETURN]] 821; CHECK: return: 822; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[L1]], [[IF_THEN]] ], [ [[L1]], [[IF_END]] ] 823; CHECK-NEXT: ret i32 [[RETVAL_0]] 824; 825entry: 826 br i1 %b, label %if.then, label %if.end 827 828if.then: ; preds = %entry 829 %l1 = load i32, ptr %y, align 4 830 br label %return 831 832if.end: ; preds = %entry 833 %l2 = load i32, ptr %y, align 1 834 br label %return 835 836return: ; preds = %if.end, %if.then 837 %retval.0 = phi i32 [ %l1, %if.then ], [ %l2, %if.end ] 838 ret i32 %retval.0 839} 840 841declare i8 @pr30991_f() nounwind readonly 842declare void @pr30991_f1(i8) 843define i8 @pr30991(ptr %sp, ptr %word, i1 %b1, i1 %b2) { 844; CHECK-LABEL: @pr30991( 845; CHECK-NEXT: entry: 846; CHECK-NEXT: [[R0:%.*]] = load i8, ptr [[WORD:%.*]], align 1 847; CHECK-NEXT: br i1 [[B1:%.*]], label [[A:%.*]], label [[B:%.*]] 848; CHECK: a: 849; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr i8, ptr [[SP:%.*]], i32 1 850; CHECK-NEXT: [[RR0:%.*]] = call i8 @pr30991_f() #[[ATTR0:[0-9]+]] 851; CHECK-NEXT: call void @pr30991_f1(i8 [[R0]]) 852; CHECK-NEXT: ret i8 [[RR0]] 853; CHECK: b: 854; CHECK-NEXT: br i1 [[B2:%.*]], label [[C:%.*]], label [[X:%.*]] 855; CHECK: c: 856; CHECK-NEXT: [[INCDEC_PTR115:%.*]] = getelementptr i8, ptr [[SP]], i32 1 857; CHECK-NEXT: [[RR1:%.*]] = call i8 @pr30991_f() #[[ATTR0]] 858; CHECK-NEXT: call void @pr30991_f1(i8 [[R0]]) 859; CHECK-NEXT: ret i8 [[RR1]] 860; CHECK: x: 861; CHECK-NEXT: ret i8 [[R0]] 862; 863entry: 864 br i1 %b1, label %a, label %b 865 866a: 867 %r0 = load i8, ptr %word, align 1 868 %incdec.ptr = getelementptr i8, ptr %sp, i32 1 869 %rr0 = call i8 @pr30991_f() nounwind readonly 870 call void @pr30991_f1(i8 %r0) 871 ret i8 %rr0 872 873b: 874 br i1 %b2, label %c, label %x 875 876c: 877 %r1 = load i8, ptr %word, align 1 878 %incdec.ptr115 = getelementptr i8, ptr %sp, i32 1 879 %rr1 = call i8 @pr30991_f() nounwind readonly 880 call void @pr30991_f1(i8 %r1) 881 ret i8 %rr1 882 883x: 884 %r2 = load i8, ptr %word, align 1 885 ret i8 %r2 886} 887