1; This test aims to check ability to support "Arithmetic with Overflow" intrinsics 2; in the special case when those intrinsics are being generated by the CodeGenPrepare; 3; pass during translations with optimization (note -disable-lsr, to inhibit 4; strength reduction pre-empting with a more preferable match for this pattern 5; in llc arguments). 6 7; RUN: llc -O3 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s 8; RUN: %if spirv-tools %{ llc -O3 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} 9 10; RUN: llc -O3 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s 11; RUN: %if spirv-tools %{ llc -O3 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} 12 13; RUN: llc -O3 -disable-lsr -mtriple=spirv32-unknown-unknown %s -o - | FileCheck --check-prefix=NOLSR %s 14; RUN: %if spirv-tools %{ llc -O3 -disable-lsr -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} 15 16; RUN: llc -O3 -disable-lsr -mtriple=spirv64-unknown-unknown %s -o - | FileCheck --check-prefix=NOLSR %s 17; RUN: %if spirv-tools %{ llc -O3 -disable-lsr -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} 18 19; CHECK-DAG: OpName %[[PhiRes:.*]] "lsr.iv" 20; CHECK-DAG: OpName %[[IsOver:.*]] "fl" 21; CHECK-DAG: OpName %[[Val:.*]] "lsr.iv.next" 22; CHECK-DAG: %[[Int:.*]] = OpTypeInt 32 0 23; CHECK-DAG: %[[Char:.*]] = OpTypeInt 8 0 24; CHECK-DAG: %[[PtrChar:.*]] = OpTypePointer Generic %[[Char]] 25; CHECK-DAG: %[[Bool:.*]] = OpTypeBool 26; CHECK-DAG: %[[Const1:.*]] = OpConstant %[[Int]] 1 27; CHECK-DAG: %[[Zero:.*]] = OpConstant %[[Int]] 0 28; CHECK-DAG: %[[Const42:.*]] = OpConstant %[[Char]] 42 29 30; CHECK: OpFunction 31; CHECK: %[[A:.*]] = OpFunctionParameter %[[Int]] 32; CHECK: %[[Ptr:.*]] = OpFunctionParameter %[[PtrChar]] 33; CHECK: %[[APlusOne:.*]] = OpIAdd %[[Int]] %[[A]] %[[Const1]] 34; CHECK: OpBranch %[[#]] 35; CHECK: [[#]] = OpLabel 36; CHECK: %[[PhiRes]] = OpPhi %[[Int]] %[[Val]] %[[#]] %[[APlusOne]] %[[#]] 37; CHECK: %[[IsOver]] = OpIEqual %[[Bool]] %[[#]] %[[#]] 38; CHECK: OpBranchConditional %[[IsOver]] %[[#]] %[[#]] 39; CHECK: [[#]] = OpLabel 40; CHECK: OpStore %[[Ptr]] %[[Const42]] Aligned 1 41; CHECK: [[Val]] = OpIAdd %[[Int]] %[[PhiRes]] %[[Const1]] 42; CHECK: OpBranch %[[#]] 43; CHECK: [[#]] = OpLabel 44; OpReturnValue %[[PhiRes]] 45 46; NOLSR-DAG: OpName %[[Val:.*]] "math" 47; NOLSR-DAG: OpName %[[IsOver:.*]] "ov" 48; NOLSR-DAG: %[[Int:.*]] = OpTypeInt 32 0 49; NOLSR-DAG: %[[Char:.*]] = OpTypeInt 8 0 50; NOLSR-DAG: %[[PtrChar:.*]] = OpTypePointer Generic %[[Char]] 51; NOLSR-DAG: %[[Bool:.*]] = OpTypeBool 52; NOLSR-DAG: %[[Struct:.*]] = OpTypeStruct %[[Int]] %[[Int]] 53; NOLSR-DAG: %[[Const1:.*]] = OpConstant %[[Int]] 1 54; NOLSR-DAG: %[[Const42:.*]] = OpConstant %[[Char]] 42 55; NOLSR-DAG: %[[Zero:.*]] = OpConstantNull %[[Int]] 56 57; NOLSR: OpFunction 58; NOLSR: %[[A:.*]] = OpFunctionParameter %[[Int]] 59; NOLSR: %[[Ptr:.*]] = OpFunctionParameter %[[PtrChar]] 60; NOLSR: %[[#]] = OpLabel 61; NOLSR: OpBranch %[[#]] 62; NOLSR: %[[#]] = OpLabel 63; NOLSR: %[[PhiRes:.*]] = OpPhi %[[Int]] %[[A]] %[[#]] %[[Val]] %[[#]] 64; NOLSR: %[[AggRes:.*]] = OpIAddCarry %[[Struct]] %[[PhiRes]] %[[Const1]] 65; NOLSR: %[[Val]] = OpCompositeExtract %[[Int]] %[[AggRes]] 0 66; NOLSR: %[[Over:.*]] = OpCompositeExtract %[[Int]] %[[AggRes]] 1 67; NOLSR: %[[IsOver]] = OpINotEqual %[[Bool:.*]] %[[Over]] %[[Zero]] 68; NOLSR: OpBranchConditional %[[IsOver]] %[[#]] %[[#]] 69; NOLSR: OpStore %[[Ptr]] %[[Const42]] Aligned 1 70; NOLSR: OpBranch %[[#]] 71; NOLSR: %[[#]] = OpLabel 72; NOLSR: OpReturnValue %[[Val]] 73; NOLSR: OpFunctionEnd 74 75define spir_func i32 @foo(i32 %a, ptr addrspace(4) %p) { 76entry: 77 br label %l1 78 79body: 80 store i8 42, ptr addrspace(4) %p 81 br label %l1 82 83l1: 84 %e = phi i32 [ %a, %entry ], [ %i, %body ] 85 %i = add nsw i32 %e, 1 86 %fl = icmp eq i32 %i, 0 87 br i1 %fl, label %exit, label %body 88 89exit: 90 ret i32 %i 91} 92