1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4define void @test(ptr %ptr, i32 %a, i32 %b) { 5; CHECK-LABEL: define void @test( 6; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { 7; CHECK-NEXT: entry: 8; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[A]] to i64 9; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP0]] 10; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[TMP1]], i64 40 11; CHECK-NEXT: store i32 [[B]], ptr [[GEP]], align 4 12; CHECK-NEXT: ret void 13; 14entry: 15 %add = add nsw i32 %a, 10 16 %idx = sext i32 %add to i64 17 %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx 18 store i32 %b, ptr %gep 19 ret void 20} 21 22define i32 @test_add_res_moreoneuse(ptr %ptr, i32 %a, i32 %b) { 23; CHECK-LABEL: define i32 @test_add_res_moreoneuse( 24; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { 25; CHECK-NEXT: entry: 26; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 5 27; CHECK-NEXT: [[IDX:%.*]] = sext i32 [[ADD]] to i64 28; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[IDX]] 29; CHECK-NEXT: store i32 [[B]], ptr [[GEP]], align 4 30; CHECK-NEXT: ret i32 [[ADD]] 31; 32entry: 33 %add = add nsw i32 %a, 5 34 %idx = sext i32 %add to i64 35 %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx 36 store i32 %b, ptr %gep 37 ret i32 %add 38} 39 40define void @test_addop_nonsw_flag(ptr %ptr, i32 %a, i32 %b) { 41; CHECK-LABEL: define void @test_addop_nonsw_flag( 42; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { 43; CHECK-NEXT: entry: 44; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 10 45; CHECK-NEXT: [[IDX:%.*]] = sext i32 [[ADD]] to i64 46; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[IDX]] 47; CHECK-NEXT: store i32 [[B]], ptr [[GEP]], align 4 48; CHECK-NEXT: ret void 49; 50entry: 51 %add = add i32 %a, 10 52 %idx = sext i32 %add to i64 53 %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx 54 store i32 %b, ptr %gep 55 ret void 56} 57 58define void @test_add_op2_not_constant(ptr %ptr, i32 %a, i32 %b) { 59; CHECK-LABEL: define void @test_add_op2_not_constant( 60; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { 61; CHECK-NEXT: entry: 62; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], [[B]] 63; CHECK-NEXT: [[IDX:%.*]] = sext i32 [[ADD]] to i64 64; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[IDX]] 65; CHECK-NEXT: store i32 [[B]], ptr [[GEP]], align 4 66; CHECK-NEXT: ret void 67; 68entry: 69 %add = add i32 %a, %b 70 %idx = sext i32 %add to i64 71 %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx 72 store i32 %b, ptr %gep 73 ret void 74} 75 76define void @test_zext_nneg(ptr %ptr, i32 %a, i32 %b) { 77; CHECK-LABEL: define void @test_zext_nneg( 78; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { 79; CHECK-NEXT: entry: 80; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[A]] to i64 81; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP0]] 82; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[TMP1]], i64 40 83; CHECK-NEXT: store i32 [[B]], ptr [[GEP]], align 4 84; CHECK-NEXT: ret void 85; 86entry: 87 %add = add nsw i32 %a, 10 88 %idx = zext nneg i32 %add to i64 89 %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx 90 store i32 %b, ptr %gep 91 ret void 92} 93 94define void @test_zext_missing_nneg(ptr %ptr, i32 %a, i32 %b) { 95; CHECK-LABEL: define void @test_zext_missing_nneg( 96; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { 97; CHECK-NEXT: entry: 98; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 10 99; CHECK-NEXT: [[IDX:%.*]] = zext i32 [[ADD]] to i64 100; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i32, ptr [[PTR]], i64 [[IDX]] 101; CHECK-NEXT: store i32 [[B]], ptr [[GEP]], align 4 102; CHECK-NEXT: ret void 103; 104entry: 105 %add = add nsw i32 %a, 10 106 %idx = zext i32 %add to i64 107 %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx 108 store i32 %b, ptr %gep 109 ret void 110} 111 112define ptr @gep_inbounds_add_nsw_nonneg(ptr %ptr, i64 %a, i64 %b) { 113; CHECK-LABEL: define ptr @gep_inbounds_add_nsw_nonneg( 114; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 115; CHECK-NEXT: [[A_NNEG:%.*]] = icmp sgt i64 [[A]], -1 116; CHECK-NEXT: call void @llvm.assume(i1 [[A_NNEG]]) 117; CHECK-NEXT: [[B_NNEG:%.*]] = icmp sgt i64 [[B]], -1 118; CHECK-NEXT: call void @llvm.assume(i1 [[B_NNEG]]) 119; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i32, ptr [[PTR]], i64 [[A]] 120; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 [[B]] 121; CHECK-NEXT: ret ptr [[GEP]] 122; 123 %a.nneg = icmp sgt i64 %a, -1 124 call void @llvm.assume(i1 %a.nneg) 125 %b.nneg = icmp sgt i64 %b, -1 126 call void @llvm.assume(i1 %b.nneg) 127 %add = add nsw i64 %a, %b 128 %gep = getelementptr inbounds i32, ptr %ptr, i64 %add 129 ret ptr %gep 130} 131 132define ptr @gep_inbounds_add_nsw_not_nonneg1(ptr %ptr, i64 %a, i64 %b) { 133; CHECK-LABEL: define ptr @gep_inbounds_add_nsw_not_nonneg1( 134; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 135; CHECK-NEXT: [[A_NNEG:%.*]] = icmp sgt i64 [[A]], -1 136; CHECK-NEXT: call void @llvm.assume(i1 [[A_NNEG]]) 137; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]] 138; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]] 139; CHECK-NEXT: ret ptr [[GEP]] 140; 141 %a.nneg = icmp sgt i64 %a, -1 142 call void @llvm.assume(i1 %a.nneg) 143 %add = add nsw i64 %a, %b 144 %gep = getelementptr inbounds i32, ptr %ptr, i64 %add 145 ret ptr %gep 146} 147 148define ptr @gep_inbounds_add_nsw_not_nonneg2(ptr %ptr, i64 %a, i64 %b) { 149; CHECK-LABEL: define ptr @gep_inbounds_add_nsw_not_nonneg2( 150; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 151; CHECK-NEXT: [[B_NNEG:%.*]] = icmp sgt i64 [[B]], -1 152; CHECK-NEXT: call void @llvm.assume(i1 [[B_NNEG]]) 153; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]] 154; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]] 155; CHECK-NEXT: ret ptr [[GEP]] 156; 157 %b.nneg = icmp sgt i64 %b, -1 158 call void @llvm.assume(i1 %b.nneg) 159 %add = add nsw i64 %a, %b 160 %gep = getelementptr inbounds i32, ptr %ptr, i64 %add 161 ret ptr %gep 162} 163 164define ptr @gep_not_inbounds_add_nsw_nonneg(ptr %ptr, i64 %a, i64 %b) { 165; CHECK-LABEL: define ptr @gep_not_inbounds_add_nsw_nonneg( 166; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 167; CHECK-NEXT: [[A_NNEG:%.*]] = icmp sgt i64 [[A]], -1 168; CHECK-NEXT: call void @llvm.assume(i1 [[A_NNEG]]) 169; CHECK-NEXT: [[B_NNEG:%.*]] = icmp sgt i64 [[B]], -1 170; CHECK-NEXT: call void @llvm.assume(i1 [[B_NNEG]]) 171; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]] 172; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]] 173; CHECK-NEXT: ret ptr [[GEP]] 174; 175 %a.nneg = icmp sgt i64 %a, -1 176 call void @llvm.assume(i1 %a.nneg) 177 %b.nneg = icmp sgt i64 %b, -1 178 call void @llvm.assume(i1 %b.nneg) 179 %add = add nsw i64 %a, %b 180 %gep = getelementptr i32, ptr %ptr, i64 %add 181 ret ptr %gep 182} 183 184define ptr @gep_inbounds_add_not_nsw_nonneg(ptr %ptr, i64 %a, i64 %b) { 185; CHECK-LABEL: define ptr @gep_inbounds_add_not_nsw_nonneg( 186; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 187; CHECK-NEXT: [[A_NNEG:%.*]] = icmp sgt i64 [[A]], -1 188; CHECK-NEXT: call void @llvm.assume(i1 [[A_NNEG]]) 189; CHECK-NEXT: [[B_NNEG:%.*]] = icmp sgt i64 [[B]], -1 190; CHECK-NEXT: call void @llvm.assume(i1 [[B_NNEG]]) 191; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]] 192; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]] 193; CHECK-NEXT: ret ptr [[GEP]] 194; 195 %a.nneg = icmp sgt i64 %a, -1 196 call void @llvm.assume(i1 %a.nneg) 197 %b.nneg = icmp sgt i64 %b, -1 198 call void @llvm.assume(i1 %b.nneg) 199 %add = add i64 %a, %b 200 %gep = getelementptr inbounds i32, ptr %ptr, i64 %add 201 ret ptr %gep 202} 203 204define ptr @gep_inbounds_sext_add_nonneg(ptr %ptr, i32 %a) { 205; CHECK-LABEL: define ptr @gep_inbounds_sext_add_nonneg( 206; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]]) { 207; CHECK-NEXT: [[A_NNEG:%.*]] = icmp sgt i32 [[A]], -1 208; CHECK-NEXT: call void @llvm.assume(i1 [[A_NNEG]]) 209; CHECK-NEXT: [[TMP1:%.*]] = zext nneg i32 [[A]] to i64 210; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i32, ptr [[PTR]], i64 [[TMP1]] 211; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP2]], i64 40 212; CHECK-NEXT: ret ptr [[GEP]] 213; 214 %a.nneg = icmp sgt i32 %a, -1 215 call void @llvm.assume(i1 %a.nneg) 216 %add = add nsw i32 %a, 10 217 %idx = sext i32 %add to i64 218 %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx 219 ret ptr %gep 220} 221 222define ptr @gep_inbounds_sext_add_not_nonneg_1(ptr %ptr, i32 %a) { 223; CHECK-LABEL: define ptr @gep_inbounds_sext_add_not_nonneg_1( 224; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]]) { 225; CHECK-NEXT: [[A_NNEG:%.*]] = icmp sgt i32 [[A]], -1 226; CHECK-NEXT: call void @llvm.assume(i1 [[A_NNEG]]) 227; CHECK-NEXT: [[TMP1:%.*]] = zext nneg i32 [[A]] to i64 228; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP1]] 229; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[TMP2]], i64 -40 230; CHECK-NEXT: ret ptr [[GEP]] 231; 232 %a.nneg = icmp sgt i32 %a, -1 233 call void @llvm.assume(i1 %a.nneg) 234 %add = add nsw i32 %a, -10 235 %idx = sext i32 %add to i64 236 %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx 237 ret ptr %gep 238} 239 240define ptr @gep_inbounds_sext_add_not_nonneg_2(ptr %ptr, i32 %a) { 241; CHECK-LABEL: define ptr @gep_inbounds_sext_add_not_nonneg_2( 242; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]]) { 243; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[A]] to i64 244; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP1]] 245; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[TMP2]], i64 40 246; CHECK-NEXT: ret ptr [[GEP]] 247; 248 %add = add nsw i32 %a, 10 249 %idx = sext i32 %add to i64 250 %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx 251 ret ptr %gep 252} 253 254define ptr @gep_not_inbounds_sext_add_nonneg(ptr %ptr, i32 %a) { 255; CHECK-LABEL: define ptr @gep_not_inbounds_sext_add_nonneg( 256; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]]) { 257; CHECK-NEXT: [[A_NNEG:%.*]] = icmp sgt i32 [[A]], -1 258; CHECK-NEXT: call void @llvm.assume(i1 [[A_NNEG]]) 259; CHECK-NEXT: [[TMP1:%.*]] = zext nneg i32 [[A]] to i64 260; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP1]] 261; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[TMP2]], i64 40 262; CHECK-NEXT: ret ptr [[GEP]] 263; 264 %a.nneg = icmp sgt i32 %a, -1 265 call void @llvm.assume(i1 %a.nneg) 266 %add = add nsw i32 %a, 10 267 %idx = sext i32 %add to i64 268 %gep = getelementptr i32, ptr %ptr, i64 %idx 269 ret ptr %gep 270} 271