; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instcombine -S | FileCheck %s target datalayout = "n32" define i1 @is_rem2_neg_i8(i8 %x) { ; CHECK-LABEL: @is_rem2_neg_i8( ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -127 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP1]], -127 ; CHECK-NEXT: ret i1 [[R]] ; %s = srem i8 %x, 2 %r = icmp slt i8 %s, 0 ret i1 %r } define <2 x i1> @is_rem2_pos_v2i8(<2 x i8> %x) { ; CHECK-LABEL: @is_rem2_pos_v2i8( ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[TMP1]], ; CHECK-NEXT: ret <2 x i1> [[R]] ; %s = srem <2 x i8> %x, %r = icmp sgt <2 x i8> %s, zeroinitializer ret <2 x i1> %r } ; i8 -97 == 159 == 0b10011111 define i1 @is_rem32_pos_i8(i8 %x) { ; CHECK-LABEL: @is_rem32_pos_i8( ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -97 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %s = srem i8 %x, 32 %r = icmp sgt i8 %s, 0 ret i1 %r } ; i16 -32765 == 32771 == 0b1000000000000011 define i1 @is_rem4_neg_i16(i16 %x) { ; CHECK-LABEL: @is_rem4_neg_i16( ; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], -32765 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i16 [[TMP1]], -32768 ; CHECK-NEXT: ret i1 [[R]] ; %s = srem i16 %x, 4 %r = icmp slt i16 %s, 0 ret i1 %r } declare void @use(i32) ; TODO: This is still worth folding because srem is difficult? define i1 @is_rem32_neg_i32_extra_use(i32 %x) { ; CHECK-LABEL: @is_rem32_neg_i32_extra_use( ; CHECK-NEXT: [[S:%.*]] = srem i32 [[X:%.*]], 32 ; CHECK-NEXT: call void @use(i32 [[S]]) ; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[S]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %s = srem i32 %x, 32 call void @use(i32 %s) %r = icmp slt i32 %s, 0 ret i1 %r } ; Negative test - wrong compare constant define i1 @is_rem8_nonneg_i16(i16 %x) { ; CHECK-LABEL: @is_rem8_nonneg_i16( ; CHECK-NEXT: [[S:%.*]] = srem i16 [[X:%.*]], 8 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i16 [[S]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %s = srem i16 %x, 8 %r = icmp sgt i16 %s, -1 ret i1 %r } ; Negative test - wrong remainder constant define i1 @is_rem3_neg_i8(i8 %x) { ; CHECK-LABEL: @is_rem3_neg_i8( ; CHECK-NEXT: [[S:%.*]] = srem i8 [[X:%.*]], 3 ; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[S]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %s = srem i8 %x, 3 %r = icmp slt i8 %s, 0 ret i1 %r } ; Negative test - wrong compare constant define i1 @is_rem16_something_i8(i8 %x) { ; CHECK-LABEL: @is_rem16_something_i8( ; CHECK-NEXT: [[S:%.*]] = srem i8 [[X:%.*]], 16 ; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[S]], 7 ; CHECK-NEXT: ret i1 [[R]] ; %s = srem i8 %x, 16 %r = icmp slt i8 %s, 7 ret i1 %r } ; PR30281 - https://llvm.org/bugs/show_bug.cgi?id=30281 ; All of these tests contain foldable division-by-constant instructions, but we ; can't assert that those folds have occurred before we process the later icmp. define i32 @icmp_div(i16 %a, i16 %c) { ; CHECK-LABEL: @icmp_div( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 ; CHECK-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[C:%.*]], 0 ; CHECK-NEXT: [[PHI_BO:%.*]] = sext i1 [[CMP]] to i32 ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[PHI_BO]], [[THEN]] ] ; CHECK-NEXT: ret i32 [[PHI]] ; entry: %tobool = icmp eq i16 %a, 0 br i1 %tobool, label %then, label %exit then: %div = sdiv i16 %c, -1 %cmp = icmp ne i16 %div, 0 br label %exit exit: %phi = phi i1 [ false, %entry ], [ %cmp, %then ] %zext = zext i1 %phi to i32 %add = add nsw i32 %zext, -1 ret i32 %add } define i32 @icmp_div2(i16 %a, i16 %c) { ; CHECK-LABEL: @icmp_div2( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 ; CHECK-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret i32 -1 ; entry: %tobool = icmp eq i16 %a, 0 br i1 %tobool, label %then, label %exit then: %div = sdiv i16 %c, 0 %cmp = icmp ne i16 %div, 0 br label %exit exit: %phi = phi i1 [ false, %entry ], [ %cmp, %then ] %zext = zext i1 %phi to i32 %add = add nsw i32 %zext, -1 ret i32 %add } define i32 @icmp_div3(i16 %a, i16 %c) { ; CHECK-LABEL: @icmp_div3( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 ; CHECK-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[C:%.*]], 0 ; CHECK-NEXT: [[PHI_BO:%.*]] = sext i1 [[CMP]] to i32 ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[PHI_BO]], [[THEN]] ] ; CHECK-NEXT: ret i32 [[PHI]] ; entry: %tobool = icmp eq i16 %a, 0 br i1 %tobool, label %then, label %exit then: %div = sdiv i16 %c, 1 %cmp = icmp ne i16 %div, 0 br label %exit exit: %phi = phi i1 [ false, %entry ], [ %cmp, %then ] %zext = zext i1 %phi to i32 %add = add nsw i32 %zext, -1 ret i32 %add }