1*9880d681SAndroid Build Coastguard Worker; RUN: opt < %s -loop-unswitch -verify-loop-info -S < %s 2>&1 | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker 3*9880d681SAndroid Build Coastguard Worker@sink = global i32 0, align 4 4*9880d681SAndroid Build Coastguard Worker@y = global i64 0, align 8 5*9880d681SAndroid Build Coastguard Worker 6*9880d681SAndroid Build Coastguard Worker; The following is approximately: 7*9880d681SAndroid Build Coastguard Worker; void f(bool x, int p, int q) { 8*9880d681SAndroid Build Coastguard Worker; volatile bool x2 = x; 9*9880d681SAndroid Build Coastguard Worker; for (int i = 0; i < 1; ++i) { 10*9880d681SAndroid Build Coastguard Worker; if (x2) { 11*9880d681SAndroid Build Coastguard Worker; if (y) 12*9880d681SAndroid Build Coastguard Worker; sink = p; 13*9880d681SAndroid Build Coastguard Worker; else 14*9880d681SAndroid Build Coastguard Worker; sink = q; 15*9880d681SAndroid Build Coastguard Worker; } 16*9880d681SAndroid Build Coastguard Worker; } 17*9880d681SAndroid Build Coastguard Worker; } 18*9880d681SAndroid Build Coastguard Worker; With MemorySanitizer, the loop can not be unswitched on "y", because "y" could 19*9880d681SAndroid Build Coastguard Worker; be uninitialized when x == false. 20*9880d681SAndroid Build Coastguard Worker; Test that the branch on "y" is inside the loop (after the first unconditional 21*9880d681SAndroid Build Coastguard Worker; branch). 22*9880d681SAndroid Build Coastguard Worker 23*9880d681SAndroid Build Coastguard Workerdefine void @may_not_execute(i1 zeroext %x, i32 %p, i32 %q) sanitize_memory { 24*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @may_not_execute( 25*9880d681SAndroid Build Coastguard Workerentry: 26*9880d681SAndroid Build Coastguard Worker; CHECK: %[[Y:.*]] = load i64, i64* @y, align 8 27*9880d681SAndroid Build Coastguard Worker; CHECK: %[[YB:.*]] = icmp eq i64 %[[Y]], 0 28*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: br i1 29*9880d681SAndroid Build Coastguard Worker; CHECK: br label 30*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 %[[YB]] 31*9880d681SAndroid Build Coastguard Worker 32*9880d681SAndroid Build Coastguard Worker %x2 = alloca i8, align 1 33*9880d681SAndroid Build Coastguard Worker %frombool1 = zext i1 %x to i8 34*9880d681SAndroid Build Coastguard Worker store volatile i8 %frombool1, i8* %x2, align 1 35*9880d681SAndroid Build Coastguard Worker %0 = load i64, i64* @y, align 8 36*9880d681SAndroid Build Coastguard Worker %tobool3 = icmp eq i64 %0, 0 37*9880d681SAndroid Build Coastguard Worker br label %for.body 38*9880d681SAndroid Build Coastguard Worker 39*9880d681SAndroid Build Coastguard Workerfor.body: 40*9880d681SAndroid Build Coastguard Worker %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] 41*9880d681SAndroid Build Coastguard Worker %x2.0. = load volatile i8, i8* %x2, align 1 42*9880d681SAndroid Build Coastguard Worker %tobool2 = icmp eq i8 %x2.0., 0 43*9880d681SAndroid Build Coastguard Worker br i1 %tobool2, label %for.inc, label %if.then 44*9880d681SAndroid Build Coastguard Worker 45*9880d681SAndroid Build Coastguard Workerif.then: 46*9880d681SAndroid Build Coastguard Worker br i1 %tobool3, label %if.else, label %if.then4 47*9880d681SAndroid Build Coastguard Worker 48*9880d681SAndroid Build Coastguard Workerif.then4: 49*9880d681SAndroid Build Coastguard Worker store volatile i32 %p, i32* @sink, align 4 50*9880d681SAndroid Build Coastguard Worker br label %for.inc 51*9880d681SAndroid Build Coastguard Worker 52*9880d681SAndroid Build Coastguard Workerif.else: 53*9880d681SAndroid Build Coastguard Worker store volatile i32 %q, i32* @sink, align 4 54*9880d681SAndroid Build Coastguard Worker br label %for.inc 55*9880d681SAndroid Build Coastguard Worker 56*9880d681SAndroid Build Coastguard Workerfor.inc: 57*9880d681SAndroid Build Coastguard Worker %inc = add nsw i32 %i.01, 1 58*9880d681SAndroid Build Coastguard Worker %cmp = icmp slt i32 %inc, 1 59*9880d681SAndroid Build Coastguard Worker br i1 %cmp, label %for.body, label %for.end 60*9880d681SAndroid Build Coastguard Worker 61*9880d681SAndroid Build Coastguard Workerfor.end: 62*9880d681SAndroid Build Coastguard Worker ret void 63*9880d681SAndroid Build Coastguard Worker} 64*9880d681SAndroid Build Coastguard Worker 65*9880d681SAndroid Build Coastguard Worker 66*9880d681SAndroid Build Coastguard Worker; The same as above, but "y" is a function parameter instead of a global. 67*9880d681SAndroid Build Coastguard Worker; This shows that it is not enough to suppress hoisting of load instructions, 68*9880d681SAndroid Build Coastguard Worker; the actual problem is in the speculative branching. 69*9880d681SAndroid Build Coastguard Worker 70*9880d681SAndroid Build Coastguard Workerdefine void @may_not_execute2(i1 zeroext %x, i1 zeroext %y, i32 %p, i32 %q) sanitize_memory { 71*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @may_not_execute2( 72*9880d681SAndroid Build Coastguard Workerentry: 73*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: br i1 74*9880d681SAndroid Build Coastguard Worker; CHECK: br label 75*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 %y, 76*9880d681SAndroid Build Coastguard Worker %x2 = alloca i8, align 1 77*9880d681SAndroid Build Coastguard Worker %frombool2 = zext i1 %x to i8 78*9880d681SAndroid Build Coastguard Worker store volatile i8 %frombool2, i8* %x2, align 1 79*9880d681SAndroid Build Coastguard Worker br label %for.body 80*9880d681SAndroid Build Coastguard Worker 81*9880d681SAndroid Build Coastguard Workerfor.body: 82*9880d681SAndroid Build Coastguard Worker %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] 83*9880d681SAndroid Build Coastguard Worker %x2.0. = load volatile i8, i8* %x2, align 1 84*9880d681SAndroid Build Coastguard Worker %tobool3 = icmp eq i8 %x2.0., 0 85*9880d681SAndroid Build Coastguard Worker br i1 %tobool3, label %for.inc, label %if.then 86*9880d681SAndroid Build Coastguard Worker 87*9880d681SAndroid Build Coastguard Workerif.then: 88*9880d681SAndroid Build Coastguard Worker br i1 %y, label %if.then5, label %if.else 89*9880d681SAndroid Build Coastguard Worker 90*9880d681SAndroid Build Coastguard Workerif.then5: 91*9880d681SAndroid Build Coastguard Worker store volatile i32 %p, i32* @sink, align 4 92*9880d681SAndroid Build Coastguard Worker br label %for.inc 93*9880d681SAndroid Build Coastguard Worker 94*9880d681SAndroid Build Coastguard Workerif.else: 95*9880d681SAndroid Build Coastguard Worker store volatile i32 %q, i32* @sink, align 4 96*9880d681SAndroid Build Coastguard Worker br label %for.inc 97*9880d681SAndroid Build Coastguard Worker 98*9880d681SAndroid Build Coastguard Workerfor.inc: 99*9880d681SAndroid Build Coastguard Worker %inc = add nsw i32 %i.01, 1 100*9880d681SAndroid Build Coastguard Worker %cmp = icmp slt i32 %inc, 1 101*9880d681SAndroid Build Coastguard Worker br i1 %cmp, label %for.body, label %for.end 102*9880d681SAndroid Build Coastguard Worker 103*9880d681SAndroid Build Coastguard Workerfor.end: 104*9880d681SAndroid Build Coastguard Worker ret void 105*9880d681SAndroid Build Coastguard Worker} 106*9880d681SAndroid Build Coastguard Worker 107*9880d681SAndroid Build Coastguard Worker 108*9880d681SAndroid Build Coastguard Worker; The following is approximately: 109*9880d681SAndroid Build Coastguard Worker; void f(bool x, int p, int q) { 110*9880d681SAndroid Build Coastguard Worker; volatile bool x2 = x; 111*9880d681SAndroid Build Coastguard Worker; for (int i = 0; i < 1; ++i) { 112*9880d681SAndroid Build Coastguard Worker; if (y) 113*9880d681SAndroid Build Coastguard Worker; sink = p; 114*9880d681SAndroid Build Coastguard Worker; else 115*9880d681SAndroid Build Coastguard Worker; sink = q; 116*9880d681SAndroid Build Coastguard Worker; } 117*9880d681SAndroid Build Coastguard Worker; } 118*9880d681SAndroid Build Coastguard Worker; "if (y)" is guaranteed to execute; the loop can be unswitched. 119*9880d681SAndroid Build Coastguard Worker 120*9880d681SAndroid Build Coastguard Workerdefine void @must_execute(i1 zeroext %x, i32 %p, i32 %q) sanitize_memory { 121*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @must_execute( 122*9880d681SAndroid Build Coastguard Workerentry: 123*9880d681SAndroid Build Coastguard Worker; CHECK: %[[Y:.*]] = load i64, i64* @y, align 8 124*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %[[YB:.*]] = icmp eq i64 %[[Y]], 0 125*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: br i1 %[[YB]], 126*9880d681SAndroid Build Coastguard Worker 127*9880d681SAndroid Build Coastguard Worker %x2 = alloca i8, align 1 128*9880d681SAndroid Build Coastguard Worker %frombool1 = zext i1 %x to i8 129*9880d681SAndroid Build Coastguard Worker store volatile i8 %frombool1, i8* %x2, align 1 130*9880d681SAndroid Build Coastguard Worker %0 = load i64, i64* @y, align 8 131*9880d681SAndroid Build Coastguard Worker %tobool2 = icmp eq i64 %0, 0 132*9880d681SAndroid Build Coastguard Worker br label %for.body 133*9880d681SAndroid Build Coastguard Worker 134*9880d681SAndroid Build Coastguard Workerfor.body: 135*9880d681SAndroid Build Coastguard Worker %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] 136*9880d681SAndroid Build Coastguard Worker br i1 %tobool2, label %if.else, label %if.then 137*9880d681SAndroid Build Coastguard Worker 138*9880d681SAndroid Build Coastguard Workerif.then: 139*9880d681SAndroid Build Coastguard Worker store volatile i32 %p, i32* @sink, align 4 140*9880d681SAndroid Build Coastguard Worker br label %for.inc 141*9880d681SAndroid Build Coastguard Worker 142*9880d681SAndroid Build Coastguard Workerif.else: 143*9880d681SAndroid Build Coastguard Worker store volatile i32 %q, i32* @sink, align 4 144*9880d681SAndroid Build Coastguard Worker br label %for.inc 145*9880d681SAndroid Build Coastguard Worker 146*9880d681SAndroid Build Coastguard Workerfor.inc: 147*9880d681SAndroid Build Coastguard Worker %inc = add nsw i32 %i.01, 1 148*9880d681SAndroid Build Coastguard Worker %cmp = icmp slt i32 %inc, 1 149*9880d681SAndroid Build Coastguard Worker br i1 %cmp, label %for.body, label %for.end 150*9880d681SAndroid Build Coastguard Worker 151*9880d681SAndroid Build Coastguard Workerfor.end: 152*9880d681SAndroid Build Coastguard Worker ret void 153*9880d681SAndroid Build Coastguard Worker} 154