Skip to content

LICM miscompilation #64897

Closed
Closed
@cbeuw

Description

@cbeuw
; ModuleID = 'repro.8de1151540a1c9b4-cgu.0'
source_filename = "repro.8de1151540a1c9b4-cgu.0"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; repro::dump_var1
; Function Attrs: noinline nonlazybind uwtable
define internal fastcc void @_ZN5repro9dump_var117h8dff5c7c82785d52E(i64 noundef %f, i64 noundef %var0, ptr noalias nocapture noundef readonly align 4 dereferenceable(28) %val0, i64 noundef %var1, i32 noundef %val1, i64 noundef %var2, i16 noundef %val2, i64 noundef %var3, ptr noalias nocapture noundef readonly align 8 dereferenceable(136) %val3) unnamed_addr #0 {
start:
  %0 = getelementptr inbounds { [8 x i128], { i32, i8, i8, [2 x i8] } }, ptr %val3, i64 0, i32 1, i32 1
  %_11 = load i8, ptr %0, align 4, !noundef !3
  call void @print_char(i8 noundef zeroext %_11)
  ret void
}

; repro::dump_var2
; Function Attrs: noinline nonlazybind uwtable
define internal fastcc void @_ZN5repro9dump_var217h50ad6f199af3f2eaE(i64 noundef %f, i64 noundef %var0, i64 noundef %val0, i64 noundef %var1, i32 noundef %val1, i64 noundef %var2, ptr noalias nocapture noundef readonly align 8 dereferenceable(136) %val2, i64 noundef %var3, i64 %0) unnamed_addr #0 {
start:
  %.sroa.4.0.extract.shift = lshr i64 %0, 32
  %.sroa.4.0.extract.trunc = trunc i64 %.sroa.4.0.extract.shift to i8
  %1 = getelementptr inbounds { [8 x i128], { i32, i8, i8, [2 x i8] } }, ptr %val2, i64 0, i32 1, i32 1
  %_11 = load i8, ptr %1, align 4, !noundef !3
  call void @print_char(i8 noundef zeroext %_11)
  call void @print_char(i8 noundef zeroext %.sroa.4.0.extract.trunc)
  ret void
}

; Function Attrs: nonlazybind uwtable
define void @fn1() unnamed_addr #1 {
start:
  %_24 = alloca { [8 x i128], { i32, i8, i8, [2 x i8] } }, align 8
  %_23 = alloca { [8 x i128], { i32, i8, i8, [2 x i8] } }, align 8
  %_18 = alloca [7 x i32], align 4
  %0 = getelementptr inbounds { [8 x i128], { i32, i8, i8, [2 x i8] } }, ptr %_23, i64 0, i32 1
  %1 = getelementptr inbounds [7 x i32], ptr %_18, i64 0, i64 1
  %2 = getelementptr inbounds [7 x i32], ptr %_18, i64 0, i64 2
  %3 = getelementptr inbounds [7 x i32], ptr %_18, i64 0, i64 3
  %4 = getelementptr inbounds [7 x i32], ptr %_18, i64 0, i64 4
  %5 = getelementptr inbounds [7 x i32], ptr %_18, i64 0, i64 5
  %6 = getelementptr inbounds [7 x i32], ptr %_18, i64 0, i64 6
  br label %bb1

bb1:                                              ; preds = %bb3, %start
  %_5.0 = phi i64 [ -47, %start ], [ %.lcssa4, %bb3 ]
  %_4.0 = phi i64 [ -47, %start ], [ %_8.lcssa7, %bb3 ]
  store i32 -571572757, ptr %0, align 8
  br label %bb2

bb2:                                              ; preds = %bb2, %bb1
  %_5.1 = phi i64 [ %_5.0, %bb1 ], [ %7, %bb2 ]
  %_4.1 = phi i64 [ %_4.0, %bb1 ], [ %_8, %bb2 ]
  %_8 = mul i64 %_4.1, -47
  %7 = mul i64 %_4.1, -1693353459891306496
  switch i64 %_5.1, label %bb7.loopexit [
    i64 1, label %bb2
    i64 -47, label %bb3
  ]

