1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; PR1949 5 6define i1 @test1(i32 %a) { 7; CHECK-LABEL: @test1( 8; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 %a, -5 9; CHECK-NEXT: ret i1 [[C]] 10; 11 %b = add i32 %a, 4 12 %c = icmp ult i32 %b, 4 13 ret i1 %c 14} 15 16define <2 x i1> @test1vec(<2 x i32> %a) { 17; CHECK-LABEL: @test1vec( 18; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i32> %a, <i32 -5, i32 -5> 19; CHECK-NEXT: ret <2 x i1> [[C]] 20; 21 %b = add <2 x i32> %a, <i32 4, i32 4> 22 %c = icmp ult <2 x i32> %b, <i32 4, i32 4> 23 ret <2 x i1> %c 24} 25 26define i1 @test2(i32 %a) { 27; CHECK-LABEL: @test2( 28; CHECK-NEXT: [[C:%.*]] = icmp ult i32 %a, 4 29; CHECK-NEXT: ret i1 [[C]] 30; 31 %b = sub i32 %a, 4 32 %c = icmp ugt i32 %b, -5 33 ret i1 %c 34} 35 36define <2 x i1> @test2vec(<2 x i32> %a) { 37; CHECK-LABEL: @test2vec( 38; CHECK-NEXT: [[C:%.*]] = icmp ult <2 x i32> %a, <i32 4, i32 4> 39; CHECK-NEXT: ret <2 x i1> [[C]] 40; 41 %b = sub <2 x i32> %a, <i32 4, i32 4> 42 %c = icmp ugt <2 x i32> %b, <i32 -5, i32 -5> 43 ret <2 x i1> %c 44} 45 46define i1 @test3(i32 %a) { 47; CHECK-LABEL: @test3( 48; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 %a, 2147483643 49; CHECK-NEXT: ret i1 [[C]] 50; 51 %b = add i32 %a, 4 52 %c = icmp slt i32 %b, 2147483652 53 ret i1 %c 54} 55 56define <2 x i1> @test3vec(<2 x i32> %a) { 57; CHECK-LABEL: @test3vec( 58; CHECK-NEXT: [[C:%.*]] = icmp sgt <2 x i32> %a, <i32 2147483643, i32 2147483643> 59; CHECK-NEXT: ret <2 x i1> [[C]] 60; 61 %b = add <2 x i32> %a, <i32 4, i32 4> 62 %c = icmp slt <2 x i32> %b, <i32 2147483652, i32 2147483652> 63 ret <2 x i1> %c 64} 65 66define i1 @test4(i32 %a) { 67; CHECK-LABEL: @test4( 68; CHECK-NEXT: [[C:%.*]] = icmp slt i32 %a, -4 69; CHECK-NEXT: ret i1 [[C]] 70; 71 %b = add i32 %a, 2147483652 72 %c = icmp sge i32 %b, 4 73 ret i1 %c 74} 75 76define <2 x i1> @test4vec(<2 x i32> %a) { 77; CHECK-LABEL: @test4vec( 78; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i32> %a, <i32 -4, i32 -4> 79; CHECK-NEXT: ret <2 x i1> [[C]] 80; 81 %b = add <2 x i32> %a, <i32 2147483652, i32 2147483652> 82 %c = icmp sge <2 x i32> %b, <i32 4, i32 4> 83 ret <2 x i1> %c 84} 85 86; icmp Pred (add nsw X, C2), C --> icmp Pred X, (C - C2), when C - C2 does not overflow. 87; This becomes equality because it's at the limit. 88 89define i1 @nsw_slt1(i8 %a) { 90; CHECK-LABEL: @nsw_slt1( 91; CHECK-NEXT: [[C:%.*]] = icmp eq i8 %a, -128 92; CHECK-NEXT: ret i1 [[C]] 93; 94 %b = add nsw i8 %a, 100 95 %c = icmp slt i8 %b, -27 96 ret i1 %c 97} 98 99define <2 x i1> @nsw_slt1_splat_vec(<2 x i8> %a) { 100; CHECK-LABEL: @nsw_slt1_splat_vec( 101; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i8> [[A:%.*]], <i8 -128, i8 -128> 102; CHECK-NEXT: ret <2 x i1> [[C]] 103; 104 %b = add nsw <2 x i8> %a, <i8 100, i8 100> 105 %c = icmp slt <2 x i8> %b, <i8 -27, i8 -27> 106 ret <2 x i1> %c 107} 108 109; icmp Pred (add nsw X, C2), C --> icmp Pred X, (C - C2), when C - C2 does not overflow. 110; This becomes equality because it's at the limit. 111 112define i1 @nsw_slt2(i8 %a) { 113; CHECK-LABEL: @nsw_slt2( 114; CHECK-NEXT: [[C:%.*]] = icmp ne i8 %a, 127 115; CHECK-NEXT: ret i1 [[C]] 116; 117 %b = add nsw i8 %a, -100 118 %c = icmp slt i8 %b, 27 119 ret i1 %c 120} 121 122define <2 x i1> @nsw_slt2_splat_vec(<2 x i8> %a) { 123; CHECK-LABEL: @nsw_slt2_splat_vec( 124; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> [[A:%.*]], <i8 127, i8 127> 125; CHECK-NEXT: ret <2 x i1> [[C]] 126; 127 %b = add nsw <2 x i8> %a, <i8 -100, i8 -100> 128 %c = icmp slt <2 x i8> %b, <i8 27, i8 27> 129 ret <2 x i1> %c 130} 131 132; icmp Pred (add nsw X, C2), C --> icmp Pred X, (C - C2), when C - C2 does not overflow. 133; Less than the limit, so the predicate doesn't change. 134 135define i1 @nsw_slt3(i8 %a) { 136; CHECK-LABEL: @nsw_slt3( 137; CHECK-NEXT: [[C:%.*]] = icmp slt i8 %a, -126 138; CHECK-NEXT: ret i1 [[C]] 139; 140 %b = add nsw i8 %a, 100 141 %c = icmp slt i8 %b, -26 142 ret i1 %c 143} 144 145; icmp Pred (add nsw X, C2), C --> icmp Pred X, (C - C2), when C - C2 does not overflow. 146; Less than the limit, so the predicate doesn't change. 147 148define i1 @nsw_slt4(i8 %a) { 149; CHECK-LABEL: @nsw_slt4( 150; CHECK-NEXT: [[C:%.*]] = icmp slt i8 %a, 126 151; CHECK-NEXT: ret i1 [[C]] 152; 153 %b = add nsw i8 %a, -100 154 %c = icmp slt i8 %b, 26 155 ret i1 %c 156} 157 158; icmp Pred (add nsw X, C2), C --> icmp Pred X, (C - C2), when C - C2 does not overflow. 159; Try sgt to make sure that works too. 160 161define i1 @nsw_sgt1(i8 %a) { 162; CHECK-LABEL: @nsw_sgt1( 163; CHECK-NEXT: [[C:%.*]] = icmp eq i8 %a, 127 164; CHECK-NEXT: ret i1 [[C]] 165; 166 %b = add nsw i8 %a, -100 167 %c = icmp sgt i8 %b, 26 168 ret i1 %c 169} 170 171define <2 x i1> @nsw_sgt1_splat_vec(<2 x i8> %a) { 172; CHECK-LABEL: @nsw_sgt1_splat_vec( 173; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i8> [[A:%.*]], <i8 127, i8 127> 174; CHECK-NEXT: ret <2 x i1> [[C]] 175; 176 %b = add nsw <2 x i8> %a, <i8 -100, i8 -100> 177 %c = icmp sgt <2 x i8> %b, <i8 26, i8 26> 178 ret <2 x i1> %c 179} 180 181define i1 @nsw_sgt2(i8 %a) { 182; CHECK-LABEL: @nsw_sgt2( 183; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[A:%.*]], -126 184; CHECK-NEXT: ret i1 [[C]] 185; 186 %b = add nsw i8 %a, 100 187 %c = icmp sgt i8 %b, -26 188 ret i1 %c 189} 190 191define <2 x i1> @nsw_sgt2_splat_vec(<2 x i8> %a) { 192; CHECK-LABEL: @nsw_sgt2_splat_vec( 193; CHECK-NEXT: [[C:%.*]] = icmp sgt <2 x i8> %a, <i8 -126, i8 -126> 194; CHECK-NEXT: ret <2 x i1> [[C]] 195; 196 %b = add nsw <2 x i8> %a, <i8 100, i8 100> 197 %c = icmp sgt <2 x i8> %b, <i8 -26, i8 -26> 198 ret <2 x i1> %c 199} 200 201; icmp Pred (add nsw X, C2), C --> icmp Pred X, (C - C2), when C - C2 does not overflow. 202; Comparison with 0 doesn't need special-casing. 203 204define i1 @slt_zero_add_nsw(i32 %a) { 205; CHECK-LABEL: @slt_zero_add_nsw( 206; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %a, -1 207; CHECK-NEXT: ret i1 [[CMP]] 208; 209 %add = add nsw i32 %a, 1 210 %cmp = icmp slt i32 %add, 0 211 ret i1 %cmp 212} 213 214; The same fold should work with vectors. 215 216define <2 x i1> @slt_zero_add_nsw_splat_vec(<2 x i8> %a) { 217; CHECK-LABEL: @slt_zero_add_nsw_splat_vec( 218; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> %a, <i8 -1, i8 -1> 219; CHECK-NEXT: ret <2 x i1> [[CMP]] 220; 221 %add = add nsw <2 x i8> %a, <i8 1, i8 1> 222 %cmp = icmp slt <2 x i8> %add, zeroinitializer 223 ret <2 x i1> %cmp 224} 225 226; Test the edges - instcombine should not interfere with simplification to constants. 227; Constant subtraction does not overflow, but this is false. 228 229define i1 @nsw_slt3_ov_no(i8 %a) { 230; CHECK-LABEL: @nsw_slt3_ov_no( 231; CHECK-NEXT: ret i1 false 232; 233 %b = add nsw i8 %a, 100 234 %c = icmp slt i8 %b, -28 235 ret i1 %c 236} 237 238; Test the edges - instcombine should not interfere with simplification to constants. 239; Constant subtraction overflows. This is false. 240 241define i1 @nsw_slt4_ov(i8 %a) { 242; CHECK-LABEL: @nsw_slt4_ov( 243; CHECK-NEXT: ret i1 false 244; 245 %b = add nsw i8 %a, 100 246 %c = icmp slt i8 %b, -29 247 ret i1 %c 248} 249 250; Test the edges - instcombine should not interfere with simplification to constants. 251; Constant subtraction overflows. This is true. 252 253define i1 @nsw_slt5_ov(i8 %a) { 254; CHECK-LABEL: @nsw_slt5_ov( 255; CHECK-NEXT: ret i1 true 256; 257 %b = add nsw i8 %a, -100 258 %c = icmp slt i8 %b, 28 259 ret i1 %c 260} 261 262; InstCombine should not thwart this opportunity to simplify completely. 263 264define i1 @slt_zero_add_nsw_signbit(i8 %x) { 265; CHECK-LABEL: @slt_zero_add_nsw_signbit( 266; CHECK-NEXT: ret i1 true 267; 268 %y = add nsw i8 %x, -128 269 %z = icmp slt i8 %y, 0 270 ret i1 %z 271} 272 273; InstCombine should not thwart this opportunity to simplify completely. 274 275define i1 @slt_zero_add_nuw_signbit(i8 %x) { 276; CHECK-LABEL: @slt_zero_add_nuw_signbit( 277; CHECK-NEXT: ret i1 true 278; 279 %y = add nuw i8 %x, 128 280 %z = icmp slt i8 %y, 0 281 ret i1 %z 282} 283 284