[llvm-dev] Loop Strength Reduction and lost "nsw" flag

Jonas Paulsson via llvm-dev llvm-dev at lists.llvm.org
Mon Sep 2 07:47:07 PDT 2019


Hi,

I was looking a bit at the handling of "nsw" flags, and found one case I 
am not sure what to do about. Function @f4 in 
test/CodeGen/SystemZ/loop-01.ll contains an add instruction which 
decrements the IV with 1. This result is then compared to against zero 
in the loop latch, but it also has another user.

I find that if i add "nsw" on that add instruction (as done in 
attachement), LSR will create an identical instruction without the flag 
for the other (non-IV) user. The problem is then that during isel, the 
"nsw" flag is lost - it seems that only one add node without it is created.

Any ideas how this could be fixed?

Thanks,

Jonas


bin/llc -mtriple=s390x-linux-gnu -mcpu=z14 f4.ll

cat f4.ll

---

define void @f4(i32* %src, i32* %dest, i64* %dest2, i64 %count) {
entry:
   br label %loop

loop:                                             ; preds = %loop.next, 
%entry
   %left = phi i64 [ %count, %entry ], [ %next, %loop.next ]
   store volatile i64 %left, i64* %dest2
   %val = load volatile i32, i32* %src
   %cmp = icmp eq i32 %val, 0
   br i1 %cmp, label %loop.next, label %loop.store

loop.store:                                       ; preds = %loop
   %add = add i32 %val, 1
   store volatile i32 %add, i32* %dest
   br label %loop.next

loop.next:                                        ; preds = %loop.store, 
%loop
   %next = add nsw i64 %left, -1
   %ext = zext i32 %val to i64
   %shl = shl i64 %ext, 32
   %and = and i64 %next, 4294967295
   %or = or i64 %shl, %and
   store volatile i64 %or, i64* %dest2
   %cont = icmp ne i64 %next, 0
   br i1 %cont, label %loop, label %exit

exit:                                             ; preds = %loop.next
   ret void
}

---

*** IR Dump After Loop Strength Reduction ***
loop.next:                                        ; preds = %loop.store, 
%loop
   %next = add nsw i64 %left, -1
   %0 = add i64 %left, -1
   %ext = zext i32 %val to i64
   %shl = shl i64 %ext, 32
   %and = and i64 %0, 4294967295
   %or = or i64 %shl, %and
   store volatile i64 %or, i64* %dest2
   %cont = icmp ne i64 %next, 0
   br i1 %cont, label %loop, label %exit

-------------- next part --------------
define void @f4(i32* %src, i32* %dest, i64* %dest2, i64 %count) {
entry:
  br label %loop

loop:                                             ; preds = %loop.next, %entry
  %left = phi i64 [ %count, %entry ], [ %next, %loop.next ]
  store volatile i64 %left, i64* %dest2
  %val = load volatile i32, i32* %src
  %cmp = icmp eq i32 %val, 0
  br i1 %cmp, label %loop.next, label %loop.store

loop.store:                                       ; preds = %loop
  %add = add i32 %val, 1
  store volatile i32 %add, i32* %dest
  br label %loop.next

loop.next:                                        ; preds = %loop.store, %loop
  %next = add nsw i64 %left, -1
  %ext = zext i32 %val to i64
  %shl = shl i64 %ext, 32
  %and = and i64 %next, 4294967295
  %or = or i64 %shl, %and
  store volatile i64 %or, i64* %dest2
  %cont = icmp ne i64 %next, 0
  br i1 %cont, label %loop, label %exit

exit:                                             ; preds = %loop.next
  ret void
}


More information about the llvm-dev mailing list