bb7.loopexit:                                     ; preds = %bb2
  store i32 97, ptr %_18, align 4
  store i32 97, ptr %1, align 4
  store i32 97, ptr %2, align 4
  store i32 97, ptr %3, align 4
  store i32 97, ptr %4, align 4
  store i32 97, ptr %5, align 4
  store i32 97, ptr %6, align 4
  br label %bb7

bb7.loopexit3:                                    ; preds = %bb3
  store i32 97, ptr %_18, align 4
  store i32 97, ptr %1, align 4
  store i32 97, ptr %2, align 4
  store i32 97, ptr %3, align 4
  store i32 97, ptr %4, align 4
  store i32 97, ptr %5, align 4
  store i32 97, ptr %6, align 4
  br label %bb7

bb7:                                              ; preds = %bb7.loopexit3, %bb7.loopexit, %bb5
  ret void

bb3:                                              ; preds = %bb2
  %_8.lcssa7 = phi i64 [ %_8, %bb2 ]
  %.lcssa4 = phi i64 [ %7, %bb2 ]
  %8 = getelementptr inbounds { [8 x i128], { i32, i8, i8, [2 x i8] } }, ptr %_23, i64 0, i32 1
  store i32 97, ptr %8, align 8
  store i64 95947119685, ptr %8, align 8
  %9 = getelementptr inbounds { [8 x i128], { i32, i8, i8, [2 x i8] } }, ptr %_24, i64 0, i32 1
  %10 = getelementptr inbounds { [8 x i128], { i32, i8, i8, [2 x i8] } }, ptr %_24, i64 0, i32 1, i32 1
  %11 = getelementptr inbounds { [8 x i128], { i32, i8, i8, [2 x i8] } }, ptr %_23, i64 0, i32 1, i32 1
  %12 = load i8, ptr %11, align 4, !noundef !3
  %13 = xor i8 %12, -1
  store i8 %13, ptr %10, align 4
  store i8 0, ptr %11, align 4
  %14 = getelementptr inbounds { [8 x i128], { i32, i8, i8, [2 x i8] } }, ptr %_23, i64 0, i32 1, i32 2
  %15 = load i8, ptr %14, align 1, !range !4, !noundef !3
  %16 = load i32, ptr %8, align 8, !noundef !3
  store i32 %16, ptr %9, align 8
  store i8 0, ptr %10, align 4
  %17 = getelementptr inbounds { [8 x i128], { i32, i8, i8, [2 x i8] } }, ptr %_24, i64 0, i32 1, i32 2
  store i8 %15, ptr %17, align 1
  switch i32 %16, label %bb7.loopexit3 [
    i32 0, label %bb1
    i32 1457839173, label %bb5
  ]

bb5:                                              ; preds = %bb3
  %.lcssa12 = phi i8 [ %13, %bb3 ]
  %.lcssa10 = phi i8 [ %15, %bb3 ]
  %.lcssa8 = phi i32 [ %16, %bb3 ]
  store i32 97, ptr %_18, align 4
  store i32 97, ptr %1, align 4
  store i32 97, ptr %2, align 4
  store i32 97, ptr %3, align 4
  store i32 97, ptr %4, align 4
  store i32 97, ptr %5, align 4
  store i32 97, ptr %6, align 4
  %18 = getelementptr inbounds { [8 x i128], { i32, i8, i8, [2 x i8] } }, ptr %_23, i64 0, i32 1, i32 1
  store i128 -89304870548512196620982851945701258489, ptr %_24, align 8
  %_17.sroa.2.0._24.sroa_idx = getelementptr inbounds i8, ptr %_24, i64 16
  store i128 -60367832464323173041853249899068734585, ptr %_17.sroa.2.0._24.sroa_idx, align 8
  %_17.sroa.3.0._24.sroa_idx = getelementptr inbounds i8, ptr %_24, i64 32
  store i128 -93906512331388985662572272619431403526, ptr %_17.sroa.3.0._24.sroa_idx, align 8
  %_17.sroa.4.0._24.sroa_idx = getelementptr inbounds i8, ptr %_24, i64 48
  store i128 -125516722603504180270166493233981031438, ptr %_17.sroa.4.0._24.sroa_idx, align 8
  %_17.sroa.5.0._24.sroa_idx = getelementptr inbounds i8, ptr %_24, i64 64
  store i128 17428368806739377979573757188831317740, ptr %_17.sroa.5.0._24.sroa_idx, align 8
  %_17.sroa.6.0._24.sroa_idx = getelementptr inbounds i8, ptr %_24, i64 80
  store i128 -124632825879573085834035531238990818991, ptr %_17.sroa.6.0._24.sroa_idx, align 8
  %_17.sroa.7.0._24.sroa_idx = getelementptr inbounds i8, ptr %_24, i64 96
  store i128 99533020080114872928824195912378985846, ptr %_17.sroa.7.0._24.sroa_idx, align 8
  %_17.sroa.8.0._24.sroa_idx = getelementptr inbounds i8, ptr %_24, i64 112
  store i128 141971359805814584223867407839838043800, ptr %_17.sroa.8.0._24.sroa_idx, align 8
  call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(128) %_23, ptr noundef nonnull align 8 dereferenceable(128) %_24, i64 128, i1 false)
  store i8 %.lcssa12, ptr %18, align 4
