16bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// RUN: %clang_cc1 -O1 -triple arm64-apple-ios7 -target-feature +neon -ffreestanding -S -o - -emit-llvm %s | FileCheck %s 26bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// RUN: %clang_cc1 -O1 -triple arm64-apple-ios7 -target-feature +neon -ffreestanding -S -o - %s | FileCheck -check-prefix=CHECK-CODEGEN %s 3c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines// REQUIRES: aarch64-registered-target 4651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Test ARM64 SIMD max/min intrinsics 5651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 6651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <arm_neon.h> 7651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 8651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Test a represntative sample of 8 and 16, signed and unsigned, 64 and 128 bit reduction 9651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesint8_t test_vmaxv_s8(int8x8_t a1) { 100e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define i8 @test_vmaxv_s8( 11651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxv_s8(a1); 120e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call i32 @llvm.aarch64.neon.smaxv.i32.v8i8( 13651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 14651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 15651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesuint16_t test_vminvq_u16(uint16x8_t a1) { 160e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define i16 @test_vminvq_u16( 17651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vminvq_u16(a1); 180e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call i32 @llvm.aarch64.neon.uminv.i32.v8i16( 19651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 20651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 21651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Test a represntative sample of 8 and 16, signed and unsigned, 64 and 128 bit pairwise 22651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesuint8x8_t test_vmin_u8(uint8x8_t a1, uint8x8_t a2) { 230e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define <8 x i8> @test_vmin_u8( 24651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmin_u8(a1, a2); 250e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call <8 x i8> @llvm.aarch64.neon.umin.v8i8( 26651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 27651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 28651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesuint8x16_t test_vminq_u8(uint8x16_t a1, uint8x16_t a2) { 290e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define <16 x i8> @test_vminq_u8( 30651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vminq_u8(a1, a2); 310e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call <16 x i8> @llvm.aarch64.neon.umin.v16i8( 32651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 33651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 34651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesint16x8_t test_vmaxq_s16(int16x8_t a1, int16x8_t a2) { 350e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define <8 x i16> @test_vmaxq_s16( 36651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxq_s16(a1, a2); 370e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call <8 x i16> @llvm.aarch64.neon.smax.v8i16( 38651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 39651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 40651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Test the more complicated cases of [suf]32 and f64 41651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat64x2_t test_vmaxq_f64(float64x2_t a1, float64x2_t a2) { 420e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define <2 x double> @test_vmaxq_f64( 43651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxq_f64(a1, a2); 440e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call <2 x double> @llvm.aarch64.neon.fmax.v2f64( 45651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 46651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 47651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat32x4_t test_vmaxq_f32(float32x4_t a1, float32x4_t a2) { 480e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define <4 x float> @test_vmaxq_f32( 49651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxq_f32(a1, a2); 500e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call <4 x float> @llvm.aarch64.neon.fmax.v4f32( 51651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 52651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 53651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat64x2_t test_vminq_f64(float64x2_t a1, float64x2_t a2) { 540e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define <2 x double> @test_vminq_f64( 55651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vminq_f64(a1, a2); 560e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call <2 x double> @llvm.aarch64.neon.fmin.v2f64( 57651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 58651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 59651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat32x2_t test_vmax_f32(float32x2_t a1, float32x2_t a2) { 600e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define <2 x float> @test_vmax_f32( 61651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmax_f32(a1, a2); 620e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call <2 x float> @llvm.aarch64.neon.fmax.v2f32( 63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 64651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 65651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesint32x2_t test_vmax_s32(int32x2_t a1, int32x2_t a2) { 660e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define <2 x i32> @test_vmax_s32( 67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmax_s32(a1, a2); 680e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call <2 x i32> @llvm.aarch64.neon.smax.v2i32( 69651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 70651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesuint32x2_t test_vmin_u32(uint32x2_t a1, uint32x2_t a2) { 720e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define <2 x i32> @test_vmin_u32( 73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmin_u32(a1, a2); 740e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call <2 x i32> @llvm.aarch64.neon.umin.v2i32( 75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 76651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat32_t test_vmaxnmv_f32(float32x2_t a1) { 780e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define float @test_vmaxnmv_f32( 79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxnmv_f32(a1); 806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // CHECK: llvm.aarch64.neon.fmaxnmv.f32.v2f32 81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT: ret 82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// this doesn't translate into a valid instruction, regardless of what the 85651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// ARM doc says. 86651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#if 0 87651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat64_t test_vmaxnmvq_f64(float64x2_t a1) { 88651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK@ test_vmaxnmvq_f64 89651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxnmvq_f64(a1); 906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // CHECK@ llvm.aarch64.neon.saddlv.i64.v2i32 91651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT@ ret 92651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 93651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#endif 94651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 95651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat32_t test_vmaxnmvq_f32(float32x4_t a1) { 960e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define float @test_vmaxnmvq_f32( 97651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxnmvq_f32(a1); 980e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call float @llvm.aarch64.neon.fmaxnmv.f32.v4f32( 99651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT: ret 100651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 101651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 102651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat32_t test_vmaxv_f32(float32x2_t a1) { 1030e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define float @test_vmaxv_f32( 104651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxv_f32(a1); 1050e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call float @llvm.aarch64.neon.fmaxv.f32.v2f32( 106651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // FIXME check that the 2nd and 3rd arguments are the same V register below 107651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-CODEGEN: fmaxp.2s 108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT: ret 109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesint32_t test_vmaxv_s32(int32x2_t a1) { 1120e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define i32 @test_vmaxv_s32( 113651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxv_s32(a1); 1140e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call i32 @llvm.aarch64.neon.smaxv.i32.v2i32( 115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // FIXME check that the 2nd and 3rd arguments are the same V register below 116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-CODEGEN: smaxp.2s 117651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT: ret 118651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesuint32_t test_vmaxv_u32(uint32x2_t a1) { 1210e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define i32 @test_vmaxv_u32( 122651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxv_u32(a1); 1230e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call i32 @llvm.aarch64.neon.umaxv.i32.v2i32( 124651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // FIXME check that the 2nd and 3rd arguments are the same V register below 125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-CODEGEN: umaxp.2s 126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT: ret 127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 128651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 129651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// FIXME punt on this for now; don't forget to fix CHECKs 130651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#if 0 131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat64_t test_vmaxvq_f64(float64x2_t a1) { 132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK@ test_vmaxvq_f64 133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxvq_f64(a1); 1346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // CHECK@ llvm.aarch64.neon.fmaxv.i64.v2f64 135651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT@ ret 136651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#endif 138651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 139651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat32_t test_vmaxvq_f32(float32x4_t a1) { 1400e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define float @test_vmaxvq_f32( 141651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vmaxvq_f32(a1); 1420e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call float @llvm.aarch64.neon.fmaxv.f32.v4f32( 143651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT: ret 144651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 145651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 146651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat32_t test_vminnmv_f32(float32x2_t a1) { 1470e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define float @test_vminnmv_f32( 148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vminnmv_f32(a1); 1490e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call float @llvm.aarch64.neon.fminnmv.f32.v2f32( 150651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT: ret 151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat32_t test_vminvq_f32(float32x4_t a1) { 1540e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define float @test_vminvq_f32( 155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vminvq_f32(a1); 1560e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call float @llvm.aarch64.neon.fminv.f32.v4f32( 157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT: ret 158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 160651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// this doesn't translate into a valid instruction, regardless of what the ARM 161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// doc says. 162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#if 0 163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat64_t test_vminnmvq_f64(float64x2_t a1) { 164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK@ test_vminnmvq_f64 165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vminnmvq_f64(a1); 1666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // CHECK@ llvm.aarch64.neon.saddlv.i64.v2i32 167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT@ ret 168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#endif 170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat32_t test_vminnmvq_f32(float32x4_t a1) { 1720e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define float @test_vminnmvq_f32( 173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vminnmvq_f32(a1); 1740e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call float @llvm.aarch64.neon.fminnmv.f32.v4f32( 175651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT: ret 176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 177651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 178651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat32_t test_vminv_f32(float32x2_t a1) { 1790e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define float @test_vminv_f32( 180651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vminv_f32(a1); 1810e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call float @llvm.aarch64.neon.fminv.f32.v2f32( 182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT: ret 183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesint32_t test_vminv_s32(int32x2_t a1) { 1860e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define i32 @test_vminv_s32( 187651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vminv_s32(a1); 1880e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call i32 @llvm.aarch64.neon.sminv.i32.v2i32( 189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-CODEGEN: sminp.2s 190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT: ret 191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesuint32_t test_vminv_u32(uint32x2_t a1) { 1940e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK-LABEL: define i32 @test_vminv_u32( 195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vminv_u32(a1); 1960e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // CHECK: call i32 @llvm.aarch64.neon.uminv.i32.v2i32( 197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 199651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// FIXME punt on this for now; don't forget to fix CHECKs 200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#if 0 201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesfloat64_t test_vminvq_f64(float64x2_t a1) { 202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK@ test_vminvq_f64 203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return vminvq_f64(a1); 2046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // CHECK@ llvm.aarch64.neon.saddlv.i64.v2i32 205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // CHECK-NEXT@ ret 206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#endif 208