<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">