; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
define i32 @test_ult_254_inc_imm(i8 zeroext %x) {
; CHECK-LABEL: @test_ult_254_inc_imm(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[X:%.*]] to i32
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], -255
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], -2
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%add = add i8 %x, 1
%cmp = icmp ult i8 %add, 254
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define i32 @test_slt_254_inc_imm(i8 signext %x) {
; CHECK-LABEL: @test_slt_254_inc_imm(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X:%.*]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[ADD]], -2
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%add = add i8 %x, 1
%cmp = icmp slt i8 %add, 254
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define i32 @test_ult_254_inc_var(i8 zeroext %x, i8 zeroext %y) {
; CHECK-LABEL: @test_ult_254_inc_var(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[ADD]], -2
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%add = add i8 %x, %y
%cmp = icmp ult i8 %add, 254
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define i32 @test_sle_254_inc_var(i8 %x, i8 %y) {
; CHECK-LABEL: @test_sle_254_inc_var(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[ADD]], -2
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%add = add i8 %x, %y
%cmp = icmp sle i8 %add, 254
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define i32 @test_ugt_1_dec_imm(i8 zeroext %x) {
; CHECK-LABEL: @test_ugt_1_dec_imm(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[X:%.*]] to i32
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD]], 1
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%add = add i8 %x, -1
%cmp = icmp ugt i8 %add, 1
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define i32 @test_sgt_1_dec_imm(i8 %x) {
; CHECK-LABEL: @test_sgt_1_dec_imm(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X:%.*]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[ADD]], 1
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%add = add i8 %x, -1
%cmp = icmp sgt i8 %add, 1
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define i32 @test_ugt_1_dec_var(i8 zeroext %x, i8 zeroext %y) {
; CHECK-LABEL: @test_ugt_1_dec_var(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[SUB]], 1
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%sub = sub i8 %x, %y
%cmp = icmp ugt i8 %sub, 1
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define i32 @test_sge_1_dec_var(i8 %x, i8 %y) {
; CHECK-LABEL: @test_sge_1_dec_var(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[SUB]], 1
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%sub = sub i8 %x, %y
%cmp = icmp sge i8 %sub, 1
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define i32 @dsp_imm1(i8 zeroext %x, i8 zeroext %y) {
; CHECK-LABEL: @dsp_imm1(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], 7
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[AND]], [[XOR]]
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[SUB]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[ADD]], -2
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%xor = xor i8 %x, %y
%and = and i8 %x, 7
%sub = sub i8 %and, %xor
%add = add i8 %sub, 1
%cmp = icmp ult i8 %add, 254
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define i32 @dsp_var(i8 zeroext %x, i8 zeroext %y) {
; CHECK-LABEL: @dsp_var(
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], 7
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[AND]], [[XOR]]
; CHECK-NEXT: [[MUL:%.*]] = shl nuw i8 [[X]], 1
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[SUB]], [[MUL]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[ADD]], -2
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
%xor = xor i8 %x, %y
%and = and i8 %x, 7
%sub = sub i8 %and, %xor
%mul = shl nuw i8 %x, 1
%add = add i8 %sub, %mul
%cmp = icmp ult i8 %add, 254
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define void @store_dsp_res(ptr %in, ptr %out, i8 %compare) {
; CHECK-LABEL: @store_dsp_res(
; CHECK-NEXT: [[SECOND:%.*]] = getelementptr inbounds i8, ptr [[IN:%.*]], i32 1
; CHECK-NEXT: [[LD0:%.*]] = load i8, ptr [[IN]], align 1
; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[SECOND]], align 1
; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[LD0]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[COMPARE:%.*]], [[LD1]]
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i8 [[COMPARE]], i8 [[XOR]]
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[LD0]], [[SELECT]]
; CHECK-NEXT: store i8 [[SUB]], ptr [[OUT:%.*]], align 1
; CHECK-NEXT: ret void
;
%second = getelementptr inbounds i8, ptr %in, i32 1
%ld0 = load i8, ptr %in
%ld1 = load i8, ptr %second
%xor = xor i8 %ld0, -1
%cmp = icmp ult i8 %compare, %ld1
%select = select i1 %cmp, i8 %compare, i8 %xor
%sub = sub i8 %ld0, %select
store i8 %sub, ptr %out, align 1
ret void
}
define i32 @ugt_1_dec_imm(i8 zeroext %x) {
; CHECK-LABEL: @ugt_1_dec_imm(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[X:%.*]] to i32
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD]], 1
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%add = add i8 %x, -1
%cmp = icmp ugt i8 %add, 1
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define i32 @ugt_1_dec_var(i8 zeroext %x, i8 zeroext %y) {
; CHECK-LABEL: @ugt_1_dec_var(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[SUB]], 1
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%sub = sub i8 %x, %y
%cmp = icmp ugt i8 %sub, 1
%res = select i1 %cmp, i32 35, i32 47
ret i32 %res
}
define i32 @icmp_eq_minus_one(ptr %ptr) {
; CHECK-LABEL: @icmp_eq_minus_one(
; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR:%.*]], align 1
; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[LOAD]] to i32
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[LOAD]], -1
; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP]], i32 [[CONV]], i32 -1
; CHECK-NEXT: ret i32 [[RET]]
;
%load = load i8, ptr %ptr, align 1
%conv = zext i8 %load to i32
%cmp = icmp eq i8 %load, -1
%ret = select i1 %cmp, i32 %conv, i32 -1
ret i32 %ret
}
define i32 @icmp_not(i16 zeroext %arg0, i16 zeroext %arg1) {
; CHECK-LABEL: @icmp_not(
; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[ARG0:%.*]] to i32
; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[ARG1:%.*]] to i32
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[TMP1]], 65535
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[NOT]], [[TMP2]]
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 16, i32 32
; CHECK-NEXT: ret i32 [[RES]]
;
%not = xor i16 %arg0, -1
%cmp = icmp eq i16 %not, %arg1
%res = select i1 %cmp, i32 16, i32 32
ret i32 %res
}
define i32 @icmp_i1(ptr %arg0, i1 zeroext %arg1, i32 %a, i32 %b) {
; CHECK-LABEL: @icmp_i1(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LOAD:%.*]] = load i1, ptr [[ARG0:%.*]], align 1
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[LOAD]], true
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i1 [[ARG1:%.*]], [[NOT]]
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 [[A:%.*]], i32 [[B:%.*]]
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%load = load i1, ptr %arg0
%not = xor i1 %load, 1
%cmp = icmp eq i1 %arg1, %not
%res = select i1 %cmp, i32 %a, i32 %b
ret i32 %res
}
define i32 @icmp_i7(ptr %arg0, i7 zeroext %arg1, i32 %a, i32 %b) {
; CHECK-LABEL: @icmp_i7(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = zext i7 [[ARG1:%.*]] to i32
; CHECK-NEXT: [[LOAD:%.*]] = load i7, ptr [[ARG0:%.*]], align 1
; CHECK-NEXT: [[TMP1:%.*]] = zext i7 [[LOAD]] to i32
; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[TMP1]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP0]], [[ADD]]
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 [[A:%.*]], i32 [[B:%.*]]
; CHECK-NEXT: ret i32 [[RES]]
;
entry:
%load = load i7, ptr %arg0
%add = add nuw i7 %load, 1
%cmp = icmp ult i7 %arg1, %add
%res = select i1 %cmp, i32 %a, i32 %b
ret i32 %res
}
define i32 @icmp_i15(i15 zeroext %arg0, i15 zeroext %arg1) {
; CHECK-LABEL: @icmp_i15(
; CHECK-NEXT: [[TMP1:%.*]] = zext i15 [[ARG0:%.*]] to i32
; CHECK-NEXT: [[TMP2:%.*]] = zext i15 [[ARG1:%.*]] to i32
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[TMP1]], 32767
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[TMP2]]
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 21, i32 42
; CHECK-NEXT: ret i32 [[RES]]
;
%xor = xor i15 %arg0, -1
%cmp = icmp eq i15 %xor, %arg1
%res = select i1 %cmp, i32 21, i32 42
ret i32 %res
}
define i32 @icmp_minus_imm(ptr %a) {
; CHECK-LABEL: @icmp_minus_imm(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[A:%.*]], align 1
; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
; CHECK-NEXT: [[ADD_I:%.*]] = add i32 [[TMP1]], -7
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD_I]], -5
; CHECK-NEXT: [[CONV1:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV1]]
;
entry:
%0 = load i8, ptr %a, align 1
%add.i = add i8 %0, -7
%cmp = icmp ugt i8 %add.i, -5
%conv1 = zext i1 %cmp to i32
ret i32 %conv1
}
define i32 @icmp_minus_imm_noncanonicalcmp(ptr %a) {
; CHECK-LABEL: @icmp_minus_imm_noncanonicalcmp(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[A:%.*]], align 1
; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32
; CHECK-NEXT: [[ADD_I:%.*]] = add i32 [[TMP1]], -7
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 -5, [[ADD_I]]
; CHECK-NEXT: [[CONV1:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV1]]
;
entry:
%0 = load i8, ptr %a, align 1
%add.i = add i8 %0, -7
%cmp = icmp ult i8 -5, %add.i
%conv1 = zext i1 %cmp to i32
ret i32 %conv1
}
define void @mul_with_neg_imm(i32, ptr %b) {
; CHECK-LABEL: @mul_with_neg_imm(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32
; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 1
; CHECK-NEXT: [[CONV_I:%.*]] = mul nuw i32 [[TMP3]], 132
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[CONV_I]], 0
; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
; CHECK: if.then:
; CHECK-NEXT: store i32 0, ptr [[B:%.*]], align 4
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: ret void
;
entry:
%1 = trunc i32 %0 to i8
%2 = and i8 %1, 1
%conv.i = mul nuw i8 %2, -124
%tobool = icmp eq i8 %conv.i, 0
br i1 %tobool, label %if.end, label %if.then
if.then:
store i32 0, ptr %b, align 4
br label %if.end
if.end:
ret void
}
define i32 @degenerateicmp() {
; CHECK-LABEL: @degenerateicmp(
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 190, 0
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 225, [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 1, i32 0
; CHECK-NEXT: ret i32 [[TMP3]]
;
%1 = sub i8 -66, 0
%2 = icmp ugt i8 -31, %1
%3 = select i1 %2, i32 1, i32 0
ret i32 %3
}
define i1 @pr55490() {
; CHECK-LABEL: @pr55490(
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 10, 8
; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 3
; CHECK-NEXT: ret i1 [[TMP2]]
;
%1 = sub i4 -6, -8
%2 = icmp ult i4 %1, 3
ret i1 %2
}