Index: test/CodeGen/ARM/su_addsub_overflow.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/su_addsub_overflow.ll @@ -0,0 +1,101 @@ +; RUN: llc < %s -mtriple=arm-eabi -mcpu=generic | FileCheck %s + +define i32 @sadd(i32 %a, i32 %b) local_unnamed_addr #0 { +; CHECK-LABEL: sadd: +; CHECK: mov r2, r0 +; CHECK-NEXT: add r0, r2, r1 +; CHECK-NEXT: mov r1, #1 +; CHECK-NEXT: cmp r0, r2 +; CHECK-NEXT: movvc r1, #0 +; CHECK-NEXT: cmp r1, #0 +; CHECK-NEXT: moveq pc, lr +entry: + %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 %b) + %1 = extractvalue { i32, i1 } %0, 1 + br i1 %1, label %trap, label %cont + +trap: + tail call void @llvm.trap() #2 + unreachable + +cont: + %2 = extractvalue { i32, i1 } %0, 0 + ret i32 %2 + +} + +define i32 @uadd(i32 %a, i32 %b) local_unnamed_addr #0 { +; CHECK-LABEL: uadd: +; CHECK: mov r2, r0 +; CHECK-NEXT: add r0, r2, r1 +; CHECK-NEXT: mov r1, #1 +; CHECK-NEXT: cmp r0, r2 +; CHECK-NEXT: movhs r1, #0 +; CHECK-NEXT: cmp r1, #0 +; CHECK-NEXT: moveq pc, lr +entry: + %0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32 %b) + %1 = extractvalue { i32, i1 } %0, 1 + br i1 %1, label %trap, label %cont + +trap: + tail call void @llvm.trap() #2 + unreachable + +cont: + %2 = extractvalue { i32, i1 } %0, 0 + ret i32 %2 + +} + +define i32 @ssub(i32 %a, i32 %b) local_unnamed_addr #0 { +; CHECK-LABEL: ssub: +; CHECK: mov r2, #1 +; CHECK-NEXT: cmp r0, r1 +; CHECK-NEXT: movvc r2, #0 +; CHECK-NEXT: cmp r2, #0 +; CHECK-NEXT: subeq r0, r0, r1 +; CHECK-NEXT: moveq pc, lr +entry: + %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %a, i32 %b) + %1 = extractvalue { i32, i1 } %0, 1 + br i1 %1, label %trap, label %cont + +trap: + tail call void @llvm.trap() #2 + unreachable + +cont: + %2 = extractvalue { i32, i1 } %0, 0 + ret i32 %2 + +} + +define i32 @usub(i32 %a, i32 %b) local_unnamed_addr #0 { +; CHECK-LABEL: usub: +; CHECK: mov r2, #1 +; CHECK-NEXT: cmp r0, r1 +; CHECK-NEXT: movhs r2, #0 +; CHECK-NEXT: cmp r2, #0 +; CHECK-NEXT: subeq r0, r0, r1 +; CHECK-NEXT: moveq pc, lr +entry: + %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %a, i32 %b) + %1 = extractvalue { i32, i1 } %0, 1 + br i1 %1, label %trap, label %cont + +trap: + tail call void @llvm.trap() #2 + unreachable + +cont: + %2 = extractvalue { i32, i1 } %0, 0 + ret i32 %2 + +} + +declare void @llvm.trap() #2 +declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) #1 +declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) #1 +declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) #1 +declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) #1