1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4define ptr @test1a(ptr %p, ptr %q) { 5; CHECK-LABEL: @test1a( 6; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr [[P:%.*]], [[Q:%.*]] 7; CHECK-NEXT: [[SELECT_V:%.*]] = select i1 [[CMP]], ptr [[P]], ptr [[Q]] 8; CHECK-NEXT: [[SELECT:%.*]] = getelementptr i8, ptr [[SELECT_V]], i64 16 9; CHECK-NEXT: ret ptr [[SELECT]] 10; 11 %gep1 = getelementptr i32, ptr %p, i64 4 12 %gep2 = getelementptr i32, ptr %q, i64 4 13 %cmp = icmp ugt ptr %p, %q 14 %select = select i1 %cmp, ptr %gep1, ptr %gep2 15 ret ptr %select 16} 17 18define ptr @test1b(ptr %p, ptr %q) { 19; CHECK-LABEL: @test1b( 20; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr [[P:%.*]], [[Q:%.*]] 21; CHECK-NEXT: [[SELECT_V:%.*]] = select i1 [[CMP]], ptr [[P]], ptr [[Q]] 22; CHECK-NEXT: [[SELECT:%.*]] = getelementptr i8, ptr [[SELECT_V]], i64 16 23; CHECK-NEXT: ret ptr [[SELECT]] 24; 25 %gep1 = getelementptr inbounds i32, ptr %p, i64 4 26 %gep2 = getelementptr i32, ptr %q, i64 4 27 %cmp = icmp ugt ptr %p, %q 28 %select = select i1 %cmp, ptr %gep1, ptr %gep2 29 ret ptr %select 30} 31 32define ptr @test1c(ptr %p, ptr %q) { 33; CHECK-LABEL: @test1c( 34; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr [[P:%.*]], [[Q:%.*]] 35; CHECK-NEXT: [[SELECT_V:%.*]] = select i1 [[CMP]], ptr [[P]], ptr [[Q]] 36; CHECK-NEXT: [[SELECT:%.*]] = getelementptr i8, ptr [[SELECT_V]], i64 16 37; CHECK-NEXT: ret ptr [[SELECT]] 38; 39 %gep1 = getelementptr i32, ptr %p, i64 4 40 %gep2 = getelementptr inbounds i32, ptr %q, i64 4 41 %cmp = icmp ugt ptr %p, %q 42 %select = select i1 %cmp, ptr %gep1, ptr %gep2 43 ret ptr %select 44} 45 46define ptr @test1d(ptr %p, ptr %q) { 47; CHECK-LABEL: @test1d( 48; CHECK-NEXT: [[CMP:%.*]] = icmp ugt ptr [[P:%.*]], [[Q:%.*]] 49; CHECK-NEXT: [[SELECT_V:%.*]] = select i1 [[CMP]], ptr [[P]], ptr [[Q]] 50; CHECK-NEXT: [[SELECT:%.*]] = getelementptr inbounds nuw i8, ptr [[SELECT_V]], i64 16 51; CHECK-NEXT: ret ptr [[SELECT]] 52; 53 %gep1 = getelementptr inbounds i32, ptr %p, i64 4 54 %gep2 = getelementptr inbounds i32, ptr %q, i64 4 55 %cmp = icmp ugt ptr %p, %q 56 %select = select i1 %cmp, ptr %gep1, ptr %gep2 57 ret ptr %select 58} 59 60define ptr @test2(ptr %p, i64 %x, i64 %y) { 61; CHECK-LABEL: @test2( 62; CHECK-NEXT: [[SELECT_V:%.*]] = call i64 @llvm.umax.i64(i64 [[X:%.*]], i64 [[Y:%.*]]) 63; CHECK-NEXT: [[SELECT:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[SELECT_V]] 64; CHECK-NEXT: ret ptr [[SELECT]] 65; 66 %gep1 = getelementptr inbounds i32, ptr %p, i64 %x 67 %gep2 = getelementptr inbounds i32, ptr %p, i64 %y 68 %cmp = icmp ugt i64 %x, %y 69 %select = select i1 %cmp, ptr %gep1, ptr %gep2 70 ret ptr %select 71} 72 73; PR50183 74define ptr @test2a(ptr %p, i64 %x, i64 %y) { 75; CHECK-LABEL: @test2a( 76; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]] 77; CHECK-NEXT: [[SELECT_IDX:%.*]] = select i1 [[CMP]], i64 [[X]], i64 0 78; CHECK-NEXT: [[SELECT:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[SELECT_IDX]] 79; CHECK-NEXT: ret ptr [[SELECT]] 80; 81 %gep = getelementptr inbounds i32, ptr %p, i64 %x 82 %cmp = icmp ugt i64 %x, %y 83 %select = select i1 %cmp, ptr %gep, ptr %p 84 ret ptr %select 85} 86 87define ptr @test2a_nusw(ptr %p, i64 %x, i64 %y) { 88; CHECK-LABEL: @test2a_nusw( 89; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]] 90; CHECK-NEXT: [[SELECT_IDX:%.*]] = select i1 [[CMP]], i64 [[X]], i64 0 91; CHECK-NEXT: [[SELECT:%.*]] = getelementptr nusw i32, ptr [[P:%.*]], i64 [[SELECT_IDX]] 92; CHECK-NEXT: ret ptr [[SELECT]] 93; 94 %gep = getelementptr nusw i32, ptr %p, i64 %x 95 %cmp = icmp ugt i64 %x, %y 96 %select = select i1 %cmp, ptr %gep, ptr %p 97 ret ptr %select 98} 99 100define ptr @test2a_nuw(ptr %p, i64 %x, i64 %y) { 101; CHECK-LABEL: @test2a_nuw( 102; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]] 103; CHECK-NEXT: [[SELECT_IDX:%.*]] = select i1 [[CMP]], i64 [[X]], i64 0 104; CHECK-NEXT: [[SELECT:%.*]] = getelementptr nuw i32, ptr [[P:%.*]], i64 [[SELECT_IDX]] 105; CHECK-NEXT: ret ptr [[SELECT]] 106; 107 %gep = getelementptr nuw i32, ptr %p, i64 %x 108 %cmp = icmp ugt i64 %x, %y 109 %select = select i1 %cmp, ptr %gep, ptr %p 110 ret ptr %select 111} 112 113; PR50183 114define ptr @test2b(ptr %p, i64 %x, i64 %y) { 115; CHECK-LABEL: @test2b( 116; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X:%.*]], [[Y:%.*]] 117; CHECK-NEXT: [[SELECT_IDX:%.*]] = select i1 [[CMP]], i64 0, i64 [[X]] 118; CHECK-NEXT: [[SELECT:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[SELECT_IDX]] 119; CHECK-NEXT: ret ptr [[SELECT]] 120; 121 %gep = getelementptr inbounds i32, ptr %p, i64 %x 122 %cmp = icmp ugt i64 %x, %y 123 %select = select i1 %cmp, ptr %p, ptr %gep 124 ret ptr %select 125} 126 127; PR51069 128define ptr @test2c(ptr %p, i64 %x, i64 %y) { 129; CHECK-LABEL: @test2c( 130; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[X:%.*]] 131; CHECK-NEXT: [[ICMP:%.*]] = icmp ugt i64 [[X]], [[Y:%.*]] 132; CHECK-NEXT: [[SEL_IDX:%.*]] = select i1 [[ICMP]], i64 0, i64 24 133; CHECK-NEXT: [[SEL:%.*]] = getelementptr inbounds nuw i8, ptr [[GEP1]], i64 [[SEL_IDX]] 134; CHECK-NEXT: ret ptr [[SEL]] 135; 136 %gep1 = getelementptr inbounds i32, ptr %p, i64 %x 137 %gep2 = getelementptr inbounds i32, ptr %gep1, i64 6 138 %icmp = icmp ugt i64 %x, %y 139 %sel = select i1 %icmp, ptr %gep1, ptr %gep2 140 ret ptr %sel 141} 142 143; PR51069 144define ptr @test2d(ptr %p, i64 %x, i64 %y) { 145; CHECK-LABEL: @test2d( 146; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[X:%.*]] 147; CHECK-NEXT: [[ICMP:%.*]] = icmp ugt i64 [[X]], [[Y:%.*]] 148; CHECK-NEXT: [[SEL_IDX:%.*]] = select i1 [[ICMP]], i64 24, i64 0 149; CHECK-NEXT: [[SEL:%.*]] = getelementptr inbounds nuw i8, ptr [[GEP1]], i64 [[SEL_IDX]] 150; CHECK-NEXT: ret ptr [[SEL]] 151; 152 %gep1 = getelementptr inbounds i32, ptr %p, i64 %x 153 %gep2 = getelementptr inbounds i32, ptr %gep1, i64 6 154 %icmp = icmp ugt i64 %x, %y 155 %sel = select i1 %icmp, ptr %gep2, ptr %gep1 156 ret ptr %sel 157} 158 159; Three (or more) operand GEPs are currently expected to not be optimised, 160; though they could be in principle. 161 162define ptr @test3a(ptr %p, i64 %x, i64 %y) { 163; CHECK-LABEL: @test3a( 164; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [4 x i32], ptr [[P:%.*]], i64 2, i64 [[X:%.*]] 165; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds [4 x i32], ptr [[P]], i64 2, i64 [[Y:%.*]] 166; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X]], [[Y]] 167; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], ptr [[GEP1]], ptr [[GEP2]] 168; CHECK-NEXT: ret ptr [[SELECT]] 169; 170 %gep1 = getelementptr inbounds [4 x i32], ptr %p, i64 2, i64 %x 171 %gep2 = getelementptr inbounds [4 x i32], ptr %p, i64 2, i64 %y 172 %cmp = icmp ugt i64 %x, %y 173 %select = select i1 %cmp, ptr %gep1, ptr %gep2 174 ret ptr %select 175} 176 177define ptr @test3b(ptr %p, ptr %q, i64 %x, i64 %y) { 178; CHECK-LABEL: @test3b( 179; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [4 x i32], ptr [[P:%.*]], i64 2, i64 [[X:%.*]] 180; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds [4 x i32], ptr [[Q:%.*]], i64 2, i64 [[X]] 181; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X]], [[Y:%.*]] 182; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], ptr [[GEP1]], ptr [[GEP2]] 183; CHECK-NEXT: ret ptr [[SELECT]] 184; 185 %gep1 = getelementptr inbounds [4 x i32], ptr %p, i64 2, i64 %x 186 %gep2 = getelementptr inbounds [4 x i32], ptr %q, i64 2, i64 %x 187 %cmp = icmp ugt i64 %x, %y 188 %select = select i1 %cmp, ptr %gep1, ptr %gep2 189 ret ptr %select 190} 191 192define ptr @test3c(ptr %p, ptr %q, i64 %x, i64 %y) { 193; CHECK-LABEL: @test3c( 194; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [4 x i32], ptr [[P:%.*]], i64 [[X:%.*]], i64 2 195; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i32, ptr [[Q:%.*]], i64 [[X]] 196; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X]], [[Y:%.*]] 197; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], ptr [[GEP1]], ptr [[GEP2]] 198; CHECK-NEXT: ret ptr [[SELECT]] 199; 200 %gep1 = getelementptr inbounds [4 x i32], ptr %p, i64 %x, i64 2 201 %gep2 = getelementptr inbounds i32, ptr %q, i64 %x 202 %cmp = icmp ugt i64 %x, %y 203 %select = select i1 %cmp, ptr %gep1, ptr %gep2 204 ret ptr %select 205} 206 207define ptr @test3d(ptr %p, ptr %q, i64 %x, i64 %y) { 208; CHECK-LABEL: @test3d( 209; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[X:%.*]] 210; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds [4 x i32], ptr [[Q:%.*]], i64 [[X]], i64 2 211; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X]], [[Y:%.*]] 212; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], ptr [[GEP1]], ptr [[GEP2]] 213; CHECK-NEXT: ret ptr [[SELECT]] 214; 215 %gep1 = getelementptr inbounds i32, ptr %p, i64 %x 216 %gep2 = getelementptr inbounds [4 x i32], ptr %q, i64 %x, i64 2 217 %cmp = icmp ugt i64 %x, %y 218 %select = select i1 %cmp, ptr %gep1, ptr %gep2 219 ret ptr %select 220} 221 222; Shouldn't be optimised as it would mean introducing an extra select 223 224define ptr @test4(ptr %p, ptr %q, i64 %x, i64 %y) { 225; CHECK-LABEL: @test4( 226; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[X:%.*]] 227; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i32, ptr [[Q:%.*]], i64 [[Y:%.*]] 228; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X]], [[Y]] 229; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], ptr [[GEP1]], ptr [[GEP2]] 230; CHECK-NEXT: ret ptr [[SELECT]] 231; 232 %gep1 = getelementptr inbounds i32, ptr %p, i64 %x 233 %gep2 = getelementptr inbounds i32, ptr %q, i64 %y 234 %cmp = icmp ugt i64 %x, %y 235 %select = select i1 %cmp, ptr %gep1, ptr %gep2 236 ret ptr %select 237} 238 239; We cannot create a select with a vector condition but scalar operands. 240 241define <2 x ptr> @test5(ptr %p1, ptr %p2, <2 x i64> %idx, <2 x i1> %cc) { 242; CHECK-LABEL: @test5( 243; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i64, ptr [[P1:%.*]], <2 x i64> [[IDX:%.*]] 244; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i64, ptr [[P2:%.*]], <2 x i64> [[IDX]] 245; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[CC:%.*]], <2 x ptr> [[GEP1]], <2 x ptr> [[GEP2]] 246; CHECK-NEXT: ret <2 x ptr> [[SELECT]] 247; 248 %gep1 = getelementptr i64, ptr %p1, <2 x i64> %idx 249 %gep2 = getelementptr i64, ptr %p2, <2 x i64> %idx 250 %select = select <2 x i1> %cc, <2 x ptr> %gep1, <2 x ptr> %gep2 251 ret <2 x ptr> %select 252} 253 254; PR51069 - multiple uses 255define ptr @test6(ptr %p, i64 %x, i64 %y) { 256; CHECK-LABEL: @test6( 257; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[X:%.*]] 258; CHECK-NEXT: [[ICMP:%.*]] = icmp ugt i64 [[X]], [[Y:%.*]] 259; CHECK-NEXT: [[SEL_IDX:%.*]] = select i1 [[ICMP]], i64 [[Y]], i64 0 260; CHECK-NEXT: [[SEL:%.*]] = getelementptr inbounds i32, ptr [[GEP1]], i64 [[SEL_IDX]] 261; CHECK-NEXT: call void @use_i32p(ptr [[GEP1]]) 262; CHECK-NEXT: ret ptr [[SEL]] 263; 264 %gep1 = getelementptr inbounds i32, ptr %p, i64 %x 265 %gep2 = getelementptr inbounds i32, ptr %gep1, i64 %y 266 %icmp = icmp ugt i64 %x, %y 267 %sel = select i1 %icmp, ptr %gep2, ptr %gep1 268 call void @use_i32p(ptr %gep1) 269 ret ptr %sel 270} 271declare void @use_i32p(ptr) 272 273; We cannot create a select-with-idx with a vector condition but scalar idx. 274 275define <2 x ptr> @test7(<2 x ptr> %p1, i64 %idx, <2 x i1> %cc) { 276; CHECK-LABEL: @test7( 277; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, <2 x ptr> [[P1:%.*]], i64 [[IDX:%.*]] 278; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[CC:%.*]], <2 x ptr> [[P1]], <2 x ptr> [[GEP]] 279; CHECK-NEXT: ret <2 x ptr> [[SELECT]] 280; 281 %gep = getelementptr i64, <2 x ptr> %p1, i64 %idx 282 %select = select <2 x i1> %cc, <2 x ptr> %p1, <2 x ptr> %gep 283 ret <2 x ptr> %select 284} 285