1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -indvars -S | FileCheck %s 3 4@array = dso_local global [16777219 x i32] zeroinitializer, align 4 5 6define void @sitofp_fptosi_range() { 7; CHECK-LABEL: @sitofp_fptosi_range( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: br label [[FOR_BODY:%.*]] 10; CHECK: for.body: 11; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] 12; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[IV_INT]] to i64 13; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] 14; CHECK-NEXT: store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4 15; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 16; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0 17; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] 18; CHECK: cleanup: 19; CHECK-NEXT: ret void 20; 21entry: 22 br label %for.body 23 24for.body: ; preds = %for.body, %entry 25 %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] 26 %indvar.conv = sitofp i32 %iv.int to float 27 %conv = fptosi float %indvar.conv to i32 28 %idxprom = sext i32 %conv to i64 29 %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom 30 store i32 %conv, i32* %arrayidx, align 4 31 %dec.int = add nsw i32 %iv.int, -1 32 %cmp = icmp ugt i32 %dec.int, 0 33 br i1 %cmp, label %for.body, label %cleanup 34 35cleanup: ; preds = %for.body 36 ret void 37} 38 39; Negative test: The transform is *not* valid because there are too many significant bits 40define void @sitofp_fptosi_range_overflow() { 41; CHECK-LABEL: @sitofp_fptosi_range_overflow( 42; CHECK-NEXT: entry: 43; CHECK-NEXT: br label [[FOR_BODY:%.*]] 44; CHECK: for.body: 45; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 16777218, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] 46; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to float 47; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[INDVAR_CONV]] to i32 48; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[CONV]] to i64 49; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] 50; CHECK-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 51; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 52; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0 53; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] 54; CHECK: cleanup: 55; CHECK-NEXT: ret void 56; 57entry: 58 br label %for.body 59 60for.body: ; preds = %for.body, %entry 61 %iv.int = phi i32 [ 16777218, %entry ], [ %dec.int, %for.body ] ; intermediate 16777218 (= 1 << 24 + 2) 62 %indvar.conv = sitofp i32 %iv.int to float 63 %conv = fptosi float %indvar.conv to i32 64 %idxprom = sext i32 %conv to i64 65 %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom 66 store i32 %conv, i32* %arrayidx, align 4 67 %dec.int = add nsw i32 %iv.int, -1 68 %cmp = icmp ugt i32 %dec.int, 0 69 br i1 %cmp, label %for.body, label %cleanup 70 71cleanup: ; preds = %for.body 72 ret void 73} 74 75; Negative test: Type mismatch between the integer IV and the fptosi result 76define void @sitofp_fptosi_range_mismatch_type() { 77; 78; CHECK-LABEL: @sitofp_fptosi_range_mismatch_type( 79; CHECK-NEXT: entry: 80; CHECK-NEXT: br label [[FOR_BODY:%.*]] 81; CHECK: for.body: 82; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] 83; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to float 84; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[INDVAR_CONV]] to i16 85; CHECK-NEXT: [[IDXPROM32:%.*]] = sext i16 [[CONV]] to i32 86; CHECK-NEXT: [[IDXPROM64:%.*]] = sext i16 [[CONV]] to i64 87; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM64]] 88; CHECK-NEXT: store i32 [[IDXPROM32]], i32* [[ARRAYIDX]], align 4 89; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 90; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0 91; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] 92; CHECK: cleanup: 93; CHECK-NEXT: ret void 94; 95entry: 96 br label %for.body 97 98for.body: ; preds = %for.body, %entry 99 %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] 100 %indvar.conv = sitofp i32 %iv.int to float 101 %conv = fptosi float %indvar.conv to i16 102 %idxprom32 = sext i16 %conv to i32 103 %idxprom64 = sext i16 %conv to i64 104 %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom64 105 store i32 %idxprom32, i32* %arrayidx, align 4 106 %dec.int = add nsw i32 %iv.int, -1 107 %cmp = icmp ugt i32 %dec.int, 0 108 br i1 %cmp, label %for.body, label %cleanup 109 110cleanup: ; preds = %for.body 111 ret void 112} 113 114define void @sitofp_fptoui_range() { 115; CHECK-LABEL: @sitofp_fptoui_range( 116; CHECK-NEXT: entry: 117; CHECK-NEXT: br label [[FOR_BODY:%.*]] 118; CHECK: for.body: 119; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] 120; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[IV_INT]] to i64 121; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] 122; CHECK-NEXT: store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4 123; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 124; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0 125; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] 126; CHECK: cleanup: 127; CHECK-NEXT: ret void 128; 129entry: 130 br label %for.body 131 132for.body: ; preds = %for.body, %entry 133 %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] 134 %indvar.conv = sitofp i32 %iv.int to float 135 %conv = fptoui float %indvar.conv to i32 136 %idxprom = zext i32 %conv to i64 137 %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom 138 store i32 %conv, i32* %arrayidx, align 4 139 %dec.int = add nsw i32 %iv.int, -1 140 %cmp = icmp sgt i32 %dec.int, 0 141 br i1 %cmp, label %for.body, label %cleanup 142 143cleanup: ; preds = %for.body 144 ret void 145} 146 147; Range including negative value. 148define void @sitofp_fptoui_range_with_negative () { 149; CHECK-LABEL: @sitofp_fptoui_range_with_negative( 150; CHECK-NEXT: entry: 151; CHECK-NEXT: br label [[FOR_BODY:%.*]] 152; CHECK: for.body: 153; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] 154; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[IV_INT]] to i64 155; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] 156; CHECK-NEXT: store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4 157; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 158; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[DEC_INT]], -100 159; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] 160; CHECK: cleanup: 161; CHECK-NEXT: ret void 162; 163entry: 164 br label %for.body 165 166for.body: ; preds = %for.body, %entry 167 %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] 168 %indvar.conv = sitofp i32 %iv.int to float 169 %conv = fptoui float %indvar.conv to i32 170 %idxprom = zext i32 %conv to i64 171 %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom 172 store i32 %conv, i32* %arrayidx, align 4 173 %dec.int = add nsw i32 %iv.int, -1 174 %cmp = icmp sgt i32 %dec.int, -100 175 br i1 %cmp, label %for.body, label %cleanup 176 177cleanup: ; preds = %for.body 178 ret void 179} 180 181; https://godbolt.org/z/51MrqYjEf 182define void @uitofp_fptoui_range () { 183; CHECK-LABEL: @uitofp_fptoui_range( 184; CHECK-NEXT: entry: 185; CHECK-NEXT: br label [[FOR_BODY:%.*]] 186; CHECK: for.body: 187; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] 188; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[IV_INT]] to i64 189; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] 190; CHECK-NEXT: store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4 191; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 192; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 3 193; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] 194; CHECK: cleanup: 195; CHECK-NEXT: ret void 196; 197entry: 198 br label %for.body 199 200for.body: ; preds = %for.body, %entry 201 %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] 202 %indvar.conv = uitofp i32 %iv.int to float 203 %conv = fptoui float %indvar.conv to i32 204 %idxprom = zext i32 %conv to i64 205 %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom 206 store i32 %conv, i32* %arrayidx, align 4 207 %dec.int = add nsw i32 %iv.int, -1 208 %cmp = icmp ugt i32 %dec.int, 3 209 br i1 %cmp, label %for.body, label %cleanup 210 211cleanup: ; preds = %for.body 212 ret void 213} 214 215define void @uitofp_fptoui_range_with_negative() { 216; CHECK-LABEL: @uitofp_fptoui_range_with_negative( 217; CHECK-NEXT: entry: 218; CHECK-NEXT: br label [[FOR_BODY:%.*]] 219; CHECK: for.body: 220; CHECK-NEXT: store i32 100, i32* getelementptr inbounds ([16777219 x i32], [16777219 x i32]* @array, i64 0, i64 100), align 4 221; CHECK-NEXT: br i1 false, label [[FOR_BODY]], label [[CLEANUP:%.*]] 222; CHECK: cleanup: 223; CHECK-NEXT: ret void 224; 225entry: 226 br label %for.body 227 228for.body: ; preds = %for.body, %entry 229 %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] 230 %indvar.conv = uitofp i32 %iv.int to float 231 %conv = fptoui float %indvar.conv to i32 232 %idxprom = zext i32 %conv to i64 233 %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom 234 store i32 %conv, i32* %arrayidx, align 4 235 %dec.int = add nsw i32 %iv.int, -1 236 %cmp = icmp ugt i32 %dec.int, -100 237 br i1 %cmp, label %for.body, label %cleanup 238 239cleanup: ; preds = %for.body 240 ret void 241} 242 243define void @uitofp_fptosi_range () { 244; CHECK-LABEL: @uitofp_fptosi_range( 245; CHECK-NEXT: entry: 246; CHECK-NEXT: br label [[FOR_BODY:%.*]] 247; CHECK: for.body: 248; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] 249; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[IV_INT]] to i64 250; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] 251; CHECK-NEXT: store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4 252; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 253; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 3 254; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] 255; CHECK: cleanup: 256; CHECK-NEXT: ret void 257; 258entry: 259 br label %for.body 260 261for.body: ; preds = %for.body, %entry 262 %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] 263 %indvar.conv = uitofp i32 %iv.int to float 264 %conv = fptosi float %indvar.conv to i32 265 %idxprom = sext i32 %conv to i64 266 %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom 267 store i32 %conv, i32* %arrayidx, align 4 268 %dec.int = add nsw i32 %iv.int, -1 269 %cmp = icmp ugt i32 %dec.int, 3 270 br i1 %cmp, label %for.body, label %cleanup 271 272cleanup: ; preds = %for.body 273 ret void 274} 275 276define void @uitofp_fptosi_range_with_negative () { 277; CHECK-LABEL: @uitofp_fptosi_range_with_negative( 278; CHECK-NEXT: entry: 279; CHECK-NEXT: br label [[FOR_BODY:%.*]] 280; CHECK: for.body: 281; CHECK-NEXT: store i32 100, i32* getelementptr inbounds ([16777219 x i32], [16777219 x i32]* @array, i64 0, i64 100), align 4 282; CHECK-NEXT: br i1 false, label [[FOR_BODY]], label [[CLEANUP:%.*]] 283; CHECK: cleanup: 284; CHECK-NEXT: ret void 285; 286entry: 287 br label %for.body 288 289for.body: ; preds = %for.body, %entry 290 %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] 291 %indvar.conv = uitofp i32 %iv.int to float 292 %conv = fptosi float %indvar.conv to i32 293 %idxprom = sext i32 %conv to i64 294 %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom 295 store i32 %conv, i32* %arrayidx, align 4 296 %dec.int = add nsw i32 %iv.int, -1 297 %cmp = icmp ugt i32 %dec.int, -100 298 br i1 %cmp, label %for.body, label %cleanup 299 300cleanup: ; preds = %for.body 301 ret void 302} 303 304