Test Failure: Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll

Test source: git

Log:

Source: /bitbucket/nlopes/llvm/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll
-- 1. ModuleToFunctionPassAdaptor
-- 1. PassManager<Function> : Skipping NOP
-- 2. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_1_exit_count_with_udiv_by_value_in_header(ptr %dst, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %dst, 4 x i64 %iv
  store i32 1, ptr %gep, align 4
  %d = udiv i64 42, %N
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation seems to be correct! (syntactically equal)

-- 3. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_1_exit_count_with_udiv_by_value_in_header(ptr %dst, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %dst, 4 x i64 %iv
  store i32 1, ptr %gep, align 4
  %d = udiv i64 42, %N
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch ]
  ret i64 %p
}
=>
define i64 @multi_exit_1_exit_count_with_udiv_by_value_in_header(ptr %dst, i64 %N) {
entry:
  %smax = smax i64 %N, 0
  %#0 = udiv i64 42, %N
  %umin = umin i64 %smax, %#0
  %#1 = add nsw nuw i64 %umin, 1
  %min.iters.check = icmp ule i64 %#1, 4
  br i1 %min.iters.check, label %scalar.ph, label %vector.ph

vector.ph:
  %n.mod.vf = urem i64 %#1, 4
  %#2 = icmp eq i64 %n.mod.vf, 0
  %#3 = select i1 %#2, i64 4, i64 %n.mod.vf
  %n.vec = sub i64 %#1, %#3
  br label %vector.body

vector.body:
  %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
  %#4 = add i64 %index, 0
  %#5 = gep inbounds ptr %dst, 4 x i64 %#4
  %#6 = gep inbounds ptr %#5, 4 x i32 0
  store <4 x i32> { 1, 1, 1, 1 }, ptr %#6, align 4
  %index.next = add nuw i64 %index, 4
  %#7 = icmp eq i64 %index.next, %n.vec
  br i1 %#7, label %middle.block, label %vector.body

middle.block:
  br label %scalar.ph

scalar.ph:
  %bc.resume.val = phi i64 [ %n.vec, %middle.block ], [ 0, %entry ]
  br label %loop.header

loop.header:
  %iv = phi i64 [ %bc.resume.val, %scalar.ph ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %dst, 4 x i64 %iv
  store i32 1, ptr %gep, align 4
  %d = udiv i64 42, %N
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation seems to be correct!

-- 4. PassManager<Function> : Skipping NOP
-- 5. PassManager<Function> : Skipping NOP
-- 6. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_1_exit_count_with_udiv_by_constant_in_header(ptr %dst, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %dst, 4 x i64 %iv
  store i32 1, ptr %gep, align 4
  %d = udiv i64 %N, 42
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation seems to be correct! (syntactically equal)

-- 7. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_1_exit_count_with_udiv_by_constant_in_header(ptr %dst, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %dst, 4 x i64 %iv
  store i32 1, ptr %gep, align 4
  %d = udiv i64 %N, 42
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch ]
  ret i64 %p
}
=>
define i64 @multi_exit_1_exit_count_with_udiv_by_constant_in_header(ptr %dst, i64 %N) {
entry:
  %smax = smax i64 %N, 0
  %#0 = udiv i64 %N, 42
  %umin = umin i64 %smax, %#0
  %#1 = add nsw nuw i64 %umin, 1
  %min.iters.check = icmp ule i64 %#1, 4
  br i1 %min.iters.check, label %scalar.ph, label %vector.ph

vector.ph:
  %n.mod.vf = urem i64 %#1, 4
  %#2 = icmp eq i64 %n.mod.vf, 0
  %#3 = select i1 %#2, i64 4, i64 %n.mod.vf
  %n.vec = sub i64 %#1, %#3
  br label %vector.body

vector.body:
  %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
  %#4 = add i64 %index, 0
  %#5 = gep inbounds ptr %dst, 4 x i64 %#4
  %#6 = gep inbounds ptr %#5, 4 x i32 0
  store <4 x i32> { 1, 1, 1, 1 }, ptr %#6, align 4
  %index.next = add nuw i64 %index, 4
  %#7 = icmp eq i64 %index.next, %n.vec
  br i1 %#7, label %middle.block, label %vector.body

middle.block:
  br label %scalar.ph

scalar.ph:
  %bc.resume.val = phi i64 [ %n.vec, %middle.block ], [ 0, %entry ]
  br label %loop.header

loop.header:
  %iv = phi i64 [ %bc.resume.val, %scalar.ph ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %dst, 4 x i64 %iv
  store i32 1, ptr %gep, align 4
  %d = udiv i64 %N, 42
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation doesn't verify! (not unsound)
ERROR: Timeout
-- 8. PassManager<Function> : Skipping NOP
-- 9. PassManager<Function> : Skipping NOP
-- 10. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_2_exit_count_with_udiv_by_value_in_block_executed_unconditionally(ptr %A, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %A, 4 x i64 %iv
  %l = load i32, ptr %gep, align 4
  %c.2 = icmp eq i32 %l, 10
  br i1 %c.2, label %then, label %continue

then:
  store i32 1, ptr %gep, align 4
  br label %continue

continue:
  %d = udiv i64 42, %N
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %continue ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation seems to be correct! (syntactically equal)

-- 11. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_2_exit_count_with_udiv_by_value_in_block_executed_unconditionally(ptr %A, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %A, 4 x i64 %iv
  %l = load i32, ptr %gep, align 4
  %c.2 = icmp eq i32 %l, 10
  br i1 %c.2, label %then, label %continue

then:
  store i32 1, ptr %gep, align 4
  br label %continue

continue:
  %d = udiv i64 42, %N
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %continue ], [ 0, %loop.latch ]
  ret i64 %p
}
=>
define i64 @multi_exit_2_exit_count_with_udiv_by_value_in_block_executed_unconditionally(ptr %A, i64 %N) {
entry:
  %smax = smax i64 %N, 0
  %#0 = udiv i64 42, %N
  %umin = umin i64 %smax, %#0
  %#1 = add nsw nuw i64 %umin, 1
  %min.iters.check = icmp ule i64 %#1, 4
  br i1 %min.iters.check, label %scalar.ph, label %vector.ph

vector.ph:
  %n.mod.vf = urem i64 %#1, 4
  %#2 = icmp eq i64 %n.mod.vf, 0
  %#3 = select i1 %#2, i64 4, i64 %n.mod.vf
  %n.vec = sub i64 %#1, %#3
  br label %vector.body

vector.body:
  %index = phi i64 [ 0, %vector.ph ], [ %index.next, %pred.store.continue6 ]
  %#4 = add i64 %index, 0
  %#5 = gep inbounds ptr %A, 4 x i64 %#4
  %#6 = gep inbounds ptr %#5, 4 x i32 0
  %wide.load = load <4 x i32>, ptr %#6, align 4
  %#7 = icmp eq <4 x i32> %wide.load, { 10, 10, 10, 10 }
  %#8 = extractelement <4 x i1> %#7, i32 0
  br i1 %#8, label %pred.store.if, label %pred.store.continue

pred.store.if:
  %#9 = gep inbounds ptr %A, 4 x i64 %#4
  store i32 1, ptr %#9, align 4
  br label %pred.store.continue

pred.store.continue:
  %#10 = extractelement <4 x i1> %#7, i32 1
  br i1 %#10, label %pred.store.if1, label %pred.store.continue2

pred.store.if1:
  %#11 = add i64 %index, 1
  %#12 = gep inbounds ptr %A, 4 x i64 %#11
  store i32 1, ptr %#12, align 4
  br label %pred.store.continue2

pred.store.continue2:
  %#13 = extractelement <4 x i1> %#7, i32 2
  br i1 %#13, label %pred.store.if3, label %pred.store.continue4

pred.store.if3:
  %#14 = add i64 %index, 2
  %#15 = gep inbounds ptr %A, 4 x i64 %#14
  store i32 1, ptr %#15, align 4
  br label %pred.store.continue4

pred.store.continue4:
  %#16 = extractelement <4 x i1> %#7, i32 3
  br i1 %#16, label %pred.store.if5, label %pred.store.continue6

pred.store.if5:
  %#17 = add i64 %index, 3
  %#18 = gep inbounds ptr %A, 4 x i64 %#17
  store i32 1, ptr %#18, align 4
  br label %pred.store.continue6

pred.store.continue6:
  %index.next = add nuw i64 %index, 4
  %#19 = icmp eq i64 %index.next, %n.vec
  br i1 %#19, label %middle.block, label %vector.body

middle.block:
  br label %scalar.ph

scalar.ph:
  %bc.resume.val = phi i64 [ %n.vec, %middle.block ], [ 0, %entry ]
  br label %loop.header

loop.header:
  %iv = phi i64 [ %bc.resume.val, %scalar.ph ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %A, 4 x i64 %iv
  %l = load i32, ptr %gep, align 4
  %c.2 = icmp eq i32 %l, 10
  br i1 %c.2, label %then, label %continue

then:
  store i32 1, ptr %gep, align 4
  br label %continue

continue:
  %d = udiv i64 42, %N
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %continue ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation doesn't verify! (not unsound)
ERROR: Timeout
-- 12. PassManager<Function> : Skipping NOP
-- 13. PassManager<Function> : Skipping NOP
-- 14. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_2_exit_count_with_udiv_by_constant_in_block_executed_unconditionally(ptr %A, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %A, 4 x i64 %iv
  %l = load i32, ptr %gep, align 4
  %c.2 = icmp eq i32 %l, 10
  br i1 %c.2, label %then, label %continue

then:
  store i32 1, ptr %gep, align 4
  br label %continue

continue:
  %d = udiv i64 %N, 42
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %continue ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation seems to be correct! (syntactically equal)

-- 15. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_2_exit_count_with_udiv_by_constant_in_block_executed_unconditionally(ptr %A, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %A, 4 x i64 %iv
  %l = load i32, ptr %gep, align 4
  %c.2 = icmp eq i32 %l, 10
  br i1 %c.2, label %then, label %continue

then:
  store i32 1, ptr %gep, align 4
  br label %continue

continue:
  %d = udiv i64 %N, 42
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %continue ], [ 0, %loop.latch ]
  ret i64 %p
}
=>
define i64 @multi_exit_2_exit_count_with_udiv_by_constant_in_block_executed_unconditionally(ptr %A, i64 %N) {
entry:
  %smax = smax i64 %N, 0
  %#0 = udiv i64 %N, 42
  %umin = umin i64 %smax, %#0
  %#1 = add nsw nuw i64 %umin, 1
  %min.iters.check = icmp ule i64 %#1, 4
  br i1 %min.iters.check, label %scalar.ph, label %vector.ph

vector.ph:
  %n.mod.vf = urem i64 %#1, 4
  %#2 = icmp eq i64 %n.mod.vf, 0
  %#3 = select i1 %#2, i64 4, i64 %n.mod.vf
  %n.vec = sub i64 %#1, %#3
  br label %vector.body

vector.body:
  %index = phi i64 [ 0, %vector.ph ], [ %index.next, %pred.store.continue6 ]
  %#4 = add i64 %index, 0
  %#5 = gep inbounds ptr %A, 4 x i64 %#4
  %#6 = gep inbounds ptr %#5, 4 x i32 0
  %wide.load = load <4 x i32>, ptr %#6, align 4
  %#7 = icmp eq <4 x i32> %wide.load, { 10, 10, 10, 10 }
  %#8 = extractelement <4 x i1> %#7, i32 0
  br i1 %#8, label %pred.store.if, label %pred.store.continue

pred.store.if:
  %#9 = gep inbounds ptr %A, 4 x i64 %#4
  store i32 1, ptr %#9, align 4
  br label %pred.store.continue

pred.store.continue:
  %#10 = extractelement <4 x i1> %#7, i32 1
  br i1 %#10, label %pred.store.if1, label %pred.store.continue2

pred.store.if1:
  %#11 = add i64 %index, 1
  %#12 = gep inbounds ptr %A, 4 x i64 %#11
  store i32 1, ptr %#12, align 4
  br label %pred.store.continue2

pred.store.continue2:
  %#13 = extractelement <4 x i1> %#7, i32 2
  br i1 %#13, label %pred.store.if3, label %pred.store.continue4

pred.store.if3:
  %#14 = add i64 %index, 2
  %#15 = gep inbounds ptr %A, 4 x i64 %#14
  store i32 1, ptr %#15, align 4
  br label %pred.store.continue4

pred.store.continue4:
  %#16 = extractelement <4 x i1> %#7, i32 3
  br i1 %#16, label %pred.store.if5, label %pred.store.continue6

pred.store.if5:
  %#17 = add i64 %index, 3
  %#18 = gep inbounds ptr %A, 4 x i64 %#17
  store i32 1, ptr %#18, align 4
  br label %pred.store.continue6

pred.store.continue6:
  %index.next = add nuw i64 %index, 4
  %#19 = icmp eq i64 %index.next, %n.vec
  br i1 %#19, label %middle.block, label %vector.body

middle.block:
  br label %scalar.ph

scalar.ph:
  %bc.resume.val = phi i64 [ %n.vec, %middle.block ], [ 0, %entry ]
  br label %loop.header

loop.header:
  %iv = phi i64 [ %bc.resume.val, %scalar.ph ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %A, 4 x i64 %iv
  %l = load i32, ptr %gep, align 4
  %c.2 = icmp eq i32 %l, 10
  br i1 %c.2, label %then, label %continue

then:
  store i32 1, ptr %gep, align 4
  br label %continue

continue:
  %d = udiv i64 %N, 42
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %continue ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation doesn't verify! (not unsound)
ERROR: Timeout
-- 16. PassManager<Function> : Skipping NOP
-- 17. PassManager<Function> : Skipping NOP
-- 18. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_3_exit_count_with_udiv_by_value_in_block_executed_conditionally(ptr %A, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %A, 4 x i64 %iv
  %l = load i32, ptr %gep, align 4
  %c.2 = icmp eq i32 %l, 10
  br i1 %c.2, label %then, label %loop.latch

then:
  %d = udiv i64 42, %N
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  store i32 1, ptr %gep, align 4
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %then ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation seems to be correct! (syntactically equal)

-- 19. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_3_exit_count_with_udiv_by_value_in_block_executed_conditionally(ptr %A, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %A, 4 x i64 %iv
  %l = load i32, ptr %gep, align 4
  %c.2 = icmp eq i32 %l, 10
  br i1 %c.2, label %then, label %loop.latch

then:
  %d = udiv i64 42, %N
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  store i32 1, ptr %gep, align 4
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %then ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation seems to be correct! (syntactically equal)

-- 20. PassManager<Function> : Skipping NOP
-- 21. PassManager<Function> : Skipping NOP
-- 22. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_3_exit_count_with_udiv_by_constant_in_block_executed_conditionally(ptr %A, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %A, 4 x i64 %iv
  %l = load i32, ptr %gep, align 4
  %c.2 = icmp eq i32 %l, 10
  br i1 %c.2, label %then, label %loop.latch

then:
  %d = udiv i64 %N, 42
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  store i32 1, ptr %gep, align 4
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %then ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation seems to be correct! (syntactically equal)

-- 23. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_3_exit_count_with_udiv_by_constant_in_block_executed_conditionally(ptr %A, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %A, 4 x i64 %iv
  %l = load i32, ptr %gep, align 4
  %c.2 = icmp eq i32 %l, 10
  br i1 %c.2, label %then, label %loop.latch

then:
  %d = udiv i64 %N, 42
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.latch, label %exit

loop.latch:
  store i32 1, ptr %gep, align 4
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %then ], [ 0, %loop.latch ]
  ret i64 %p
}
=>
define i64 @multi_exit_3_exit_count_with_udiv_by_constant_in_block_executed_conditionally(ptr %A, i64 %N) {
entry:
  %d = udiv i64 %N, 42
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %A, 4 x i64 %iv
  %l = load i32, ptr %gep, align 4
  %c.2 = icmp ne i32 %l, 10
  %c.1 = icmp slt i64 %iv, %d
  %or.cond = select i1 %c.2, i1 1, i1 %c.1
  br i1 %or.cond, label %loop.latch, label %exit

loop.latch:
  store i32 1, ptr %gep, align 4
  %iv.next = add i64 %iv, 1
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.header, label %exit

exit:
  %p = phi i64 [ 0, %loop.latch ], [ 1, %loop.header ]
  ret i64 %p
}
Transformation seems to be correct!

-- 24. PassManager<Function> : Skipping NOP
-- 25. PassManager<Function> : Skipping NOP
-- 26. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch(ptr %dst, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %dst, 4 x i64 %iv
  store i32 1, ptr %gep, align 4
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %d = udiv i64 42, %N
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation seems to be correct! (syntactically equal)

-- 27. LoopVectorizePass

----------------------------------------
define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch(ptr %dst, i64 %N) {
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %dst, 4 x i64 %iv
  store i32 1, ptr %gep, align 4
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %d = udiv i64 42, %N
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch ]
  ret i64 %p
}
=>
define i64 @multi_exit_4_exit_count_with_udiv_by_value_in_latch(ptr %dst, i64 %N) {
entry:
  %smax = smax i64 %N, 0
  %#0 = udiv i64 42, %N
  %umin = umin i64 %smax, %#0
  %#1 = add nsw nuw i64 %umin, 1
  %min.iters.check = icmp ule i64 %#1, 4
  br i1 %min.iters.check, label %scalar.ph, label %vector.ph

vector.ph:
  %n.mod.vf = urem i64 %#1, 4
  %#2 = icmp eq i64 %n.mod.vf, 0
  %#3 = select i1 %#2, i64 4, i64 %n.mod.vf
  %n.vec = sub i64 %#1, %#3
  br label %vector.body

vector.body:
  %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
  %#4 = add i64 %index, 0
  %#5 = gep inbounds ptr %dst, 4 x i64 %#4
  %#6 = gep inbounds ptr %#5, 4 x i32 0
  store <4 x i32> { 1, 1, 1, 1 }, ptr %#6, align 4
  %index.next = add nuw i64 %index, 4
  %#7 = icmp eq i64 %index.next, %n.vec
  br i1 %#7, label %middle.block, label %vector.body

middle.block:
  br label %scalar.ph

scalar.ph:
  %bc.resume.val = phi i64 [ %n.vec, %middle.block ], [ 0, %entry ]
  br label %loop.header

loop.header:
  %iv = phi i64 [ %bc.resume.val, %scalar.ph ], [ %iv.next, %loop.latch ]
  %gep = gep inbounds ptr %dst, 4 x i64 %iv
  store i32 1, ptr %gep, align 4
  %c.0 = icmp slt i64 %iv, %N
  br i1 %c.0, label %loop.latch, label %exit

loop.latch:
  %iv.next = add i64 %iv, 1
  %d = udiv i64 42, %N
  %c.1 = icmp slt i64 %iv, %d
  br i1 %c.1, label %loop.header, label %exit

exit:
  %p = phi i64 [ 1, %loop.header ], [ 0, %loop.latch ]
  ret i64 %p
}
Transformation doesn't verify! (unsound)
ERROR: Source is more defined than target

Example:
ptr %dst = pointer(non-local, block_id=1, offset=0) / Address=#x0000000000000004
i64 %N = #x0000000000000000 (0)

Source:
  >> Jump to %loop.header
i64 %iv = #x0000000000000000 (0)
ptr %gep = pointer(non-local, block_id=1, offset=0) / Address=#x0000000000000004
i1 %c.0 = #x0 (0)
  >> Jump to %exit
i64 %p = #x0000000000000001 (1)

SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 >	size: 0	align: 4	alloc type: 0	alive: false	address: 0
Block 1 >	size: 8	align: 1	alloc type: 0	alive: true	address: 4

Target:
i64 %smax = #x0000000000000000 (0)
i64 %#0 = UB triggered!


Pass: LoopVectorizePass
Command line: '/home/nlopes/llvm/build/bin/opt' '-load=/home/nlopes/alive2/build/tv/tv.so' '-load-pass-plugin=/home/nlopes/alive2/build/tv/tv.so' '-tv-exit-on-error' '-p' 'loop-vectorize' '-force-vector-width=4' '-S' '/bitbucket/nlopes/llvm/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll' '-tv-smt-to=20000' '-tv-report-dir=/home/nlopes/alive2/build/logs' '-tv-smt-stats'
Wrote bitcode to: "/home/nlopes/alive2/build/logs/trip-count-expansion-may-introduce-ub_vt86VMRm_sfP6.bc"


------------------- SMT STATS -------------------
Num queries: 57
Num invalid: 0
Num skips:   0
Num trivial: 11 (16.2%)
Num timeout: 3 (5.3%)
Num errors:  0 (0.0%)
Num SAT:     40 (70.2%)
Num UNSAT:   14 (24.6%)
Alive2: Transform doesn't verify; aborting!

stderr:

RUN: at line 2: /home/nlopes/alive2/build/opt-alive.sh -p loop-vectorize -force-vector-width=4 -S /bitbucket/nlopes/llvm/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll | /bitbucket/nlopes/llvm/build/bin/FileCheck /bitbucket/nlopes/llvm/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll
+ /home/nlopes/alive2/build/opt-alive.sh -p loop-vectorize -force-vector-width=4 -S /bitbucket/nlopes/llvm/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll
+ /bitbucket/nlopes/llvm/build/bin/FileCheck /bitbucket/nlopes/llvm/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll
remark: <unknown>:0:0: loop not vectorized: Cannot vectorize early exit loop
remark: <unknown>:0:0: loop not vectorized: Cannot vectorize early exit loop with writes to memory

FileCheck error: '<stdin>' is empty.
FileCheck command line:  /bitbucket/nlopes/llvm/build/bin/FileCheck /bitbucket/nlopes/llvm/llvm/test/Transforms/LoopVectorize/trip-count-expansion-may-introduce-ub.ll

 

<-- Back