Skip to content

[InstCombine] Miscompilation caused by incorrect ICMP predicate #123151

Closed as not planned
@mshockwave

Description

@mshockwave

This is discovered from 445.gobmk when compiling it with RISC-V LLVM:

clang --target riscv64-linux-gnu -mcpu=sifive-p670 -O1 -mno-implicit-float ...

This is the reproducer snippet:

define dso_local i1 @gg_sort.do.body.split(i32 %gap.0, i64 %width, ptr %base, ptr %div.out, ptr %add.ptr4.out, i64 noundef %nel) {
newFuncRoot:
  %sub = add i64 %nel, -1
  %mul = mul i64 %width, %sub
  %add.ptr = getelementptr inbounds nuw i8, ptr %base, i64 %mul
  br label %do.body.split

do.body.split:                                    ; preds = %newFuncRoot
  %mul1 = mul nsw i32 %gap.0, 10
  %add = add nsw i32 %mul1, 3
  %div = sdiv i32 %add, 13
  store i32 %div, ptr %div.out, align 4
  %conv2 = sext i32 %div to i64
  %mul3 = mul i64 %conv2, %width
  %add.ptr4 = getelementptr inbounds nuw i8, ptr %base, i64 %mul3
  store ptr %add.ptr4, ptr %add.ptr4.out, align 8
  %cmp5.not21 = icmp ugt ptr %add.ptr4, %add.ptr
  br i1 %cmp5.not21, label %for.end.exitStub, label %for.body.exitStub

for.end.exitStub:                                 ; preds = %do.body.split
  ret i1 true

for.body.exitStub:                                ; preds = %do.body.split
  ret i1 false
}

With this command:

opt -p instcombine input.ll ...

The following code is generated:

define dso_local i1 @gg_sort.do.body.split(i32 %gap.0, i64 %width, ptr %base, ptr %div.out, ptr %add.ptr4.out, i64 noundef %nel) {
newFuncRoot:
  br label %do.body.split

do.body.split:                                    ; preds = %newFuncRoot
  %sub = add i64 %nel, -1
  %mul = mul i64 %width, %sub
  %mul1 = mul nsw i32 %gap.0, 10
  %add = add nsw i32 %mul1, 3
  %div = sdiv i32 %add, 13
  store i32 %div, ptr %div.out, align 4
  %conv2 = sext i32 %div to i64
  %mul3 = mul i64 %width, %conv2
  %add.ptr4 = getelementptr inbounds nuw i8, ptr %base, i64 %mul3
  store ptr %add.ptr4, ptr %add.ptr4.out, align 8
  %cmp5.not21 = icmp samesign ugt i64 %mul3, %mul
  br i1 %cmp5.not21, label %for.end.exitStub, label %for.body.exitStub

for.end.exitStub:                                 ; preds = %do.body.split
  ret i1 true

for.body.exitStub:                                ; preds = %do.body.split
  ret i1 false
}

InstCombine reduces ICMP on pointers (i.e. %add.ptr and %add.ptr4) into ICMP of their offsets (i.e. %mul3 and %mul). I think the problem here is %mul3 and %mul might have different signs.

Changing ICMP into sign comparison solves this issue: %cmp5.not21 = icmp sgt i64 %mul3, %mul

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions