blob: 0e996e5d017feece1913f0869573c43193f61d76 [file] [log] [blame]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
declare void @use(i8)
define i1 @test1(i32 %i, ptr %p) {
; CHECK-LABEL: define i1 @test1(
; CHECK-SAME: i32 [[I:%.*]], ptr [[P:%.*]]) {
; CHECK-NEXT: [[DOTLOBIT:%.*]] = lshr i32 [[I]], 31
; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[P]], align 1
; CHECK-NEXT: ret i1 false
;
%lobit = lshr i32 %i, 31
%t = trunc nuw i32 %lobit to i1
%b = icmp slt i32 %i, 0
%not = xor i1 %t, true
%op = select i1 %not, i1 %b, i1 false
store i32 %lobit, ptr %p, align 1
ret i1 %op
}
define i1 @test2(i32 %i, ptr %p) {
; CHECK-LABEL: define i1 @test2(
; CHECK-SAME: i32 [[I:%.*]], ptr [[P:%.*]]) {
; CHECK-NEXT: [[DOTLOBIT:%.*]] = ashr i32 [[I]], 31
; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[P]], align 1
; CHECK-NEXT: ret i1 false
;
%lobit = ashr i32 %i, 31
%t = trunc nuw i32 %lobit to i1
%b = icmp slt i32 %i, 0
%not = xor i1 %t, true
%op = select i1 %not, i1 %b, i1 false
store i32 %lobit, ptr %p, align 1
ret i1 %op
}
define i1 @test3(i32 %i, ptr %p, ptr %q) {
; CHECK-LABEL: define i1 @test3(
; CHECK-SAME: i32 [[I:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]]) {
; CHECK-NEXT: [[DOTLOBIT:%.*]] = lshr i32 [[I]], 31
; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[P]], align 1
; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[Q]], align 1
; CHECK-NEXT: ret i1 false
;
%lobit = lshr i32 %i, 31
%t = trunc nuw i32 %lobit to i1
%b = icmp slt i32 %i, 0
%not = xor i1 %t, true
%op = select i1 %not, i1 %b, i1 false
store i32 %lobit, ptr %p, align 1
store i32 %lobit, ptr %q, align 1
ret i1 %op
}
; Negative Test
define i1 @test4(i32 %i, ptr %p) {
; CHECK-LABEL: define i1 @test4(
; CHECK-SAME: i32 [[I:%.*]], ptr [[P:%.*]]) {
; CHECK-NEXT: [[DOTLOBIT:%.*]] = lshr i32 [[I]], 30
; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[DOTLOBIT]] to i1
; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[I]], 0
; CHECK-NEXT: [[NOT_:%.*]] = xor i1 [[T]], true
; CHECK-NEXT: [[COMMON_RET1_OP:%.*]] = select i1 [[NOT_]], i1 [[B]], i1 false
; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[P]], align 1
; CHECK-NEXT: ret i1 [[COMMON_RET1_OP]]
;
%lobit = lshr i32 %i, 30 ; should not fold as no. of bits shifted < BitWidth - 1
%t = trunc nuw i32 %lobit to i1
%b = icmp slt i32 %i, 0
%not = xor i1 %t, true
%op = select i1 %not, i1 %b, i1 false
store i32 %lobit, ptr %p, align 1
ret i1 %op
}
; Negative Test
define i1 @test5(i32 %i, ptr %p) {
; CHECK-LABEL: define i1 @test5(
; CHECK-SAME: i32 [[I:%.*]], ptr [[P:%.*]]) {
; CHECK-NEXT: [[DOTLOBIT:%.*]] = ashr i32 [[I]], 30
; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[DOTLOBIT]] to i1
; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[I]], 0
; CHECK-NEXT: [[NOT_:%.*]] = xor i1 [[T]], true
; CHECK-NEXT: [[COMMON_RET1_OP:%.*]] = select i1 [[NOT_]], i1 [[B]], i1 false
; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[P]], align 1
; CHECK-NEXT: ret i1 [[COMMON_RET1_OP]]
;
%lobit = ashr i32 %i, 30 ; should not fold as no. of bits shifted < BitWidth - 1
%t = trunc nuw i32 %lobit to i1
%b = icmp slt i32 %i, 0
%not = xor i1 %t, true
%op = select i1 %not, i1 %b, i1 false
store i32 %lobit, ptr %p, align 1
ret i1 %op
}
define i1 @fold_lshr_power_of_2(i8 %x) {
; CHECK-LABEL: define i1 @fold_lshr_power_of_2(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[TRUNC:%.*]] = icmp eq i8 [[X]], 4
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%lshr = lshr i8 16, %x ; 16 is a power of 2
%trunc = trunc i8 %lshr to i1
ret i1 %trunc
}
define i1 @fold_lshr_power_of_2_minus_1(i8 %x) {
; CHECK-LABEL: define i1 @fold_lshr_power_of_2_minus_1(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[TRUNC:%.*]] = icmp ult i8 [[X]], 4
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%lshr = lshr i8 15, %x
%trunc = trunc i8 %lshr to i1
ret i1 %trunc
}
define i1 @fold_ashr_power_of_2(i8 %x) {
; CHECK-LABEL: define i1 @fold_ashr_power_of_2(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[TRUNC:%.*]] = icmp eq i8 [[X]], 4
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%ashr = ashr i8 16, %x
%trunc = trunc i8 %ashr to i1
ret i1 %trunc
}
define i1 @fold_ashr_power_of_2_minus_1(i8 %x) {
; CHECK-LABEL: define i1 @fold_ashr_power_of_2_minus_1(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[TRUNC:%.*]] = icmp ult i8 [[X]], 4
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%ashr = ashr i8 15, %x ; (15 + 1) is a power of 2
%trunc = trunc i8 %ashr to i1
ret i1 %trunc
}
define i1 @fold_lshr_power_of_2_multi_use(i8 %x) {
; CHECK-LABEL: define i1 @fold_lshr_power_of_2_multi_use(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 16, [[X]]
; CHECK-NEXT: call void @use(i8 [[LSHR]])
; CHECK-NEXT: [[TRUNC:%.*]] = icmp eq i8 [[X]], 4
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%lshr = lshr i8 16, %x ; 16 is a power of 2
call void @use(i8 %lshr)
%trunc = trunc i8 %lshr to i1
ret i1 %trunc
}
define i1 @fold_lshr_power_of_2_minus_1_multi_use(i8 %x) {
; CHECK-LABEL: define i1 @fold_lshr_power_of_2_minus_1_multi_use(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 15, [[X]]
; CHECK-NEXT: call void @use(i8 [[LSHR]])
; CHECK-NEXT: [[TRUNC:%.*]] = icmp ult i8 [[X]], 4
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%lshr = lshr i8 15, %x
call void @use(i8 %lshr)
%trunc = trunc i8 %lshr to i1
ret i1 %trunc
}
define i1 @fold_ashr_power_of_2_multi_use(i8 %x) {
; CHECK-LABEL: define i1 @fold_ashr_power_of_2_multi_use(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[ASHR:%.*]] = lshr i8 16, [[X]]
; CHECK-NEXT: call void @use(i8 [[ASHR]])
; CHECK-NEXT: [[TRUNC:%.*]] = icmp eq i8 [[X]], 4
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%ashr = ashr i8 16, %x
call void @use(i8 %ashr)
%trunc = trunc i8 %ashr to i1
ret i1 %trunc
}
define i1 @fold_ashr_power_of_2_minus_1_multi_use(i8 %x) {
; CHECK-LABEL: define i1 @fold_ashr_power_of_2_minus_1_multi_use(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[ASHR:%.*]] = lshr i8 15, [[X]]
; CHECK-NEXT: call void @use(i8 [[ASHR]])
; CHECK-NEXT: [[TRUNC:%.*]] = icmp ult i8 [[X]], 4
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%ashr = ashr i8 15, %x ; (15 + 1) is a power of 2
call void @use(i8 %ashr)
%trunc = trunc i8 %ashr to i1
ret i1 %trunc
}
define i1 @negative_test_fold_lshr(i8 %x) {
; CHECK-LABEL: define i1 @negative_test_fold_lshr(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 9, [[X]]
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[LSHR]] to i1
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%lshr = lshr i8 9, %x ; 9 or (9 + 1) is not a power of 2
%trunc = trunc i8 %lshr to i1
ret i1 %trunc
}
; Negative Test for arithmetic shift right
define i1 @negative_test_fold_ashr(i8 %x) {
; CHECK-LABEL: define i1 @negative_test_fold_ashr(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[ASHR:%.*]] = lshr i8 9, [[X]]
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[ASHR]] to i1
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%ashr = ashr i8 9, %x ; 9 or (9 + 1) is not a power of 2
%trunc = trunc i8 %ashr to i1
ret i1 %trunc
}
define i1 @fold_lshr_negated_power_of_2(i8 %x) {
; CHECK-LABEL: define i1 @fold_lshr_negated_power_of_2(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%lshr = lshr i8 -16, %x
%trunc = trunc i8 %lshr to i1
ret i1 %trunc
}
define i1 @fold_ashr_negated_power_of_2(i8 %x) {
; CHECK-LABEL: define i1 @fold_ashr_negated_power_of_2(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%ashr = ashr i8 -16, %x
%trunc = trunc i8 %ashr to i1
ret i1 %trunc
}
define i1 @fold_lshr_negated_power_of_2_multi_use(i8 %x) {
; CHECK-LABEL: define i1 @fold_lshr_negated_power_of_2_multi_use(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 -16, [[X]]
; CHECK-NEXT: call void @use(i8 [[LSHR]])
; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%lshr = lshr i8 -16, %x
call void @use(i8 %lshr)
%trunc = trunc i8 %lshr to i1
ret i1 %trunc
}
define i1 @fold_ashr_negated_power_of_2_multi_use(i8 %x) {
; CHECK-LABEL: define i1 @fold_ashr_negated_power_of_2_multi_use(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[ASHR:%.*]] = ashr i8 -16, [[X]]
; CHECK-NEXT: call void @use(i8 [[ASHR]])
; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%ashr = ashr i8 -16, %x
call void @use(i8 %ashr)
%trunc = trunc i8 %ashr to i1
ret i1 %trunc
}
define i1 @negative_test_fold_lshr_negated_power_of_2(i8 %x) {
; CHECK-LABEL: define i1 @negative_test_fold_lshr_negated_power_of_2(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 -17, [[X]]
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[LSHR]] to i1
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%lshr = lshr i8 -17, %x
%trunc = trunc i8 %lshr to i1
ret i1 %trunc
}
define i1 @negative_test_fold_ashr_negated_power_of_2(i8 %x) {
; CHECK-LABEL: define i1 @negative_test_fold_ashr_negated_power_of_2(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[ASHR1:%.*]] = lshr i8 -17, [[X]]
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[ASHR1]] to i1
; CHECK-NEXT: ret i1 [[TRUNC]]
;
%ashr = ashr i8 -17, %x
%trunc = trunc i8 %ashr to i1
ret i1 %trunc
}