; call repro::dump_var1
  call fastcc void @_ZN5repro9dump_var117h8dff5c7c82785d52E(i64 noundef 1, i64 noundef 26, ptr noalias nocapture noundef nonnull readonly align 4 dereferenceable(28) %_18, i64 noundef 19, i32 noundef 97, i64 noundef 20, i16 noundef 1207, i64 noundef 27, ptr noalias nocapture noundef nonnull readonly align 8 dereferenceable(136) %_23)
  %_21.sroa.4.0.insert.ext = zext i8 %.lcssa10 to i64
  %_21.sroa.4.0.insert.shift = shl nuw nsw i64 %_21.sroa.4.0.insert.ext, 40
  %_21.sroa.3.0.insert.ext = zext i8 %.lcssa12 to i64
  %_21.sroa.3.0.insert.shift = shl nuw nsw i64 %_21.sroa.3.0.insert.ext, 32
  %_21.sroa.3.0.insert.insert = add nuw nsw i64 %_21.sroa.4.0.insert.shift, %_21.sroa.3.0.insert.shift
  %_21.sroa.0.0.insert.ext = zext i32 %.lcssa8 to i64
  %_21.sroa.0.0.insert.insert = add nuw nsw i64 %_21.sroa.3.0.insert.insert, %_21.sroa.0.0.insert.ext
; call repro::dump_var2
  call fastcc void @_ZN5repro9dump_var217h50ad6f199af3f2eaE(i64 noundef 1, i64 noundef 29, i64 noundef -1, i64 noundef 13, i32 noundef 97, i64 noundef 33, ptr noalias nocapture noundef nonnull readonly align 8 dereferenceable(136) %_24, i64 noundef 37, i64 %_21.sroa.0.0.insert.insert)
  br label %bb7
}

; Function Attrs: nonlazybind uwtable
declare void @print_char(i8 noundef zeroext) unnamed_addr #1

; Function Attrs: mustprogress nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #2

attributes #0 = { noinline nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
attributes #1 = { nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
attributes #2 = { mustprogress nocallback nofree nounwind willreturn memory(argmem: readwrite) }

!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}

!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 2, !"RtLibUseGOT", i32 1}
!2 = !{!"rustc version 1.74.0-nightly (ef85656a1 2023-08-21)"}
!3 = !{}
!4 = !{i8 0, i8 2}

When compiled with the helper

#include <stdio.h>

void print_char(unsigned char v) {
    printf("%d\n", v);
}

void fn1(void);

int main() {
    fn1();
}

Should print

$ llc -O0 repro.ll && clang helper.c repro.s && ./a.out
233
0
233

However, with LICM optimisation, this prints something else

$ opt -passes=licm repro.ll -S | llc -o repro.s && clang helper.c repro.s && ./a.out
255
0
255

Metadata

Metadata

Assignees

Labels

llvm:analysisIncludes value tracking, cost tables and constant foldingmiscompilation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions