[llvm] [polly] [SCEV] Introduce SDiv expressions (PR #216862)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 24 03:16:04 PDT 2026
artagnon wrote:
> > Included in description, thanks. There are improvements from analyzing sdiv instructions in IR, independently of any stride expressions, and the compile-time increase is in noise anyway.
>
> With example I meant an example loop (IR) to show a concrete motivating case.
Not sure exactly if this is what you mean, but it's pretty easy to craft examples:
```llvm
define void @stride.1(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%mul = mul i64 %iv, %stride
%gep.A = getelementptr nusw i32, ptr %A, i64 %mul
%load = load i32, ptr %gep.A, align 4
%gep.B = getelementptr nusw i32, ptr %B, i64 %iv
%load_1 = load i32, ptr %gep.B, align 4
%add = add i32 %load_1, %load
%iv.next = add nuw nsw i64 %iv, 1
%gep.A.next = getelementptr nusw i32, ptr %A, i64 %iv.next
store i32 %add, ptr %gep.A.next, align 4
%exitcond = icmp eq i64 %iv.next, %N
br i1 %exitcond, label %exit, label %loop
exit: ; preds = %loop
ret void
}
define void @stride.minus1(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {
entry:
%stride.minus1 = mul i64 %stride, -1
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%mul = mul i64 %iv, %stride.minus1
%gep.A = getelementptr nusw i32, ptr %A, i64 %mul
%load = load i32, ptr %gep.A, align 4
%gep.B = getelementptr nusw i32, ptr %B, i64 %iv
%load_1 = load i32, ptr %gep.B, align 4
%add = add i32 %load_1, %load
%iv.next = add nuw nsw i64 %iv, 1
%gep.A.next = getelementptr nusw i32, ptr %A, i64 %iv.next
store i32 %add, ptr %gep.A.next, align 4
%exitcond = icmp eq i64 %iv.next, %N
br i1 %exitcond, label %exit, label %loop
exit: ; preds = %loop
ret void
}
define void @stride.2(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {
entry:
%stride.2 = mul i64 %stride, 2
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%mul = mul i64 %iv, %stride.2
%gep.A = getelementptr nusw i32, ptr %A, i64 %mul
%load = load i32, ptr %gep.A, align 4
%gep.B = getelementptr nusw i32, ptr %B, i64 %iv
%load_1 = load i32, ptr %gep.B, align 4
%add = add i32 %load_1, %load
%iv.next = add nuw nsw i64 %iv, 1
%gep.A.next = getelementptr nusw i32, ptr %A, i64 %iv.next
store i32 %add, ptr %gep.A.next, align 4
%exitcond = icmp eq i64 %iv.next, %N
br i1 %exitcond, label %exit, label %loop
exit: ; preds = %loop
ret void
}
define void @stride.div.2(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {
entry:
%stride.div.2 = udiv i64 %stride, 2
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%mul = mul i64 %iv, %stride.div.2
%gep.A = getelementptr nusw i32, ptr %A, i64 %mul
%load = load i32, ptr %gep.A, align 4
%gep.B = getelementptr nusw i32, ptr %B, i64 %iv
%load_1 = load i32, ptr %gep.B, align 4
%add = add i32 %load_1, %load
%iv.next = add nuw nsw i64 %iv, 1
%gep.A.next = getelementptr nusw i32, ptr %A, i64 %iv.next
store i32 %add, ptr %gep.A.next, align 4
%exitcond = icmp eq i64 %iv.next, %N
br i1 %exitcond, label %exit, label %loop
exit: ; preds = %loop
ret void
}
define void @stride.max.of(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {
entry:
%stride.max.of = call i64 @llvm.umax(i64 %stride, i64 3)
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%mul = mul i64 %iv, %stride
%gep.A = getelementptr nusw i32, ptr %A, i64 %mul
%load = load i32, ptr %gep.A, align 4
%gep.B = getelementptr nusw i32, ptr %B, i64 %iv
%load_1 = load i32, ptr %gep.B, align 4
%add = add i32 %load_1, %load
%iv.next = add nuw nsw i64 %iv, 1
%gep.A.next = getelementptr nusw i32, ptr %A, i64 %iv.next
store i32 %add, ptr %gep.A.next, align 4
%exitcond = icmp eq i64 %iv.next, %N
br i1 %exitcond, label %exit, label %loop
exit: ; preds = %loop
ret void
}
```
we do stride speculation successfully in the first case, the second and third cases can be handled pretty easily with just a SCEVConstant, but if the stride expression is more complicated, we would need sdiv to successfully speculate and vectorize? The stride is rarely an argument to the function, but rather a computation in a block before the vector loop: sure, we handle SCEVMul of a SCEVUnknown with an AddRec, but wouldn't we need a first-class expression to speculate further successfully?
https://github.com/llvm/llvm-project/pull/216862
More information about the llvm-commits
mailing list