1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -loop-vectorize -force-vector-width=4 -S | FileCheck %s 3 4 5; Test cases below are reduced (and slightly modified) reproducers based on a 6; problem seen when compiling a C program like this: 7; 8; #include <stdint.h> 9; #include <stdio.h> 10; 11; int y = 0; 12; int b = 1; 13; int d = 1; 14; 15; int main() { 16; #pragma clang loop vectorize_width(4) 17; for (int i = 0; i < 3; ++i) { 18; b = (y == 0) ? d : (d / y); 19; } 20; 21; if (b == 1) 22; printf("GOOD!\n"); 23; else 24; printf("BAD!\n"); 25; } 26; 27; When compiled+executed using 28; build-all/bin/clang -O1 lv-bug.c && ./a.out 29; the result is "GOOD!" 30; 31; When compiled+executed using 32; build-all/bin/clang -O1 lv-bug.c -fvectorize && ./a.out 33; the result is "BAD!" 34 35 36; This test case miscompiled with clang 8.0.0 (see PR43166), now we get 37; loop not vectorized: Cannot fold tail by masking in the presence of live outs. 38; instead. 39define i64 @test1(i64 %y) { 40; CHECK-LABEL: @test1( 41; CHECK-NEXT: entry: 42; CHECK-NEXT: br label [[FOR_BODY:%.*]] 43; CHECK: for.body: 44; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[COND_END:%.*]] ] 45; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[Y:%.*]], 0 46; CHECK-NEXT: br i1 [[CMP]], label [[COND_END]], label [[COND_FALSE:%.*]] 47; CHECK: cond.false: 48; CHECK-NEXT: [[DIV:%.*]] = xor i64 3, [[Y]] 49; CHECK-NEXT: br label [[COND_END]] 50; CHECK: cond.end: 51; CHECK-NEXT: [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_FALSE]] ], [ 77, [[FOR_BODY]] ] 52; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1 53; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 3 54; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 55; CHECK: for.cond.cleanup: 56; CHECK-NEXT: [[COND_LCSSA:%.*]] = phi i64 [ [[COND]], [[COND_END]] ] 57; CHECK-NEXT: ret i64 [[COND_LCSSA]] 58; 59entry: 60 br label %for.body 61 62for.body: 63 %i = phi i32 [ 0, %entry ], [ %inc, %cond.end ] 64 %cmp = icmp eq i64 %y, 0 65 br i1 %cmp, label %cond.end, label %cond.false 66 67cond.false: 68 %div = xor i64 3, %y 69 br label %cond.end 70 71cond.end: 72 %cond = phi i64 [ %div, %cond.false ], [ 77, %for.body ] 73 %inc = add nuw nsw i32 %i, 1 74 %exitcond = icmp eq i32 %inc, 3 75 br i1 %exitcond, label %for.cond.cleanup, label %for.body 76 77for.cond.cleanup: 78 ret i64 %cond 79} 80 81; This test case miscompiled with clang 8.0.0 (see PR43166), now we get 82; loop not vectorized: Cannot fold tail by masking in the presence of live outs. 83; instead. 84define i64 @test2(i64 %y) { 85; CHECK-LABEL: @test2( 86; CHECK-NEXT: entry: 87; CHECK-NEXT: br label [[FOR_BODY:%.*]] 88; CHECK: for.body: 89; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[COND_END:%.*]] ] 90; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[Y:%.*]], 0 91; CHECK-NEXT: br i1 [[CMP]], label [[COND_END]], label [[COND_FALSE:%.*]] 92; CHECK: cond.false: 93; CHECK-NEXT: br label [[COND_END]] 94; CHECK: cond.end: 95; CHECK-NEXT: [[COND:%.*]] = phi i64 [ 55, [[COND_FALSE]] ], [ 77, [[FOR_BODY]] ] 96; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1 97; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 3 98; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 99; CHECK: for.cond.cleanup: 100; CHECK-NEXT: [[COND_LCSSA:%.*]] = phi i64 [ [[COND]], [[COND_END]] ] 101; CHECK-NEXT: ret i64 [[COND_LCSSA]] 102; 103entry: 104 br label %for.body 105 106for.body: 107 %i = phi i32 [ 0, %entry ], [ %inc, %cond.end ] 108 %cmp = icmp eq i64 %y, 0 109 br i1 %cmp, label %cond.end, label %cond.false 110 111cond.false: 112 br label %cond.end 113 114cond.end: 115 %cond = phi i64 [ 55, %cond.false ], [ 77, %for.body ] 116 %inc = add nuw nsw i32 %i, 1 117 %exitcond = icmp eq i32 %inc, 3 118 br i1 %exitcond, label %for.cond.cleanup, label %for.body 119 120for.cond.cleanup: 121 ret i64 %cond 122} 123 124; This test case miscompiled with clang 8.0.0 (see PR43166), now we get 125; loop not vectorized: Cannot fold tail by masking in the presence of live outs. 126; instead. 127define i32 @test3(i64 %y) { 128; CHECK-LABEL: @test3( 129; CHECK-NEXT: entry: 130; CHECK-NEXT: br label [[FOR_BODY:%.*]] 131; CHECK: for.body: 132; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[COND_END:%.*]] ] 133; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[Y:%.*]], 0 134; CHECK-NEXT: br i1 [[CMP]], label [[COND_END]], label [[COND_FALSE:%.*]] 135; CHECK: cond.false: 136; CHECK-NEXT: br label [[COND_END]] 137; CHECK: cond.end: 138; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 55, [[COND_FALSE]] ], [ [[I]], [[FOR_BODY]] ] 139; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1 140; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 3 141; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 142; CHECK: for.cond.cleanup: 143; CHECK-NEXT: [[COND_LCSSA:%.*]] = phi i32 [ [[COND]], [[COND_END]] ] 144; CHECK-NEXT: ret i32 [[COND_LCSSA]] 145; 146entry: 147 br label %for.body 148 149for.body: 150 %i = phi i32 [ 0, %entry ], [ %inc, %cond.end ] 151 %cmp = icmp eq i64 %y, 0 152 br i1 %cmp, label %cond.end, label %cond.false 153 154cond.false: 155 br label %cond.end 156 157cond.end: 158 %cond = phi i32 [ 55, %cond.false ], [ %i, %for.body ] 159 %inc = add nuw nsw i32 %i, 1 160 %exitcond = icmp eq i32 %inc, 3 161 br i1 %exitcond, label %for.cond.cleanup, label %for.body 162 163for.cond.cleanup: 164 ret i32 %cond 165} 166