1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine -S -data-layout="p:32:32:32-p1:16:16:16-n8:16:32:64" < %s | FileCheck %s 3 4@G16 = internal constant [10 x i16] [i16 35, i16 82, i16 69, i16 81, i16 85, 5 i16 73, i16 82, i16 69, i16 68, i16 0] 6 7@G16_as1 = internal addrspace(1) constant [10 x i16] [i16 35, i16 82, i16 69, i16 81, i16 85, 8 i16 73, i16 82, i16 69, i16 68, i16 0] 9 10@GD = internal constant [6 x double] 11 [double -10.0, double 1.0, double 4.0, double 2.0, double -20.0, double -40.0] 12 13%Foo = type { i32, i32, i32, i32 } 14 15@GS = internal constant %Foo { i32 1, i32 4, i32 9, i32 14 } 16 17@GStructArr = internal constant [4 x %Foo] [ %Foo { i32 1, i32 4, i32 9, i32 14 }, 18 %Foo { i32 5, i32 4, i32 6, i32 11 }, 19 %Foo { i32 6, i32 5, i32 9, i32 20 }, 20 %Foo { i32 12, i32 3, i32 9, i32 8 } ] 21 22 23define i1 @test1(i32 %X) { 24; CHECK-LABEL: @test1( 25; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X:%.*]], 9 26; CHECK-NEXT: ret i1 [[R]] 27; 28 %P = getelementptr inbounds [10 x i16], [10 x i16]* @G16, i32 0, i32 %X 29 %Q = load i16, i16* %P 30 %R = icmp eq i16 %Q, 0 31 ret i1 %R 32} 33 34define i1 @test1_noinbounds(i32 %X) { 35; CHECK-LABEL: @test1_noinbounds( 36; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 2147483647 37; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 9 38; CHECK-NEXT: ret i1 [[R]] 39; 40 %P = getelementptr [10 x i16], [10 x i16]* @G16, i32 0, i32 %X 41 %Q = load i16, i16* %P 42 %R = icmp eq i16 %Q, 0 43 ret i1 %R 44} 45 46define i1 @test1_noinbounds_i64(i64 %X) { 47; CHECK-LABEL: @test1_noinbounds_i64( 48; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[X:%.*]], 2147483647 49; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[TMP1]], 9 50; CHECK-NEXT: ret i1 [[R]] 51; 52 %P = getelementptr [10 x i16], [10 x i16]* @G16, i64 0, i64 %X 53 %Q = load i16, i16* %P 54 %R = icmp eq i16 %Q, 0 55 ret i1 %R 56} 57 58define i1 @test1_noinbounds_as1(i32 %x) { 59; CHECK-LABEL: @test1_noinbounds_as1( 60; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 32767 61; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 9 62; CHECK-NEXT: ret i1 [[R]] 63; 64 %p = getelementptr [10 x i16], [10 x i16] addrspace(1)* @G16_as1, i16 0, i32 %x 65 %q = load i16, i16 addrspace(1)* %p 66 %r = icmp eq i16 %q, 0 67 ret i1 %r 68 69} 70 71define i1 @test2(i32 %X) { 72; CHECK-LABEL: @test2( 73; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X:%.*]], 4 74; CHECK-NEXT: ret i1 [[R]] 75; 76 %P = getelementptr inbounds [10 x i16], [10 x i16]* @G16, i32 0, i32 %X 77 %Q = load i16, i16* %P 78 %R = icmp slt i16 %Q, 85 79 ret i1 %R 80} 81 82define i1 @test3(i32 %X) { 83; CHECK-LABEL: @test3( 84; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X:%.*]], 1 85; CHECK-NEXT: ret i1 [[R]] 86; 87 %P = getelementptr inbounds [6 x double], [6 x double]* @GD, i32 0, i32 %X 88 %Q = load double, double* %P 89 %R = fcmp oeq double %Q, 1.0 90 ret i1 %R 91 92} 93 94define i1 @test4(i32 %X) { 95; CHECK-LABEL: @test4( 96; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 933, [[X:%.*]] 97; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 1 98; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[TMP2]], 0 99; CHECK-NEXT: ret i1 [[R]] 100; 101 %P = getelementptr inbounds [10 x i16], [10 x i16]* @G16, i32 0, i32 %X 102 %Q = load i16, i16* %P 103 %R = icmp sle i16 %Q, 73 104 ret i1 %R 105} 106 107define i1 @test4_i16(i16 %X) { 108; CHECK-LABEL: @test4_i16( 109; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[X:%.*]] to i32 110; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 933, [[TMP1]] 111; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 1 112; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[TMP3]], 0 113; CHECK-NEXT: ret i1 [[R]] 114; 115 %P = getelementptr inbounds [10 x i16], [10 x i16]* @G16, i32 0, i16 %X 116 %Q = load i16, i16* %P 117 %R = icmp sle i16 %Q, 73 118 ret i1 %R 119} 120 121define i1 @test5(i32 %X) { 122; CHECK-LABEL: @test5( 123; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 2 124; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[X]], 7 125; CHECK-NEXT: [[R:%.*]] = or i1 [[TMP1]], [[TMP2]] 126; CHECK-NEXT: ret i1 [[R]] 127; 128 %P = getelementptr inbounds [10 x i16], [10 x i16]* @G16, i32 0, i32 %X 129 %Q = load i16, i16* %P 130 %R = icmp eq i16 %Q, 69 131 ret i1 %R 132} 133 134define i1 @test6(i32 %X) { 135; CHECK-LABEL: @test6( 136; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], -1 137; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[TMP1]], 3 138; CHECK-NEXT: ret i1 [[R]] 139; 140 %P = getelementptr inbounds [6 x double], [6 x double]* @GD, i32 0, i32 %X 141 %Q = load double, double* %P 142 %R = fcmp ogt double %Q, 0.0 143 ret i1 %R 144} 145 146define i1 @test7(i32 %X) { 147; CHECK-LABEL: @test7( 148; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], -4 149; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[TMP1]], -3 150; CHECK-NEXT: ret i1 [[R]] 151; 152 %P = getelementptr inbounds [6 x double], [6 x double]* @GD, i32 0, i32 %X 153 %Q = load double, double* %P 154 %R = fcmp olt double %Q, 0.0 155 ret i1 %R 156} 157 158define i1 @test8(i32 %X) { 159; CHECK-LABEL: @test8( 160; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -2 161; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 8 162; CHECK-NEXT: ret i1 [[TMP2]] 163; 164 %P = getelementptr inbounds [10 x i16], [10 x i16]* @G16, i32 0, i32 %X 165 %Q = load i16, i16* %P 166 %R = and i16 %Q, 3 167 %S = icmp eq i16 %R, 0 168 ret i1 %S 169} 170 171@GA = internal constant [4 x { i32, i32 } ] [ 172 { i32, i32 } { i32 1, i32 0 }, 173 { i32, i32 } { i32 2, i32 1 }, 174 { i32, i32 } { i32 3, i32 1 }, 175 { i32, i32 } { i32 4, i32 0 } 176] 177 178define i1 @test9(i32 %X) { 179; CHECK-LABEL: @test9( 180; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], -1 181; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 2 182; CHECK-NEXT: ret i1 [[TMP2]] 183; 184 %P = getelementptr inbounds [4 x { i32, i32 } ], [4 x { i32, i32 } ]* @GA, i32 0, i32 %X, i32 1 185 %Q = load i32, i32* %P 186 %R = icmp eq i32 %Q, 1 187 ret i1 %R 188} 189 190define i1 @test10_struct(i32 %x) { 191; CHECK-LABEL: @test10_struct( 192; CHECK-NEXT: ret i1 false 193; 194 %p = getelementptr inbounds %Foo, %Foo* @GS, i32 %x, i32 0 195 %q = load i32, i32* %p 196 %r = icmp eq i32 %q, 9 197 ret i1 %r 198} 199 200define i1 @test10_struct_noinbounds(i32 %x) { 201; CHECK-LABEL: @test10_struct_noinbounds( 202; CHECK-NEXT: [[P:%.*]] = getelementptr [[FOO:%.*]], %Foo* @GS, i32 [[X:%.*]], i32 0 203; CHECK-NEXT: [[Q:%.*]] = load i32, i32* [[P]], align 8 204; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[Q]], 9 205; CHECK-NEXT: ret i1 [[R]] 206; 207 %p = getelementptr %Foo, %Foo* @GS, i32 %x, i32 0 208 %q = load i32, i32* %p 209 %r = icmp eq i32 %q, 9 210 ret i1 %r 211} 212 213; Test that the GEP indices are converted before we ever get here 214; Index < ptr size 215define i1 @test10_struct_i16(i16 %x){ 216; CHECK-LABEL: @test10_struct_i16( 217; CHECK-NEXT: ret i1 false 218; 219 %p = getelementptr inbounds %Foo, %Foo* @GS, i16 %x, i32 0 220 %q = load i32, i32* %p 221 %r = icmp eq i32 %q, 0 222 ret i1 %r 223} 224 225; Test that the GEP indices are converted before we ever get here 226; Index > ptr size 227define i1 @test10_struct_i64(i64 %x){ 228; CHECK-LABEL: @test10_struct_i64( 229; CHECK-NEXT: ret i1 false 230; 231 %p = getelementptr inbounds %Foo, %Foo* @GS, i64 %x, i32 0 232 %q = load i32, i32* %p 233 %r = icmp eq i32 %q, 0 234 ret i1 %r 235} 236 237define i1 @test10_struct_noinbounds_i16(i16 %x) { 238; CHECK-LABEL: @test10_struct_noinbounds_i16( 239; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i32 240; CHECK-NEXT: [[P:%.*]] = getelementptr [[FOO:%.*]], %Foo* @GS, i32 [[TMP1]], i32 0 241; CHECK-NEXT: [[Q:%.*]] = load i32, i32* [[P]], align 8 242; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[Q]], 0 243; CHECK-NEXT: ret i1 [[R]] 244; 245 %p = getelementptr %Foo, %Foo* @GS, i16 %x, i32 0 246 %q = load i32, i32* %p 247 %r = icmp eq i32 %q, 0 248 ret i1 %r 249} 250 251define i1 @test10_struct_arr(i32 %x) { 252; CHECK-LABEL: @test10_struct_arr( 253; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X:%.*]], 1 254; CHECK-NEXT: ret i1 [[R]] 255; 256 %p = getelementptr inbounds [4 x %Foo], [4 x %Foo]* @GStructArr, i32 0, i32 %x, i32 2 257 %q = load i32, i32* %p 258 %r = icmp eq i32 %q, 9 259 ret i1 %r 260} 261 262define i1 @test10_struct_arr_noinbounds(i32 %x) { 263; CHECK-LABEL: @test10_struct_arr_noinbounds( 264; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 268435455 265; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[TMP1]], 1 266; CHECK-NEXT: ret i1 [[R]] 267; 268 %p = getelementptr [4 x %Foo], [4 x %Foo]* @GStructArr, i32 0, i32 %x, i32 2 269 %q = load i32, i32* %p 270 %r = icmp eq i32 %q, 9 271 ret i1 %r 272} 273 274define i1 @test10_struct_arr_i16(i16 %x) { 275; CHECK-LABEL: @test10_struct_arr_i16( 276; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[X:%.*]], 1 277; CHECK-NEXT: ret i1 [[R]] 278; 279 %p = getelementptr inbounds [4 x %Foo], [4 x %Foo]* @GStructArr, i16 0, i16 %x, i32 2 280 %q = load i32, i32* %p 281 %r = icmp eq i32 %q, 9 282 ret i1 %r 283} 284 285define i1 @test10_struct_arr_i64(i64 %x) { 286; CHECK-LABEL: @test10_struct_arr_i64( 287; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[X:%.*]], 4294967295 288; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[TMP1]], 1 289; CHECK-NEXT: ret i1 [[R]] 290; 291 %p = getelementptr inbounds [4 x %Foo], [4 x %Foo]* @GStructArr, i64 0, i64 %x, i32 2 292 %q = load i32, i32* %p 293 %r = icmp eq i32 %q, 9 294 ret i1 %r 295} 296 297define i1 @test10_struct_arr_noinbounds_i16(i16 %x) { 298; CHECK-LABEL: @test10_struct_arr_noinbounds_i16( 299; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i32 300; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 268435455 301; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[TMP2]], 1 302; CHECK-NEXT: ret i1 [[R]] 303; 304 %p = getelementptr [4 x %Foo], [4 x %Foo]* @GStructArr, i32 0, i16 %x, i32 2 305 %q = load i32, i32* %p 306 %r = icmp eq i32 %q, 9 307 ret i1 %r 308} 309 310define i1 @test10_struct_arr_noinbounds_i64(i64 %x) { 311; CHECK-LABEL: @test10_struct_arr_noinbounds_i64( 312; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[X:%.*]], 268435455 313; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[TMP1]], 1 314; CHECK-NEXT: ret i1 [[R]] 315; 316 %p = getelementptr [4 x %Foo], [4 x %Foo]* @GStructArr, i32 0, i64 %x, i32 2 317 %q = load i32, i32* %p 318 %r = icmp eq i32 %q, 9 319 ret i1 %r 320} 321