<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/55672>55672</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[LICM] freeze instruction inhibits hoistng of invariants
</td>
</tr>
<tr>
<th>Labels</th>
<td>
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
max-quazan
</td>
</tr>
</table>
<pre>
Godbolt example:
https://godbolt.org/z/bTGT3Mdxn
opt -passes=licm -debug-only=licm -S
```
define void @test_01(i8 addrspace(1)* addrspace(1)* %arg, i32 %arg2) {
bb:
%tmp103 = load atomic i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %arg unordered, align 8, !dereferenceable_or_null !5, !align !6
%tmp117 = icmp eq i8 addrspace(1)* %tmp103, null
%tmp118 = getelementptr inbounds i8, i8 addrspace(1)* %tmp103, i64 8
%tmp119 = bitcast i8 addrspace(1)* %tmp118 to i32 addrspace(1)*
br i1 %tmp117, label %bb122, label %bb149
bb122: ; preds = %bb
ret void
bb149: ; preds = %bb
br label %bb150
bb150: ; preds = %bb150, %bb149
%tmp151 = phi i32 [ 0, %bb149 ], [ %tmp163, %bb150 ]
%tmp152 = icmp ult i32 %tmp151, %arg2
call void (i1, ...) @llvm.experimental.guard(i1 %tmp152, i32 12) [ "deopt"() ]
%tmp157 = load atomic i32, i32 addrspace(1)* %tmp119 unordered, align 8
%tmp158 = icmp ult i32 %tmp151, %tmp157
call void (i1, ...) @llvm.experimental.guard(i1 %tmp158, i32 12) [ "deopt"() ]
%tmp163 = add i32 %tmp151, 1
br label %bb150
}
define void @test_02(i8 addrspace(1)* addrspace(1)* %arg, i32 %arg2) {
bb:
%tmp103 = load atomic i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %arg unordered, align 8, !dereferenceable_or_null !5, !align !6
%tmp117 = icmp eq i8 addrspace(1)* %tmp103, null
%tmp118 = getelementptr inbounds i8, i8 addrspace(1)* %tmp103, i64 8
%tmp119 = bitcast i8 addrspace(1)* %tmp118 to i32 addrspace(1)*
%freeze = freeze i1 %tmp117
br i1 %freeze, label %bb122, label %bb149
bb122: ; preds = %bb
ret void
bb149: ; preds = %bb
br label %bb150
bb150: ; preds = %bb150, %bb149
%tmp151 = phi i32 [ 0, %bb149 ], [ %tmp163, %bb150 ]
%tmp152 = icmp ult i32 %tmp151, %arg2
call void (i1, ...) @llvm.experimental.guard(i1 %tmp152, i32 12) [ "deopt"() ]
%tmp157 = load atomic i32, i32 addrspace(1)* %tmp119 unordered, align 8
%tmp158 = icmp ult i32 %tmp151, %tmp157
call void (i1, ...) @llvm.experimental.guard(i1 %tmp158, i32 12) [ "deopt"() ]
%tmp163 = add i32 %tmp151, 1
br label %bb150
}
; Function Attrs: nocallback nofree nosync willreturn
declare void @llvm.experimental.guard(i1, ...) #2
!5 = !{i64 16}
!6 = !{i64 8}
```
Output:
```
LICM hoisting to bb149: %tmp157 = load atomic i32, i32 addrspace(1)* %tmp119 unordered, align 8
; ModuleID = 'reduced.ll'
source_filename = "reduced.ll"
define void @test_01(i8 addrspace(1)* addrspace(1)* %arg, i32 %arg2) {
bb:
%tmp103 = load atomic i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %arg unordered, align 8, !dereferenceable_or_null !0, !align !1
%tmp117 = icmp eq i8 addrspace(1)* %tmp103, null
%tmp118 = getelementptr inbounds i8, i8 addrspace(1)* %tmp103, i64 8
%tmp119 = bitcast i8 addrspace(1)* %tmp118 to i32 addrspace(1)*
br i1 %tmp117, label %bb122, label %bb149
bb122: ; preds = %bb
ret void
bb149: ; preds = %bb
%tmp157 = load atomic i32, i32 addrspace(1)* %tmp119 unordered, align 8
br label %bb150
bb150: ; preds = %bb150, %bb149
%tmp151 = phi i32 [ 0, %bb149 ], [ %tmp163, %bb150 ]
%tmp152 = icmp ult i32 %tmp151, %arg2
call void (i1, ...) @llvm.experimental.guard(i1 %tmp152, i32 12) [ "deopt"() ]
%tmp158 = icmp ult i32 %tmp151, %tmp157
call void (i1, ...) @llvm.experimental.guard(i1 %tmp158, i32 12) [ "deopt"() ]
%tmp163 = add i32 %tmp151, 1
br label %bb150
}
define void @test_02(i8 addrspace(1)* addrspace(1)* %arg, i32 %arg2) {
bb:
%tmp103 = load atomic i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %arg unordered, align 8, !dereferenceable_or_null !0, !align !1
%tmp117 = icmp eq i8 addrspace(1)* %tmp103, null
%tmp118 = getelementptr inbounds i8, i8 addrspace(1)* %tmp103, i64 8
%tmp119 = bitcast i8 addrspace(1)* %tmp118 to i32 addrspace(1)*
%freeze = freeze i1 %tmp117
br i1 %freeze, label %bb122, label %bb149
bb122: ; preds = %bb
ret void
bb149: ; preds = %bb
br label %bb150
bb150: ; preds = %bb150, %bb149
%tmp151 = phi i32 [ 0, %bb149 ], [ %tmp163, %bb150 ]
%tmp152 = icmp ult i32 %tmp151, %arg2
call void (i1, ...) @llvm.experimental.guard(i1 %tmp152, i32 12) [ "deopt"() ]
%tmp157 = load atomic i32, i32 addrspace(1)* %tmp119 unordered, align 8
%tmp158 = icmp ult i32 %tmp151, %tmp157
call void (i1, ...) @llvm.experimental.guard(i1 %tmp158, i32 12) [ "deopt"() ]
%tmp163 = add i32 %tmp151, 1
br label %bb150
}
; Function Attrs: nocallback nofree nosync willreturn
declare void @llvm.experimental.guard(i1, ...) #0
attributes #0 = { nocallback nofree nosync willreturn }
!0 = !{i64 16}
!1 = !{i64 8}
```
The only difference between test_02 and test_02 is freeze on loop-invariant condition. In former case invariant load gets hoisted, while in presence of freeze it doesn't. For us, it causes massive negative performance impact after freeze instructions started generated with -freeze-loop-unswitch-cond set to true.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJztWUtv4zgM_jXJRYhhy7HjHHJop-igwBZ72N4L2WIS7dqSR4--fv1SsvNyM-3s7AwGu3WRJrJMkR9p8mOIlIo_rz4rXqraEnhiTVvDJL2YxFeT-GJrbWv8Fb3G16aTipTe4NUL_pd3n-_SW_4kO_HuXbWWzFpmDODRq1pUDZlxKN1mpmT9vN_6oz-Tx_0rXHJYCwnkQQlOJvPYgrH3cTKhhSgI41ybllWAl7i1nNCLs3sTmjEP8RMRKe2vKN4jk8VlZ6Us9y4SL2CbNolTgthIrRgnzKpGVOS8zaD4n6IhTirNQQP3x1ktNpIUfjmhid9e47-sgJU13Ct9L11d-1tZL9IdwEU-QJ0sAmqMaEvgy9dw7V306rzuoZYiaNmAhRoakLa1mghZKie5QaVvuHyiWuRz9Gqgexl0l8JWzNh31CAQq8JjOxf4XnGJ2JJDALzhmpXgA5aVZULpcGe-PM7PTiRFRd_-N0kvSYsPzwRfgtYdGg02pOvABNr8YSbQ4WN3snhgCzf-tS2vJOTaccD2DzFLgmS7FV1NZZfkRBx3rsI13uiP5OlBIIuDwEAnPaSuQ_Lpi7Uz158NldsfqxjWREcMSAdBIoqiUNfzuK4fmgieWtDC5y-ro41jmgfJg8EdJyQdHQSwlAMy1sRnTdHtvgK6eM0M6V7XW9m8PF_2A_XF-3HoYPy4SBTfF4m840h0-TXK5L1sXVwdp-1Zoqcj0Y9ET48f2FoDvEBQ3C9PqH_YETqZsSOMHWHsCP-1juBT8NrJygolyYW12k8eRCrvW8mqv3Dpyxs_zLOsyKOoa6w0p-WuoVQ104eO8pbXx_GhKT1BgVzc10CCbcQTHXLxHikS8-BuMXTjdKDp3n93tnV234sGMr_dfLolWyWMFXLjefGILX5qxvmQ3yruari56t1aoJyrgEfYO2ifX0Y5XcH9WtQgWQO9JD2WPInhOMSd9PZ42NuTAeqP2Ns_3BD3k1vH-I3g134j-JAtexziRqIfh7jvNTFS9jjE_d86wi8b4k6Kh6FhUTrsR-FWVw6Ly2_BQYYOIa2_OQ8mX58HT6e8uy0Q_wsY4WLdNxBSgn0EkKTvnIRJvl8Ls2NLDGWtVDsT8oFpwaQllZJc-BhH5EaStdINaMwfg8y6lwmJjU3CdKNll6uPWxziUMjzhAkQ1HpPypZwBUbi3Gcjcq00cSYkFNpjzmAwG2aMeMCowYZZv8AH440zr0g0WC6WsLVFLDuV0ljtQjYYYizTCAMxSdDMrx6F3ZJZJzsLLjppcLPazryHxCAJY4dBFRB1QZzyVcqX6ZJNrbA1rDDF_fSMOX3GJK63AltZHwGcrdHZfYDM1Ol6NfiJEwG5MqpUgxc--fqPWavVn1BhFV0LYxxgXK6zLF_Q6XaV0nVRVXmS5kk2j-dzllBeJHyRx-slp5BNQ9kYDxVhTsWKxpTGGZ0ncUyTeRTnZV4W1XzJlsUyXxSY9tAwUUch-ZXeTPUqYCjdxviaQFfM4aZ_JBsJsNPPnN0qvWrY0-yLYy9MTgPiVYD7N6keFYc">