Skip to content

[IndVarSimplify] WRONG code with i128 and -replexitval=always #83268

Closed
@JonPsson1

Description

@JonPsson1

This program should print -86:

int printf(const char *, ...);

unsigned short a = 0, b = 0;
unsigned __int128 c = 0, d = 0;

unsigned char e(unsigned char f, unsigned char g) { return f + g; }

long h() {
  for (; c != 2; c = e(c, 3)) {
    --d;
    if (d)
      continue;
    return a;
  }
  return b;
}

int main() {
  h();
  printf("%d\n", (int)d);
}

With the option -replexitval=always, the IndVarSimplifyPass does something quite weird that I don't understand. It seems it is trying to compute the final value that is stored in the preheader, but that computation is '0', so it must be wrong.

clang -O3 -march=z15 wrong0.i -o ./a.out <> clang -O3 -march=z15 wrong0.i -o ./a.out -mllvm -replexitval=always

IR Dump After IndVarSimplifyPass on for.body

define dso_local i64 @h() local_unnamed_addr #1 {               define dso_local i64 @h() local_unnamed_addr #1 {
entry:                                                          entry:
  %.pr = load i128, ptr @c, align 8, !tbaa !4                     %.pr = load i128, ptr @c, align 8, !tbaa !4
  %d.promoted = load i128, ptr @d, align 1, !tbaa !4              %d.promoted = load i128, ptr @d, align 1, !tbaa !4
  %cmp.not5 = icmp eq i128 %.pr, 2                                %cmp.not5 = icmp eq i128 %.pr, 2
  %extract.t9 = trunc i128 %.pr to i8                             %extract.t9 = trunc i128 %.pr to i8
  br i1 %cmp.not5, label %return, label %for.body.prehea          br i1 %cmp.not5, label %return, label %for.body.prehea

for.body.preheader:                               ; pred        for.body.preheader:                               ; pred
                                                           >      %0 = add i128 %d.promoted, -1
                                                           >      %1 = mul i8 %extract.t9, 85
                                                           >      %2 = add i8 %1, 85
                                                           >      %3 = zext i8 %2 to i128
                                                           >      %umin = call i128 @llvm.umin.i128(i128 %0, i128 %3)
                                                           >      %4 = sub i128 %0, %umin
  br label %for.body                                              br label %for.body

for.body:                                         ; pred        for.body:                                         ; pred
  %.off0 = phi i8 [ %add.i, %for.inc ], [ %extract.t9, %          %.off0 = phi i8 [ %add.i, %for.inc ], [ %extract.t9, %
  %dec46 = phi i128 [ %dec, %for.inc ], [ %d.promoted, %          %dec46 = phi i128 [ %dec, %for.inc ], [ %d.promoted, %
  %dec = add i128 %dec46, -1                                      %dec = add i128 %dec46, -1
  %tobool.not = icmp eq i128 %dec, 0                              %tobool.not = icmp eq i128 %dec, 0
  br i1 %tobool.not, label %for.body.return_crit_edge, l          br i1 %tobool.not, label %for.body.return_crit_edge, l

for.inc:                                          ; pred        for.inc:                                          ; pred
  %add.i = add i8 %.off0, 3                                       %add.i = add i8 %.off0, 3
  %conv2 = zext i8 %add.i to i128                                 %conv2 = zext i8 %add.i to i128
  store i128 %conv2, ptr @c, align 8, !tbaa !4                    store i128 %conv2, ptr @c, align 8, !tbaa !4
  %cmp.not = icmp eq i8 %add.i, 2                                 %cmp.not = icmp eq i8 %add.i, 2
  br i1 %cmp.not, label %for.cond.return_crit_edge, labe          br i1 %cmp.not, label %for.cond.return_crit_edge, labe

for.cond.return_crit_edge:                        ; pred        for.cond.return_crit_edge:                        ; pred
  %dec.lcssa10 = phi i128 [ %dec, %for.inc ]               |      store i128 %4, ptr @d, align 8, !tbaa !4
  store i128 %dec.lcssa10, ptr @d, align 8, !tbaa !4       <
  br label %return                                                br label %return

for.body.return_crit_edge:                        ; pred        for.body.return_crit_edge:                        ; pred
  %dec.lcssa = phi i128 [ %dec, %for.body ]                |      store i128 %4, ptr @d, align 8, !tbaa !4
  store i128 %dec.lcssa, ptr @d, align 8, !tbaa !4         <
  br label %return                                                br label %return

return:                                           ; pred        return:                                           ; pred
  %retval.0.in.in = phi ptr [ @a, %for.body.return_crit_          %retval.0.in.in = phi ptr [ @a, %for.body.return_crit_
  %retval.0.in = load i16, ptr %retval.0.in.in, align 2,          %retval.0.in = load i16, ptr %retval.0.in.in, align 2,
  %retval.0 = zext i16 %retval.0.in to i64                        %retval.0 = zext i16 %retval.0.in to i64
  ret i64 %retval.0                                               ret i64 %retval.0
}                                                               }
;

@nikic @xortator @uweigand

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Done

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions