Bjorn Pettersson 8ebb3eac02 [test] Use -passes syntax when specifying pipeline in some more tests
The legacy PM is deprecated, so update a bunch of lit tests running
opt to use the new PM syntax when specifying the pipeline.
In this patch focus has been put on test cases for ConstantMerge,
ConstraintElimination, CorrelatedValuePropagation, GlobalDCE,
GlobalOpt, SCCP, TailCallElim and PredicateInfo.

Differential Revision: https://reviews.llvm.org/D114516
2021-11-27 09:52:55 +01:00

635 lines
22 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
define void @test0(i32 %n) {
; CHECK-LABEL: @test0(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[DIV1:%.*]], [[FOR_BODY:%.*]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[J_0]], 1
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[DIV1]] = udiv i32 [[J_0]], 2
; CHECK-NEXT: br label [[FOR_COND]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
entry:
br label %for.cond
for.cond: ; preds = %for.body, %entry
%j.0 = phi i32 [ %n, %entry ], [ %div, %for.body ]
%cmp = icmp sgt i32 %j.0, 1
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%div = sdiv i32 %j.0, 2
br label %for.cond
for.end: ; preds = %for.cond
ret void
}
define void @test1(i32 %n) {
; CHECK-LABEL: @test1(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_COND:%.*]]
; CHECK: for.cond:
; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[DIV:%.*]], [[FOR_BODY:%.*]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[J_0]], -2
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[DIV]] = sdiv i32 [[J_0]], 2
; CHECK-NEXT: br label [[FOR_COND]]
; CHECK: for.end:
; CHECK-NEXT: ret void
;
entry:
br label %for.cond
for.cond: ; preds = %for.body, %entry
%j.0 = phi i32 [ %n, %entry ], [ %div, %for.body ]
%cmp = icmp sgt i32 %j.0, -2
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%div = sdiv i32 %j.0, 2
br label %for.cond
for.end: ; preds = %for.cond
ret void
}
define void @test2(i32 %n) {
; CHECK-LABEL: @test2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 1
; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]
; CHECK: bb:
; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[N]], 2
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%cmp = icmp sgt i32 %n, 1
br i1 %cmp, label %bb, label %exit
bb:
%div = sdiv i32 %n, 2
br label %exit
exit:
ret void
}
; looping case where loop has exactly one block
; at the point of sdiv, we know that %a is always greater than 0,
; because of the guard before it, so we can transform it to udiv.
declare void @llvm.experimental.guard(i1,...)
define void @test4(i32 %n) {
; CHECK-LABEL: @test4(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 0
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP:%.*]], label [[EXIT:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[DIV1:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[A]], 4
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND]]) [ "deopt"() ]
; CHECK-NEXT: [[DIV1]] = udiv i32 [[A]], 6
; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%cmp = icmp sgt i32 %n, 0
br i1 %cmp, label %loop, label %exit
loop:
%a = phi i32 [ %n, %entry ], [ %div, %loop ]
%cond = icmp sgt i32 %a, 4
call void(i1,...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
%div = sdiv i32 %a, 6
br i1 %cond, label %loop, label %exit
exit:
ret void
}
; same test as above with assume instead of guard.
declare void @llvm.assume(i1)
define void @test5(i32 %n) {
; CHECK-LABEL: @test5(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 0
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP:%.*]], label [[EXIT:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[DIV1:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[COND:%.*]] = icmp ugt i32 [[A]], 4
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
; CHECK-NEXT: [[DIV1]] = udiv i32 [[A]], 6
; CHECK-NEXT: [[LOOPCOND:%.*]] = icmp ugt i32 [[DIV1]], 8
; CHECK-NEXT: br i1 [[LOOPCOND]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%cmp = icmp sgt i32 %n, 0
br i1 %cmp, label %loop, label %exit
loop:
%a = phi i32 [ %n, %entry ], [ %div, %loop ]
%cond = icmp sgt i32 %a, 4
call void @llvm.assume(i1 %cond)
%div = sdiv i32 %a, 6
%loopcond = icmp sgt i32 %div, 8
br i1 %loopcond, label %loop, label %exit
exit:
ret void
}
; Now, let's try various domain combinations for operands.
define i32 @test6_pos_pos(i32 %x, i32 %y) {
; CHECK-LABEL: @test6_pos_pos(
; CHECK-NEXT: [[C0:%.*]] = icmp sge i32 [[X:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i32 [[Y:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X]], [[Y]]
; CHECK-NEXT: ret i32 [[DIV1]]
;
%c0 = icmp sge i32 %x, 0
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i32 %y, 0
call void @llvm.assume(i1 %c1)
%div = sdiv i32 %x, %y
ret i32 %div
}
define i32 @test7_pos_neg(i32 %x, i32 %y) {
; CHECK-LABEL: @test7_pos_neg(
; CHECK-NEXT: [[C0:%.*]] = icmp sge i32 [[X:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sle i32 [[Y:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[Y_NONNEG:%.*]] = sub i32 0, [[Y]]
; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X]], [[Y_NONNEG]]
; CHECK-NEXT: [[DIV1_NEG:%.*]] = sub i32 0, [[DIV1]]
; CHECK-NEXT: ret i32 [[DIV1_NEG]]
;
%c0 = icmp sge i32 %x, 0
call void @llvm.assume(i1 %c0)
%c1 = icmp sle i32 %y, 0
call void @llvm.assume(i1 %c1)
%div = sdiv i32 %x, %y
ret i32 %div
}
define i32 @test8_neg_pos(i32 %x, i32 %y) {
; CHECK-LABEL: @test8_neg_pos(
; CHECK-NEXT: [[C0:%.*]] = icmp sle i32 [[X:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i32 [[Y:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i32 0, [[X]]
; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X_NONNEG]], [[Y]]
; CHECK-NEXT: [[DIV1_NEG:%.*]] = sub i32 0, [[DIV1]]
; CHECK-NEXT: ret i32 [[DIV1_NEG]]
;
%c0 = icmp sle i32 %x, 0
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i32 %y, 0
call void @llvm.assume(i1 %c1)
%div = sdiv i32 %x, %y
ret i32 %div
}
define i32 @test9_neg_neg(i32 %x, i32 %y) {
; CHECK-LABEL: @test9_neg_neg(
; CHECK-NEXT: [[C0:%.*]] = icmp sle i32 [[X:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sle i32 [[Y:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i32 0, [[X]]
; CHECK-NEXT: [[Y_NONNEG:%.*]] = sub i32 0, [[Y]]
; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X_NONNEG]], [[Y_NONNEG]]
; CHECK-NEXT: ret i32 [[DIV1]]
;
%c0 = icmp sle i32 %x, 0
call void @llvm.assume(i1 %c0)
%c1 = icmp sle i32 %y, 0
call void @llvm.assume(i1 %c1)
%div = sdiv i32 %x, %y
ret i32 %div
}
; After making division unsigned, can we narrow it?
define i32 @test10_narrow(i32 %x, i32 %y) {
; CHECK-LABEL: @test10_narrow(
; CHECK-NEXT: [[C0:%.*]] = icmp ult i32 [[X:%.*]], 128
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 [[Y:%.*]], 128
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[DIV1_LHS_TRUNC:%.*]] = trunc i32 [[X]] to i8
; CHECK-NEXT: [[DIV1_RHS_TRUNC:%.*]] = trunc i32 [[Y]] to i8
; CHECK-NEXT: [[DIV12:%.*]] = udiv i8 [[DIV1_LHS_TRUNC]], [[DIV1_RHS_TRUNC]]
; CHECK-NEXT: [[DIV1_ZEXT:%.*]] = zext i8 [[DIV12]] to i32
; CHECK-NEXT: ret i32 [[DIV1_ZEXT]]
;
%c0 = icmp ult i32 %x, 128
call void @llvm.assume(i1 %c0)
%c1 = icmp ult i32 %y, 128
call void @llvm.assume(i1 %c1)
%div = sdiv i32 %x, %y
ret i32 %div
}
; Ok, but what about narrowing sdiv in general?
; If both operands are i15, it's uncontroversial - we can truncate to i16
define i64 @test11_i15_i15(i64 %x, i64 %y) {
; CHECK-LABEL: @test11_i15_i15(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 16383
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -16384
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 16383
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -16384
; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])
; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16
; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16
; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]
; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64
; CHECK-NEXT: ret i64 [[DIV_SEXT]]
;
entry:
%c0 = icmp sle i64 %x, 16383
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i64 %x, -16384
call void @llvm.assume(i1 %c1)
%c2 = icmp sle i64 %y, 16383
call void @llvm.assume(i1 %c2)
%c3 = icmp sge i64 %y, -16384
call void @llvm.assume(i1 %c3)
%div = sdiv i64 %x, %y
ret i64 %div
}
; But if operands are i16, we can only truncate to i32, because we can't
; rule out UB of i16 INT_MIN s/ i16 -1
define i64 @test12_i16_i16(i64 %x, i64 %y) {
; CHECK-LABEL: @test12_i16_i16(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -32768
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 32767
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -32768
; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])
; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32
; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32
; CHECK-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]
; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64
; CHECK-NEXT: ret i64 [[DIV_SEXT]]
;
entry:
%c0 = icmp sle i64 %x, 32767
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i64 %x, -32768
call void @llvm.assume(i1 %c1)
%c2 = icmp sle i64 %y, 32767
call void @llvm.assume(i1 %c2)
%c3 = icmp sge i64 %y, -32768
call void @llvm.assume(i1 %c3)
%div = sdiv i64 %x, %y
ret i64 %div
}
; But if divident is i16, and divisor is u15, then we know that i16 is UB-safe.
define i64 @test13_i16_u15(i64 %x, i64 %y) {
; CHECK-LABEL: @test13_i16_u15(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -32768
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp ule i64 [[Y:%.*]], 32767
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16
; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16
; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]
; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64
; CHECK-NEXT: ret i64 [[DIV_SEXT]]
;
entry:
%c0 = icmp sle i64 %x, 32767
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i64 %x, -32768
call void @llvm.assume(i1 %c1)
%c2 = icmp ule i64 %y, 32767
call void @llvm.assume(i1 %c2)
%div = sdiv i64 %x, %y
ret i64 %div
}
; And likewise, if we know that if the divident is never i16 INT_MIN,
; we can truncate to i16.
define i64 @test14_i16safe_i16(i64 %x, i64 %y) {
; CHECK-LABEL: @test14_i16safe_i16(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sgt i64 [[X]], -32768
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 32767
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -32768
; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])
; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16
; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16
; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]
; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64
; CHECK-NEXT: ret i64 [[DIV_SEXT]]
;
entry:
%c0 = icmp sle i64 %x, 32767
call void @llvm.assume(i1 %c0)
%c1 = icmp sgt i64 %x, -32768
call void @llvm.assume(i1 %c1)
%c2 = icmp sle i64 %y, 32767
call void @llvm.assume(i1 %c2)
%c3 = icmp sge i64 %y, -32768
call void @llvm.assume(i1 %c3)
%div = sdiv i64 %x, %y
ret i64 %div
}
; Of course, both of the conditions can happen at once.
define i64 @test15_i16safe_u15(i64 %x, i64 %y) {
; CHECK-LABEL: @test15_i16safe_u15(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sgt i64 [[X]], -32768
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp ule i64 [[Y:%.*]], 32767
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16
; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16
; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]
; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64
; CHECK-NEXT: ret i64 [[DIV_SEXT]]
;
entry:
%c0 = icmp sle i64 %x, 32767
call void @llvm.assume(i1 %c0)
%c1 = icmp sgt i64 %x, -32768
call void @llvm.assume(i1 %c1)
%c2 = icmp ule i64 %y, 32767
call void @llvm.assume(i1 %c2)
%div = sdiv i64 %x, %y
ret i64 %div
}
; We at most truncate to i8
define i64 @test16_i4_i4(i64 %x, i64 %y) {
; CHECK-LABEL: @test16_i4_i4(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 3
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -4
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 3
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -4
; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])
; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i8
; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i8
; CHECK-NEXT: [[DIV1:%.*]] = sdiv i8 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]
; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i8 [[DIV1]] to i64
; CHECK-NEXT: ret i64 [[DIV_SEXT]]
;
entry:
%c0 = icmp sle i64 %x, 3
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i64 %x, -4
call void @llvm.assume(i1 %c1)
%c2 = icmp sle i64 %y, 3
call void @llvm.assume(i1 %c2)
%c3 = icmp sge i64 %y, -4
call void @llvm.assume(i1 %c3)
%div = sdiv i64 %x, %y
ret i64 %div
}
; And we round up to the powers of two
define i64 @test17_i9_i9(i64 %x, i64 %y) {
; CHECK-LABEL: @test17_i9_i9(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 255
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -256
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 255
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -256
; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])
; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16
; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16
; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]
; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64
; CHECK-NEXT: ret i64 [[DIV_SEXT]]
;
entry:
%c0 = icmp sle i64 %x, 255
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i64 %x, -256
call void @llvm.assume(i1 %c1)
%c2 = icmp sle i64 %y, 255
call void @llvm.assume(i1 %c2)
%c3 = icmp sge i64 %y, -256
call void @llvm.assume(i1 %c3)
%div = sdiv i64 %x, %y
ret i64 %div
}
; Don't widen the operation to the next power of two if it wasn't a power of two.
define i9 @test18_i9_i9(i9 %x, i9 %y) {
; CHECK-LABEL: @test18_i9_i9(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i9 [[X:%.*]], 255
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i9 [[X]], -256
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp sle i9 [[Y:%.*]], 255
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[C3:%.*]] = icmp sge i9 [[Y]], -256
; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])
; CHECK-NEXT: [[DIV:%.*]] = sdiv i9 [[X]], [[Y]]
; CHECK-NEXT: ret i9 [[DIV]]
;
entry:
%c0 = icmp sle i9 %x, 255
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i9 %x, -256
call void @llvm.assume(i1 %c1)
%c2 = icmp sle i9 %y, 255
call void @llvm.assume(i1 %c2)
%c3 = icmp sge i9 %y, -256
call void @llvm.assume(i1 %c3)
%div = sdiv i9 %x, %y
ret i9 %div
}
define i10 @test19_i10_i10(i10 %x, i10 %y) {
; CHECK-LABEL: @test19_i10_i10(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i10 [[X:%.*]], 255
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i10 [[X]], -256
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp sle i10 [[Y:%.*]], 255
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[C3:%.*]] = icmp sge i10 [[Y]], -256
; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])
; CHECK-NEXT: [[DIV:%.*]] = sdiv i10 [[X]], [[Y]]
; CHECK-NEXT: ret i10 [[DIV]]
;
entry:
%c0 = icmp sle i10 %x, 255
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i10 %x, -256
call void @llvm.assume(i1 %c1)
%c2 = icmp sle i10 %y, 255
call void @llvm.assume(i1 %c2)
%c3 = icmp sge i10 %y, -256
call void @llvm.assume(i1 %c3)
%div = sdiv i10 %x, %y
ret i10 %div
}
; Note that we need to take the maximal bitwidth, in which both of the operands are representable!
define i64 @test20_i16_i18(i64 %x, i64 %y) {
; CHECK-LABEL: @test20_i16_i18(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 16383
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -16384
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 65535
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -65536
; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])
; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32
; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32
; CHECK-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]
; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64
; CHECK-NEXT: ret i64 [[DIV_SEXT]]
;
entry:
%c0 = icmp sle i64 %x, 16383
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i64 %x, -16384
call void @llvm.assume(i1 %c1)
%c2 = icmp sle i64 %y, 65535
call void @llvm.assume(i1 %c2)
%c3 = icmp sge i64 %y, -65536
call void @llvm.assume(i1 %c3)
%div = sdiv i64 %x, %y
ret i64 %div
}
define i64 @test21_i18_i16(i64 %x, i64 %y) {
; CHECK-LABEL: @test21_i18_i16(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 65535
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -65536
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 16383
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -16384
; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])
; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32
; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32
; CHECK-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]
; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64
; CHECK-NEXT: ret i64 [[DIV_SEXT]]
;
entry:
%c0 = icmp sle i64 %x, 65535
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i64 %x, -65536
call void @llvm.assume(i1 %c1)
%c2 = icmp sle i64 %y, 16383
call void @llvm.assume(i1 %c2)
%c3 = icmp sge i64 %y, -16384
call void @llvm.assume(i1 %c3)
%div = sdiv i64 %x, %y
ret i64 %div
}
; Ensure that we preserve exact-ness
define i64 @test22_i16_i16(i64 %x, i64 %y) {
; CHECK-LABEL: @test22_i16_i16(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767
; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])
; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -32768
; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])
; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 32767
; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])
; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -32768
; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])
; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32
; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32
; CHECK-NEXT: [[DIV1:%.*]] = sdiv exact i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]
; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64
; CHECK-NEXT: ret i64 [[DIV_SEXT]]
;
entry:
%c0 = icmp sle i64 %x, 32767
call void @llvm.assume(i1 %c0)
%c1 = icmp sge i64 %x, -32768
call void @llvm.assume(i1 %c1)
%c2 = icmp sle i64 %y, 32767
call void @llvm.assume(i1 %c2)
%c3 = icmp sge i64 %y, -32768
call void @llvm.assume(i1 %c3)
%div = sdiv exact i64 %x, %y
ret i64 %div
}