| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -indvars -S | FileCheck %s |
| |
| @array = dso_local global [16777219 x i32] zeroinitializer, align 4 |
| |
| define void @sitofp_fptosi_range() { |
| ; CHECK-LABEL: @sitofp_fptosi_range( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[IV_INT]] to i64 |
| ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] |
| ; CHECK-NEXT: store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4 |
| ; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] |
| ; CHECK: cleanup: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] |
| %indvar.conv = sitofp i32 %iv.int to float |
| %conv = fptosi float %indvar.conv to i32 |
| %idxprom = sext i32 %conv to i64 |
| %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom |
| store i32 %conv, i32* %arrayidx, align 4 |
| %dec.int = add nsw i32 %iv.int, -1 |
| %cmp = icmp ugt i32 %dec.int, 0 |
| br i1 %cmp, label %for.body, label %cleanup |
| |
| cleanup: ; preds = %for.body |
| ret void |
| } |
| |
| ; Negative test: The transform is *not* valid because there are too many significant bits |
| define void @sitofp_fptosi_range_overflow() { |
| ; CHECK-LABEL: @sitofp_fptosi_range_overflow( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 16777218, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to float |
| ; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[INDVAR_CONV]] to i32 |
| ; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[CONV]] to i64 |
| ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] |
| ; CHECK-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 |
| ; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] |
| ; CHECK: cleanup: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %iv.int = phi i32 [ 16777218, %entry ], [ %dec.int, %for.body ] ; intermediate 16777218 (= 1 << 24 + 2) |
| %indvar.conv = sitofp i32 %iv.int to float |
| %conv = fptosi float %indvar.conv to i32 |
| %idxprom = sext i32 %conv to i64 |
| %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom |
| store i32 %conv, i32* %arrayidx, align 4 |
| %dec.int = add nsw i32 %iv.int, -1 |
| %cmp = icmp ugt i32 %dec.int, 0 |
| br i1 %cmp, label %for.body, label %cleanup |
| |
| cleanup: ; preds = %for.body |
| ret void |
| } |
| |
| ; Negative test: Type mismatch between the integer IV and the fptosi result |
| define void @sitofp_fptosi_range_mismatch_type() { |
| ; |
| ; CHECK-LABEL: @sitofp_fptosi_range_mismatch_type( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to float |
| ; CHECK-NEXT: [[CONV:%.*]] = fptosi float [[INDVAR_CONV]] to i16 |
| ; CHECK-NEXT: [[IDXPROM32:%.*]] = sext i16 [[CONV]] to i32 |
| ; CHECK-NEXT: [[IDXPROM64:%.*]] = sext i16 [[CONV]] to i64 |
| ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM64]] |
| ; CHECK-NEXT: store i32 [[IDXPROM32]], i32* [[ARRAYIDX]], align 4 |
| ; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] |
| ; CHECK: cleanup: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] |
| %indvar.conv = sitofp i32 %iv.int to float |
| %conv = fptosi float %indvar.conv to i16 |
| %idxprom32 = sext i16 %conv to i32 |
| %idxprom64 = sext i16 %conv to i64 |
| %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom64 |
| store i32 %idxprom32, i32* %arrayidx, align 4 |
| %dec.int = add nsw i32 %iv.int, -1 |
| %cmp = icmp ugt i32 %dec.int, 0 |
| br i1 %cmp, label %for.body, label %cleanup |
| |
| cleanup: ; preds = %for.body |
| ret void |
| } |
| |
| define void @sitofp_fptoui_range() { |
| ; CHECK-LABEL: @sitofp_fptoui_range( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[IV_INT]] to i64 |
| ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] |
| ; CHECK-NEXT: store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4 |
| ; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] |
| ; CHECK: cleanup: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] |
| %indvar.conv = sitofp i32 %iv.int to float |
| %conv = fptoui float %indvar.conv to i32 |
| %idxprom = zext i32 %conv to i64 |
| %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom |
| store i32 %conv, i32* %arrayidx, align 4 |
| %dec.int = add nsw i32 %iv.int, -1 |
| %cmp = icmp sgt i32 %dec.int, 0 |
| br i1 %cmp, label %for.body, label %cleanup |
| |
| cleanup: ; preds = %for.body |
| ret void |
| } |
| |
| ; Range including negative value. |
| define void @sitofp_fptoui_range_with_negative () { |
| ; CHECK-LABEL: @sitofp_fptoui_range_with_negative( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[IV_INT]] to i64 |
| ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] |
| ; CHECK-NEXT: store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4 |
| ; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[DEC_INT]], -100 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] |
| ; CHECK: cleanup: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] |
| %indvar.conv = sitofp i32 %iv.int to float |
| %conv = fptoui float %indvar.conv to i32 |
| %idxprom = zext i32 %conv to i64 |
| %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom |
| store i32 %conv, i32* %arrayidx, align 4 |
| %dec.int = add nsw i32 %iv.int, -1 |
| %cmp = icmp sgt i32 %dec.int, -100 |
| br i1 %cmp, label %for.body, label %cleanup |
| |
| cleanup: ; preds = %for.body |
| ret void |
| } |
| |
| ; https://godbolt.org/z/51MrqYjEf |
| define void @uitofp_fptoui_range () { |
| ; CHECK-LABEL: @uitofp_fptoui_range( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[IV_INT]] to i64 |
| ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] |
| ; CHECK-NEXT: store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4 |
| ; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 3 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] |
| ; CHECK: cleanup: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] |
| %indvar.conv = uitofp i32 %iv.int to float |
| %conv = fptoui float %indvar.conv to i32 |
| %idxprom = zext i32 %conv to i64 |
| %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom |
| store i32 %conv, i32* %arrayidx, align 4 |
| %dec.int = add nsw i32 %iv.int, -1 |
| %cmp = icmp ugt i32 %dec.int, 3 |
| br i1 %cmp, label %for.body, label %cleanup |
| |
| cleanup: ; preds = %for.body |
| ret void |
| } |
| |
| define void @uitofp_fptoui_range_with_negative() { |
| ; CHECK-LABEL: @uitofp_fptoui_range_with_negative( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: store i32 100, i32* getelementptr inbounds ([16777219 x i32], [16777219 x i32]* @array, i64 0, i64 100), align 4 |
| ; CHECK-NEXT: br i1 false, label [[FOR_BODY]], label [[CLEANUP:%.*]] |
| ; CHECK: cleanup: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] |
| %indvar.conv = uitofp i32 %iv.int to float |
| %conv = fptoui float %indvar.conv to i32 |
| %idxprom = zext i32 %conv to i64 |
| %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom |
| store i32 %conv, i32* %arrayidx, align 4 |
| %dec.int = add nsw i32 %iv.int, -1 |
| %cmp = icmp ugt i32 %dec.int, -100 |
| br i1 %cmp, label %for.body, label %cleanup |
| |
| cleanup: ; preds = %for.body |
| ret void |
| } |
| |
| define void @uitofp_fptosi_range () { |
| ; CHECK-LABEL: @uitofp_fptosi_range( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] |
| ; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[IV_INT]] to i64 |
| ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] |
| ; CHECK-NEXT: store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4 |
| ; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 |
| ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 3 |
| ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] |
| ; CHECK: cleanup: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] |
| %indvar.conv = uitofp i32 %iv.int to float |
| %conv = fptosi float %indvar.conv to i32 |
| %idxprom = sext i32 %conv to i64 |
| %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom |
| store i32 %conv, i32* %arrayidx, align 4 |
| %dec.int = add nsw i32 %iv.int, -1 |
| %cmp = icmp ugt i32 %dec.int, 3 |
| br i1 %cmp, label %for.body, label %cleanup |
| |
| cleanup: ; preds = %for.body |
| ret void |
| } |
| |
| define void @uitofp_fptosi_range_with_negative () { |
| ; CHECK-LABEL: @uitofp_fptosi_range_with_negative( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[FOR_BODY:%.*]] |
| ; CHECK: for.body: |
| ; CHECK-NEXT: store i32 100, i32* getelementptr inbounds ([16777219 x i32], [16777219 x i32]* @array, i64 0, i64 100), align 4 |
| ; CHECK-NEXT: br i1 false, label [[FOR_BODY]], label [[CLEANUP:%.*]] |
| ; CHECK: cleanup: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %entry |
| %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] |
| %indvar.conv = uitofp i32 %iv.int to float |
| %conv = fptosi float %indvar.conv to i32 |
| %idxprom = sext i32 %conv to i64 |
| %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom |
| store i32 %conv, i32* %arrayidx, align 4 |
| %dec.int = add nsw i32 %iv.int, -1 |
| %cmp = icmp ugt i32 %dec.int, -100 |
| br i1 %cmp, label %for.body, label %cleanup |
| |
| cleanup: ; preds = %for.body |
| ret void |
| } |
| |