llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
26.7k stars 10.93k forks source link

arithmetic miscompile from AArch64 backend #96366

Open regehr opened 1 week ago

regehr commented 1 week ago

this function:

declare void @mumble(i32)

define i32 @f(i32 %0) {
  %2 = sub nuw i32 0, %0
  call void @mumble(i32 %2)
  %3 = sub i32 1, %0
  %4 = sub i32 3, %0
  %5 = mul i32 %0, 1
  %6 = add i32 %3, %5
  %7 = add i32 %6, %4
  ret i32 %7
}

is getting lowered to always return 4:

_f:                       
    stp x29, x30, [sp, #-16]!       
    mov w0, wzr
    bl  _mumble
    mov w0, #4             
    ldp x29, x30, [sp], #16        
    ret

but that's not right. for example, f(9) should give -5

llvmbot commented 1 week ago

@llvm/issue-subscribers-backend-aarch64

Author: John Regehr (regehr)

this function: ```llvm declare void @mumble(i32) define i32 @f(i32 %0) { %2 = sub nuw i32 0, %0 call void @mumble(i32 %2) %3 = sub i32 1, %0 %4 = sub i32 3, %0 %5 = mul i32 %0, 1 %6 = add i32 %3, %5 %7 = add i32 %6, %4 ret i32 %7 } ``` is getting lowered to always return 4: ``` _f: stp x29, x30, [sp, #-16]! .cfi_def_cfa_offset 16 .cfi_offset w30, -8 .cfi_offset w29, -16 mov w0, wzr bl _mumble mov w0, #4 ldp x29, x30, [sp], #16 ret ``` but that's not right. for example, `f(9)` should give `-5`
dtcxzyw commented 1 week ago

It is also incorrect on riscv.

Initial selection DAG: %bb.0 'f:'
SelectionDAG has 26 nodes:
  t0: ch,glue = EntryToken
    t2: i64,ch = CopyFromReg t0, Register:i64 %0
  t3: i32 = truncate t2
  t6: i64 = GlobalAddress<ptr @mumble> 0
    t9: ch,glue = callseq_start t0, TargetConstant:i64<0>, TargetConstant:i64<0>
      t5: i32 = sub nuw Constant:i32<0>, t3
    t7: i64 = any_extend t5
  t11: ch,glue = CopyToReg t9, Register:i64 $x10, t7
  t14: ch,glue = RISCVISD::CALL t11, TargetGlobalAddress:i64<ptr @mumble> 0 [TF=1], Register:i64 $x10, RegisterMask:Untyped, t11:1
    t15: ch,glue = callseq_end t14, TargetConstant:i64<0>, TargetConstant:i64<0>, t14:1
          t17: i32 = sub Constant:i32<1>, t3
          t20: i32 = mul t3, Constant:i32<1>
        t21: i32 = add t17, t20
        t19: i32 = sub Constant:i32<3>, t3
      t22: i32 = add t21, t19
    t23: i64 = any_extend t22
  t24: ch,glue = CopyToReg t15, Register:i64 $x10, t23
  t25: ch = RISCVISD::RET_GLUE t24, Register:i64 $x10, t24:1

Combining: t25: ch = RISCVISD::RET_GLUE t24, Register:i64 $x10, t24:1

Combining: t24: ch,glue = CopyToReg t15, Register:i64 $x10, t23

Combining: t23: i64 = any_extend t22

Combining: t22: i32 = add t21, t19
Creating new node: t26: i32 = sub t21, t3
Creating new node: t27: i32 = add t26, Constant:i32<3>
 ... into: t27: i32 = add t26, Constant:i32<3>

Combining: t27: i32 = add t26, Constant:i32<3>

Combining: t26: i32 = sub t21, t3

Combining: t23: i64 = any_extend t27

Combining: t21: i32 = add t17, t20
Creating new node: t28: i32 = sub t20, t3
Creating new node: t29: i32 = add t28, Constant:i32<1>
 ... into: t29: i32 = add t28, Constant:i32<1>

Combining: t29: i32 = add t28, Constant:i32<1>

Combining: t28: i32 = sub t20, t3

Combining: t26: i32 = sub t29, t3
Creating new node: t30: i32 = sub t28, t3
Creating new node: t31: i32 = add t30, Constant:i32<1>
 ... into: t31: i32 = add t30, Constant:i32<1>

Combining: t28: i32 = sub t20, t3

Combining: t31: i32 = add t30, Constant:i32<1>

Combining: t30: i32 = sub t28, t3

Combining: t27: i32 = add t31, Constant:i32<3>
Creating constant: t32: i32 = Constant<4>
Creating new node: t33: i32 = add t30, Constant:i32<4>
 ... into: t33: i32 = add t30, Constant:i32<4>

Combining: t30: i32 = sub t28, t3

Combining: t33: i32 = add t30, Constant:i32<4>

Combining: t32: i32 = Constant<4>

Combining: t23: i64 = any_extend t33

Combining: t20: i32 = mul t3, Constant:i32<1>
 ... into: t3: i32 = truncate t2

Combining: t30: i32 = sub t28, t3

Combining: t28: i32 = sub t3, t3
 ... into: t4: i32 = Constant<0>

Combining: t15: ch,glue = callseq_end t14, TargetConstant:i64<0>, TargetConstant:i64<0>, t14:1

Combining: t14: ch,glue = RISCVISD::CALL t11, TargetGlobalAddress:i64<ptr @mumble> 0 [TF=1], Register:i64 $x10, RegisterMask:Untyped, t11:1

Combining: t13: Untyped = RegisterMask

Combining: t12: i64 = TargetGlobalAddress<ptr @mumble> 0 [TF=1]

Combining: t11: ch,glue = CopyToReg t9, Register:i64 $x10, t7

Combining: t10: i64 = Register $x10

Combining: t9: ch,glue = callseq_start t0, TargetConstant:i64<0>, TargetConstant:i64<0>

Combining: t8: i64 = TargetConstant<0>

Combining: t7: i64 = any_extend t5

Combining: t5: i32 = sub nuw Constant:i32<0>, t3
 ... into: t4: i32 = Constant<0>

Combining: t33: i32 = add Constant:i32<0>, Constant:i32<4>
 ... into: t32: i32 = Constant<4>

Combining: t32: i32 = Constant<4>

Combining: t23: i64 = any_extend Constant:i32<4>
Creating constant: t34: i64 = Constant<4>
 ... into: t34: i64 = Constant<4>

Combining: t34: i64 = Constant<4>

Combining: t24: ch,glue = CopyToReg t15, Register:i64 $x10, Constant:i64<4>

Combining: t7: i64 = any_extend Constant:i32<0>
Creating constant: t35: i64 = Constant<0>
 ... into: t35: i64 = Constant<0>

Combining: t35: i64 = Constant<0>

Combining: t11: ch,glue = CopyToReg t9, Register:i64 $x10, Constant:i64<0>

Combining: t0: ch,glue = EntryToken

Optimized lowered selection DAG: %bb.0 'f:'
SelectionDAG has 13 nodes:
      t0: ch,glue = EntryToken
    t9: ch,glue = callseq_start t0, TargetConstant:i64<0>, TargetConstant:i64<0>
  t11: ch,glue = CopyToReg t9, Register:i64 $x10, Constant:i64<0>
  t14: ch,glue = RISCVISD::CALL t11, TargetGlobalAddress:i64<ptr @mumble> 0 [TF=1], Register:i64 $x10, RegisterMask:Untyped, t11:1
    t15: ch,glue = callseq_end t14, TargetConstant:i64<0>, TargetConstant:i64<0>, t14:1
  t24: ch,glue = CopyToReg t15, Register:i64 $x10, Constant:i64<4>
  t25: ch = RISCVISD::RET_GLUE t24, Register:i64 $x10, t24:1

I don't know why t30 was changed from t33: i32 = add t30, Constant:i32<4> to t33: i32 = add Constant:i32<0>, Constant:i32<4>.