mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-29 10:25:12 +00:00
indvars: fixed IV cloning in -disable-iv-rewrite mode with associated
cleanup and overdue test cases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132038 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
93
test/Transforms/IndVarSimplify/elim-extend.ll
Normal file
93
test/Transforms/IndVarSimplify/elim-extend.ll
Normal file
@@ -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
|
||||
}
|
123
test/Transforms/IndVarSimplify/no-iv-rewrite.ll
Normal file
123
test/Transforms/IndVarSimplify/no-iv-rewrite.ll
Normal file
@@ -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
|
||||
}
|
Reference in New Issue
Block a user