diff options
Diffstat (limited to 'llvm/test/Transforms/IndVarSimplify')
| -rw-r--r-- | llvm/test/Transforms/IndVarSimplify/elim-extend.ll | 93 | ||||
| -rw-r--r-- | llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll | 123 |
2 files changed, 216 insertions, 0 deletions
diff --git a/llvm/test/Transforms/IndVarSimplify/elim-extend.ll b/llvm/test/Transforms/IndVarSimplify/elim-extend.ll new file mode 100644 index 00000000000..b494a194136 --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/elim-extend.ll @@ -0,0 +1,93 @@ +; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + +; Tests sign extend elimination in the inner and outer loop. +; %outercount is straightforward to widen, besides being in an outer loop. +; %innercount is currently blocked by lcssa, so is not widened. +; %inneriv can be widened only after proving it has no signed-overflow +; based on the loop test. +define void @nestedIV(i8* %address, i32 %limit) nounwind { +entry: + %limitdec = add i32 %limit, -1 + br label %outerloop + +; CHECK: outerloop: +; +; Eliminate %ofs1 after widening outercount. +; CHECK-NOT: sext +; CHECK: getelementptr +; +; IV rewriting hoists a gep into this block. We don't like that. +; CHECK-NOT: getelementptr +outerloop: + %outercount = phi i32 [ %outerpostcount, %outermerge ], [ 0, %entry ] + %innercount = phi i32 [ %innercount.merge, %outermerge ], [ 0, %entry ] + + %outercountdec = add i32 %outercount, -1 + %ofs1 = sext i32 %outercountdec to i64 + %adr1 = getelementptr i8* %address, i64 %ofs1 + store i8 0, i8* %adr1 + + br label %innerpreheader + +innerpreheader: + %innerprecmp = icmp sgt i32 %limitdec, %innercount + br i1 %innerprecmp, label %innerloop, label %outermerge + +; CHECK: innerloop: +; +; Eliminate %ofs2 after widening inneriv. +; CHECK-NOT: sext +; CHECK: getelementptr +; +; FIXME: We should not increase the number of IVs in this loop. +; sext elimination plus LFTR results in 3 final IVs. +; +; FIXME: eliminate %ofs3 based the loop pre/post conditions +; even though innerpostiv is not NSW, thus sign extending innerpostiv +; does not yield the same expression as incrementing the widened inneriv. +innerloop: + %inneriv = phi i32 [ %innerpostiv, %innerloop ], [ %innercount, %innerpreheader ] + %innerpostiv = add i32 %inneriv, 1 + + %ofs2 = sext i32 %inneriv to i64 + %adr2 = getelementptr i8* %address, i64 %ofs2 + store i8 0, i8* %adr2 + + %ofs3 = sext i32 %innerpostiv to i64 + %adr3 = getelementptr i8* %address, i64 %ofs3 + store i8 0, i8* %adr3 + + %innercmp = icmp sgt i32 %limitdec, %innerpostiv + br i1 %innercmp, label %innerloop, label %innerexit + +innerexit: + %innercount.lcssa = phi i32 [ %innerpostiv, %innerloop ] + br label %outermerge + +; CHECK: outermerge: +; +; Eliminate %ofs4 after widening outercount +; CHECK-NOT: sext +; CHECK: getelementptr +; +; TODO: Eliminate %ofs5 after removing lcssa +outermerge: + %innercount.merge = phi i32 [ %innercount.lcssa, %innerexit ], [ %innercount, %innerpreheader ] + + %ofs4 = sext i32 %outercount to i64 + %adr4 = getelementptr i8* %address, i64 %ofs4 + store i8 0, i8* %adr3 + + %ofs5 = sext i32 %innercount.merge to i64 + %adr5 = getelementptr i8* %address, i64 %ofs5 + store i8 0, i8* %adr4 + + %outerpostcount = add i32 %outercount, 1 + %tmp47 = icmp slt i32 %outerpostcount, %limit + br i1 %tmp47, label %outerloop, label %return + +return: + ret void +} diff --git a/llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll new file mode 100644 index 00000000000..c35feef26f9 --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/no-iv-rewrite.ll @@ -0,0 +1,123 @@ +; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s +; +; Make sure that indvars isn't inserting canonical IVs. +; This is kinda hard to do until linear function test replacement is removed. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + +define i32 @sum(i32* %arr, i32 %n) nounwind { +entry: + %precond = icmp slt i32 0, %n + br i1 %precond, label %ph, label %return + +ph: + br label %loop + +; CHECK: loop: +; +; We should only have 2 IVs. +; CHECK: phi +; CHECK: phi +; CHECK-NOT: phi +; +; sext should be eliminated while preserving gep inboundsness. +; CHECK-NOT: sext +; CHECK: getelementptr inbounds +loop: + %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ] + %s.01 = phi i32 [ 0, %ph ], [ %sinc, %loop ] + %ofs = sext i32 %i.02 to i64 + %adr = getelementptr inbounds i32* %arr, i64 %ofs + %val = load i32* %adr + %sinc = add nsw i32 %s.01, %val + %iinc = add nsw i32 %i.02, 1 + %cond = icmp slt i32 %iinc, %n + br i1 %cond, label %loop, label %exit + +exit: + %s.lcssa = phi i32 [ %sinc, %loop ] + br label %return + +return: + %s.0.lcssa = phi i32 [ %s.lcssa, %exit ], [ 0, %entry ] + ret i32 %s.0.lcssa +} + +define i64 @suml(i32* %arr, i32 %n) nounwind { +entry: + %precond = icmp slt i32 0, %n + br i1 %precond, label %ph, label %return + +ph: + br label %loop + +; CHECK: loop: +; +; We should only have 2 IVs. +; CHECK: phi +; CHECK: phi +; CHECK-NOT: phi +; +; %ofs sext should be eliminated while preserving gep inboundsness. +; CHECK-NOT: sext +; CHECK: getelementptr inbounds +; %vall sext should obviously not be eliminated +; CHECK: sext +loop: + %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ] + %s.01 = phi i64 [ 0, %ph ], [ %sinc, %loop ] + %ofs = sext i32 %i.02 to i64 + %adr = getelementptr inbounds i32* %arr, i64 %ofs + %val = load i32* %adr + %vall = sext i32 %val to i64 + %sinc = add nsw i64 %s.01, %vall + %iinc = add nsw i32 %i.02, 1 + %cond = icmp slt i32 %iinc, %n + br i1 %cond, label %loop, label %exit + +exit: + %s.lcssa = phi i64 [ %sinc, %loop ] + br label %return + +return: + %s.0.lcssa = phi i64 [ %s.lcssa, %exit ], [ 0, %entry ] + ret i64 %s.0.lcssa +} + +define void @outofbounds(i32* %first, i32* %last, i32 %idx) nounwind { + %precond = icmp ne i32* %first, %last + br i1 %precond, label %ph, label %return + +; CHECK: ph: +; It's not indvars' job to perform LICM on %ofs +; CHECK-NOT: sext +ph: + br label %loop + +; CHECK: loop: +; +; Preserve exactly one pointer type IV. +; CHECK: phi i32* +; CHECK-NOT: phi +; +; Don't create any extra adds. +; CHECK-NOT: add +; +; Preserve gep inboundsness, and don't factor it. +; CHECK: getelementptr inbounds i32* %ptriv, i32 1 +; CHECK-NOT: add +loop: + %ptriv = phi i32* [ %first, %ph ], [ %ptrpost, %loop ] + %ofs = sext i32 %idx to i64 + %adr = getelementptr inbounds i32* %ptriv, i64 %ofs + store i32 3, i32* %adr + %ptrpost = getelementptr inbounds i32* %ptriv, i32 1 + %cond = icmp ne i32* %ptrpost, %last + br i1 %cond, label %loop, label %exit + +exit: + br label %return + +return: + ret void +} |

