<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/54558>54558</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
An InstCombine patch is making the loop terminating condition more complicated
</td>
</tr>
<tr>
<th>Labels</th>
<td>
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
kazutakahirata
</td>
</tr>
</table>
<pre>
I'm seeing a case where https://github.com/llvm/llvm-project/commit/61580d0949fd3465f53c71f5a8f304d4722a38fb is making the loop terminating condition more complicated.
Consider:
```
define i32 @foo(i32 %arg) {
bb_entry:
br label %bb_outer
bb_outer: ; preds = %bb_inner, %bb_entry
%phi_outer = phi i32 [ %arg, %bb_entry ], [ %sub, %bb_inner ]
%cond_outer = icmp ne i32 %phi_outer, 0
br i1 %cond_outer, label %bb_preheader, label %bb_exit
bb_preheader: ; preds = %bb_outer
%ugt = icmp ugt i32 43, %phi_outer
%sel = select i1 %ugt, i32 %phi_outer, i32 43
%sub = sub i32 %phi_outer, %sel
br label %bb_inner
bb_inner: ; preds = %bb_inner, %bb_preheader
%phi_inner = phi i32 [ %sel, %bb_preheader ], [ %iv, %bb_inner ]
call void @bar()
%iv = add i32 %phi_inner, 1
%cond_inner = icmp ne i32 %phi_inner, 0
br i1 %cond_inner, label %bb_inner, label %bb_outer
bb_exit: ; preds = %bb_outer
ret i32 0
}
declare void @bar()
```
Compile this like so:
```
$ clang -O2 -S reduced.ll
```
After InstCombinePass, I see a diff like so:
```
*** IR Dump After InstCombinePass on foo ***
define i32 @foo(i32 %arg) local_unnamed_addr {
bb_entry:
%cond_outer.not1 = icmp eq i32 %arg, 0
br i1 %cond_outer.not1, label %bb_exit, label %bb_preheader
bb_outer.loopexit: ; preds = %bb_inner
- %cond_outer.not = icmp eq i32 %sub, 0
+ %cond_outer.not = icmp ult i32 %phi_outer2, 44
br i1 %cond_outer.not, label %bb_exit, label %bb_preheader
bb_preheader: ; preds = %bb_entry, %bb_outer.loopexit
%phi_outer2 = phi i32 [ %sub, %bb_outer.loopexit ], [ %arg, %bb_entry ]
%0 = tail call i32 @llvm.umin.i32(i32 %phi_outer2, i32 43)
%sub = sub i32 %phi_outer2, %0
br label %bb_inner
bb_inner: ; preds = %bb_inner, %bb_preheader
%phi_inner = phi i32 [ %0, %bb_preheader ], [ %iv, %bb_inner ]
tail call void @bar()
%iv = add i32 %phi_inner, 1
%cond_inner.not = icmp eq i32 %phi_inner, 0
br i1 %cond_inner.not, label %bb_outer.loopexit, label %bb_inner
bb_exit: ; preds = %bb_outer.loopexit, %bb_entry
ret i32 0
}
```
Notice that `icmp eq i32 ..., 0` is replaced with `icmp ult i32 ..., 44`. This one-liner diff persists all the way through the remaining LLVM IR passes.
At the assembly level, I see a diff like so:
```
foo: # @foo
# %bb.0: # %bb_entry
pushq %rbp
pushq %r14
pushq %rbx
testl %edi, %edi
je .LBB0_5
# %bb.1:
movl %edi, %ebx
.p2align 4, 0x90
.LBB0_3: # %bb_preheader
# =>This Loop Header: Depth=1
# Child Loop BB0_4 Depth 2
cmpl $43, %ebx
movl $43, %r14d
cmovbl %ebx, %r14d
leal -1(%r14), %ebp
.p2align 4, 0x90
.LBB0_4: # %bb_inner
# Parent Loop BB0_3 Depth=1
# => This Inner Loop Header: Depth=2
callq bar@PLT
incl %ebp
jne .LBB0_4
# %bb.2: # %bb_outer.loopexit
# in Loop: Header=BB0_3 Depth=1
- subl %r14d, %ebx
- jne .LBB0_3
+ movl %ebx, %eax
+ subl %r14d, %eax
+ cmpl $44, %ebx
+ movl %eax, %ebx
+ jae .LBB0_3
.LBB0_5: # %bb_exit
xorl %eax, %eax
popq %rbx
popq %r14
popq %rbp
retq
```
Notice that we have three more instructions.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy9WNtu4zYQ_Rr5hbCgqy8PfkjiLhogbRftYl8DSqQsJrSolSgn6dd3SOpC2dIm3l3UMGyLHM4MD4fnkE4EedvdO8H6iGpKWXFAGKW4puglpxVFuZRl7YQ3TvAJ3gcm8yZxU3GEB85P3deyrMQTTSU8Qt-RqR8rP954xNtG24yE0SrO4jBd-1mMN1noRSRaBwEON1mCWI2O-FlFljlFXIgSSVodWYGlakxFQZhkokBHAQmB_5KzFEtKXMfbO96N-bwTRc0IrVSupnnltW_9SGjGCopYGCAn8jIhnGCjH4IYVwcn2CJnfWtMk-SRFrJ6610hlFSI44RyZQ7dooEM7eh9WwjGH3w54S0qK0pq-LVvHbOiACfBXfto0mhzgKYyZyaOHgJPZj7xbT-N0Ujo2esmY1A3yWCgI2mDwb2C2vLP0mOJOsys4MqJZyHD_PFg1W-jBZPMKSaXHfQVKmWM4mD7QSSnULSWR8-rOchhQupBzSgKWzCGeQ0japUjjIBvKOt2hjBSDZmCo3VoOWgS4wC-pwaYGDPlZapgDIxp-7XlNYA9LrG2Ni5LTKV8OfqszNjpO1WWYs7RSTCidmGCIZkN7D0rPjvpwJgQG7c-cf-8XIdcJ8q1HzZTrn3_JfpnjVM7XpfvFSvyfq1W1NRmm66z3tshCU05Bgqcge-M8O6AKBmnQKpAsJw9U1SLOXJ0ggiBb2Db5V8BWv4DiZAmBYblfNL-JlMccV_UEqIkwKufcV0ryO6ViICCEJZl7wUFAG7MG93_jfYNrN6kXwTUD3w9mLfD32d0LqDcHpuiwEdKHqGkqoHk0QTLj2nMLYT0h8qi35Dt3aqpKQ7Ugyf5bpYcW1D67IwfpYcfLLT5Ha99LifmNzW9Vib60rj97riGywuCC9T4KHoPn5-D55cohamAnq7OILfKYpjbJC_ayjp2ckaOMyJtRfJ0AIkZN2TZ1rc6ZrkNnIpcaBgqfYx5p2tb2-H3pChokxnV8owUWdj_L2L0rhp5P6lFFsizinSNJI1lZW57TevSlDBN7ZGzCp2UrvPV-nU6NQo8cUQ9FzA0KNiY-_8UkqVKmzBgtPJsiFzXNcisPHU1qGjJMUgReoG7R2_bsU5rDFyz8lyEviitEwVdcqbWWqtQSaua1bJGap3VDeMFv8F3JZpDrp8resSsUFeNh4evfygtKkF1aD26XtxIbas6jgl_Q5yezFnoKsVTIvWxhXCCsFO1TixDg7jrfUQKOuvR-jjetmzq_Bt8Q2eVlNPtfjRj_zq0S1pLbtopYW05qF-9xROFD_fh9tZ7jC_m4A-qC1ZHcbr0ZUdzywBzdijgZ6SL43XbQWoihFdhckk1H3tpD-HeCX_Thfagrqq_9xq0p6XModv_Aa_qdZczToxTNaXIOETBAANUvsEp6i8vI5h6HId-WExiOxCnpIMaRk7ZcIqVxdLXRKirAeiwi1ZesSjRVYtic9d10H2GQ3EhB-TCn1oKs8Atl9xrzZhZaHtlgFzUNlH6EXmfH74MXaxIe8Qt9J6KYX9EF_sjuAq6mWPLNRiyQs9She0mup_EcglZw0mC91xBzitxeTa7sD9Ijrd6X38Uv9om097HNtZOiM7jXwTCr9MmT_giSdQR1lUUO4AO_l5FdRkYW7u0FOUUo1rNIwK2rK3yAaH99q6yvlCU45N6qECj9N9nDO5WVZOq_9Nqd0F2IdmGW7yQTHK6uynsuxfIoEzzH_97btFUfHf1_4esrhsKd8lPcRTHm0W-W_letlmnmRd6fhr5eB0l8QZH20222mY4IQt9AKp3cOKDs92C7QIvCLwwiP21F0W-G6_xer3J0mQTBxs_IbA_leBzV5-oRXVYVDudQ9IcanXQVoeFoRMUHziO0s4_bmQuqt0z_reR-BnnrMISL3TWO53yf8TEwXw">