Noinline, no-opt method loses call to other method -O3

Godbolt link: Compiler Explorer

Got a fairly simple function (BADCALLER): that is noinline, optnone, it calls BADCALLEE, however neither the call nor the inlined code is present in the result:

; ModuleID = 'Type.get_Methodsd__6-f73a26d932fbf794da5cc508811d5f14'
target triple = "x86_64-pc-windows-msvc"

%typeobj = type { %rstObject, ptr, ptr, i32, ptr, i32, i32 }
%rstObject = type { ptr }

; Function Attrs: noinline optnone
define void @"BADCALLER"(i32 %x0, ptr %x1, i64 %x2, i64 %x3) #5 {
  %x5 = urem i32 %x0, 11
  switch i32 %x5, label %x6 [
    i32 6, label %x28
  ]

x6:                                                ; preds = %x55, %x45, %x35, %x16, %x4
  call void @__abstract()
  unreachable

x28:                                               ; preds = %x29, %x26
  musttail call void @"BADCALLEE"(i32 %x0, ptr %x1, i64 %x2, i64 %x3)
  ret void
}

define i8 @"$u8"(i32 %x0, ptr nocapture readnone %x1, ptr %x2) unnamed_addr {
  ret i8 0
}

; Function Attrs: uwtable
declare void @__abstract() local_unnamed_addr #4


; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
define ptr @"BADCALLEE"(i32 %x0, ptr nocapture readnone %x1, ptr nocapture readonly %x2) unnamed_addr #7 {
  %x4 = getelementptr %typeobj, ptr %x2, i64 0, i32 1
  %x5 = load ptr, ptr %x4, align 8
  ret ptr %x5
}


attributes #4 = { uwtable }
attributes #5 = { noinline optnone "thunk"="true" }
attributes #7 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }

Result:

        .def    BADCALLER;
        .scl    3;
        .type   32;
        .endef
        .p2align        4, 0x90                         # -- Begin function BADCALLER
BADCALLER:                              # @BADCALLER
.seh_proc BADCALLER
# %bb.0:
        sub     rsp, 40
        .seh_stackalloc 40
        .seh_endprologue
        imul    eax, ecx, -1171354717
        add     eax, -1561806290
        sub     eax, 390451572
        jb      .LBB0_2
        jmp     .LBB0_1
.LBB0_1:                                # %x6
        call    __abstract
.LBB0_2:                                # %x28
        nop
        add     rsp, 40
        ret
        .seh_endproc

Note how it does call __abstract but not BADCALLEE.

Can someone tell me what I’m doing wrong?

(Cmdline -O3 -filetype=asm)

Your function has internal linkage but no uses. It is simply deleted.

Fixed (doesn’t change the effect).

What seems to happen is that because the result of the musttail call isn’t used (it’s a thunk), and the function has no side effects, it’s completely eliminated.

Yep:

  %a = musttail call i64 @"BADCALLEE"(i32 %x0, ptr %x1, i64 %x2, i64 %x3)
  ret i64 %a

(And changing the result of BADCALLER ofc) fixes it.

Just removing memory(argmem: read) from the callee attributes is enough to make it preserving the jmp

1 Like