1; RUN: opt -loop-reduce -S < %s | FileCheck %s 2 3target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64" 4target triple = "nvptx64-unknown-unknown" 5 6; LSR used not to be able to generate a float* induction variable in 7; these cases due to scalar evolution not propagating nsw from an 8; instruction to the SCEV, preventing distributing sext into the 9; corresponding addrec. 10 11; Test this pattern: 12; 13; for (int i = 0; i < numIterations; ++i) 14; sum += ptr[i + offset]; 15; 16define float @testadd(float* %input, i32 %offset, i32 %numIterations) { 17; CHECK-LABEL: @testadd 18; CHECK: sext i32 %offset to i64 19; CHECK: loop: 20; CHECK-DAG: phi float* 21; CHECK-DAG: phi i32 22; CHECK-NOT: sext 23 24entry: 25 br label %loop 26 27loop: 28 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] 29 %sum = phi float [ %nextsum, %loop ], [ 0.000000e+00, %entry ] 30 %index32 = add nuw nsw i32 %i, %offset 31 %index64 = sext i32 %index32 to i64 32 %ptr = getelementptr inbounds float, float* %input, i64 %index64 33 %addend = load float, float* %ptr, align 4 34 %nextsum = fadd float %sum, %addend 35 %nexti = add nuw nsw i32 %i, 1 36 %exitcond = icmp eq i32 %nexti, %numIterations 37 br i1 %exitcond, label %exit, label %loop 38 39exit: 40 ret float %nextsum 41} 42 43; Test this pattern: 44; 45; for (int i = 0; i < numIterations; ++i) 46; sum += ptr[i - offset]; 47; 48define float @testsub(float* %input, i32 %offset, i32 %numIterations) { 49; CHECK-LABEL: @testsub 50; CHECK: sext i32 %offset to i64 51; CHECK: loop: 52; CHECK-DAG: phi float* 53; CHECK-DAG: phi i32 54; CHECK-NOT: sext 55 56entry: 57 br label %loop 58 59loop: 60 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] 61 %sum = phi float [ %nextsum, %loop ], [ 0.000000e+00, %entry ] 62 %index32 = sub nuw nsw i32 %i, %offset 63 %index64 = sext i32 %index32 to i64 64 %ptr = getelementptr inbounds float, float* %input, i64 %index64 65 %addend = load float, float* %ptr, align 4 66 %nextsum = fadd float %sum, %addend 67 %nexti = add nuw nsw i32 %i, 1 68 %exitcond = icmp eq i32 %nexti, %numIterations 69 br i1 %exitcond, label %exit, label %loop 70 71exit: 72 ret float %nextsum 73} 74 75; Test this pattern: 76; 77; for (int i = 0; i < numIterations; ++i) 78; sum += ptr[i * stride]; 79; 80define float @testmul(float* %input, i32 %stride, i32 %numIterations) { 81; CHECK-LABEL: @testmul 82; CHECK: sext i32 %stride to i64 83; CHECK: loop: 84; CHECK-DAG: phi float* 85; CHECK-DAG: phi i32 86; CHECK-NOT: sext 87 88entry: 89 br label %loop 90 91loop: 92 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] 93 %sum = phi float [ %nextsum, %loop ], [ 0.000000e+00, %entry ] 94 %index32 = mul nuw nsw i32 %i, %stride 95 %index64 = sext i32 %index32 to i64 96 %ptr = getelementptr inbounds float, float* %input, i64 %index64 97 %addend = load float, float* %ptr, align 4 98 %nextsum = fadd float %sum, %addend 99 %nexti = add nuw nsw i32 %i, 1 100 %exitcond = icmp eq i32 %nexti, %numIterations 101 br i1 %exitcond, label %exit, label %loop 102 103exit: 104 ret float %nextsum 105} 106 107; Test this pattern: 108; 109; for (int i = 0; i < numIterations; ++i) 110; sum += ptr[3 * (i << 7)]; 111; 112; The multiplication by 3 is to make the address calculation expensive 113; enough to force the introduction of a pointer induction variable. 114define float @testshl(float* %input, i32 %numIterations) { 115; CHECK-LABEL: @testshl 116; CHECK: loop: 117; CHECK-DAG: phi float* 118; CHECK-DAG: phi i32 119; CHECK-NOT: sext 120 121entry: 122 br label %loop 123 124loop: 125 %i = phi i32 [ %nexti, %loop ], [ 0, %entry ] 126 %sum = phi float [ %nextsum, %loop ], [ 0.000000e+00, %entry ] 127 %index32 = shl nuw nsw i32 %i, 7 128 %index32mul = mul nuw nsw i32 %index32, 3 129 %index64 = sext i32 %index32mul to i64 130 %ptr = getelementptr inbounds float, float* %input, i64 %index64 131 %addend = load float, float* %ptr, align 4 132 %nextsum = fadd float %sum, %addend 133 %nexti = add nuw nsw i32 %i, 1 134 %exitcond = icmp eq i32 %nexti, %numIterations 135 br i1 %exitcond, label %exit, label %loop 136 137exit: 138 ret float %nextsum 139} 140