diff --git a/llvm/test/Analysis/CostModel/RISCV/gep-zero-indices.ll b/llvm/test/Analysis/CostModel/RISCV/gep-zero-indices.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/CostModel/RISCV/gep-zero-indices.ll @@ -0,0 +1,102 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 2 +; RUN: opt -mtriple=riscv32 -mattr=+v -passes="print" 2>&1 -disable-output < %s \ +; RUN: | FileCheck %s +; RUN: opt -mtriple=riscv64 -mattr=+v -passes="print" 2>&1 -disable-output < %s \ +; RUN: | FileCheck %s + +; These GEPs should all cost zero becuase all the indices operands are zero, so +; no computation actually needs to happen. + +define ptr @zero_indices_i8(ptr %p) { +; CHECK-LABEL: 'zero_indices_i8' +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %x = getelementptr i8, ptr %p, i32 0 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret ptr %x +; + %x = getelementptr i8, ptr %p, i32 0 + ret ptr %x +} + +define ptr @zero_indices_i16(ptr %p) { +; CHECK-LABEL: 'zero_indices_i16' +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %x = getelementptr i16, ptr %p, i32 0 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret ptr %x +; + %x = getelementptr i16, ptr %p, i32 0 + ret ptr %x +} + +define ptr @zero_indices_i32(ptr %p) { +; CHECK-LABEL: 'zero_indices_i32' +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %x = getelementptr i32, ptr %p, i32 0 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret ptr %x +; + %x = getelementptr i32, ptr %p, i32 0 + ret ptr %x +} + +define ptr @zero_indices_i64(ptr %p) { +; CHECK-LABEL: 'zero_indices_i64' +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %x = getelementptr i64, ptr %p, i32 0 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret ptr %x +; + %x = getelementptr i64, ptr %p, i32 0 + ret ptr %x +} + +define ptr @zero_indices_array(ptr %p) { +; CHECK-LABEL: 'zero_indices_array' +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %x = getelementptr [42 x i64], ptr %p, i32 0, i32 0 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret ptr %x +; + %x = getelementptr [42 x i64], ptr %p, i32 0, i32 0 + ret ptr %x +} + +%struct = type { %struct.inner } +%struct.inner = type { %struct.inner.inner } +%struct.inner.inner = type { i32 } + +define ptr @zero_indices_struct(ptr %p) { +; CHECK-LABEL: 'zero_indices_struct' +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %x = getelementptr %struct, ptr %p, i32 0, i32 0, i32 0 +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret ptr %x +; + %x = getelementptr %struct, ptr %p, i32 0, i32 0, i32 0 + ret ptr %x +} + +define <4 x ptr> @zero_indices_v4i32(<4 x ptr> %p) { +; CHECK-LABEL: 'zero_indices_v4i32' +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %x = getelementptr i32, <4 x ptr> %p, <4 x i32> zeroinitializer +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret <4 x ptr> %x +; + %x = getelementptr i32, <4 x ptr> %p, <4 x i32> zeroinitializer + ret <4 x ptr> %x +} + +define <16 x ptr> @zero_indices_v16i32(<16 x ptr> %p) { +; CHECK-LABEL: 'zero_indices_v16i32' +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %x = getelementptr i32, <16 x ptr> %p, <16 x i32> zeroinitializer +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret <16 x ptr> %x +; + %x = getelementptr i32, <16 x ptr> %p, <16 x i32> zeroinitializer + ret <16 x ptr> %x +} + +define <4 x ptr> @zero_indices_v4f32(<4 x ptr> %p) { +; CHECK-LABEL: 'zero_indices_v4f32' +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %x = getelementptr float, <4 x ptr> %p, <4 x i32> zeroinitializer +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret <4 x ptr> %x +; + %x = getelementptr float, <4 x ptr> %p, <4 x i32> zeroinitializer + ret <4 x ptr> %x +} + +define <4 x ptr> @zero_indices_v4v4i32(<4 x ptr> %p) { +; CHECK-LABEL: 'zero_indices_v4v4i32' +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %x = getelementptr <32 x i32>, <4 x ptr> %p, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer +; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret <4 x ptr> %x +; + %x = getelementptr <32 x i32>, <4 x ptr> %p, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer + ret <4 x ptr> %x +} diff --git a/llvm/test/Analysis/CostModel/RISCV/gep.ll b/llvm/test/Analysis/CostModel/RISCV/gep.ll --- a/llvm/test/Analysis/CostModel/RISCV/gep.ll +++ b/llvm/test/Analysis/CostModel/RISCV/gep.ll @@ -1,165 +1,409 @@ ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py -; RUN: opt -mtriple=riscv32 -passes="print" 2>&1 -disable-output < %s \ -; RUN: | FileCheck %s -check-prefix=RVI -; RUN: opt -mtriple=riscv64 -passes="print" 2>&1 -disable-output < %s \ -; RUN: | FileCheck %s -check-prefix=RVI +; RUN: opt -mtriple=riscv32 -mattr=+v -passes="print" 2>&1 \ +; RUN: -disable-output < %s | FileCheck %s -check-prefix=RVI +; RUN: opt -mtriple=riscv64 -mattr=+v -passes="print" 2>&1 \ +; RUN: -disable-output < %s | FileCheck %s -check-prefix=RVI define void @testi8(ptr %a, i32 %i) { ; RVI-LABEL: 'testi8' ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = getelementptr inbounds i8, ptr %a, i32 1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i8 undef, ptr %a1, align 1 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = getelementptr inbounds i8, ptr %a, i32 -1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i8 undef, ptr %a2, align 1 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = getelementptr inbounds i8, ptr %a, i32 2047 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i8 undef, ptr %a3, align 1 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a4 = getelementptr inbounds i8, ptr %a, i32 2048 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i8 undef, ptr %a4, align 1 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = getelementptr inbounds i8, ptr %a, i32 -2048 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i8 undef, ptr %a5, align 1 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a6 = getelementptr inbounds i8, ptr %a, i32 -2049 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i8 undef, ptr %a6, align 1 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ai = getelementptr inbounds i8, ptr %a, i32 %i +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i8 undef, ptr %ai, align 1 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; %a1 = getelementptr inbounds i8, ptr %a, i32 1 + store volatile i8 undef, ptr %a1 %a2 = getelementptr inbounds i8, ptr %a, i32 -1 + store volatile i8 undef, ptr %a2 %a3 = getelementptr inbounds i8, ptr %a, i32 2047 + store volatile i8 undef, ptr %a3 %a4 = getelementptr inbounds i8, ptr %a, i32 2048 + store volatile i8 undef, ptr %a4 %a5 = getelementptr inbounds i8, ptr %a, i32 -2048 + store volatile i8 undef, ptr %a5 %a6 = getelementptr inbounds i8, ptr %a, i32 -2049 + store volatile i8 undef, ptr %a6 %ai = getelementptr inbounds i8, ptr %a, i32 %i + store volatile i8 undef, ptr %ai ret void } define void @testi16(ptr %a, i32 %i) { ; RVI-LABEL: 'testi16' ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = getelementptr inbounds i16, ptr %a, i32 1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i16 undef, ptr %a1, align 2 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = getelementptr inbounds i16, ptr %a, i32 -1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i16 undef, ptr %a2, align 2 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = getelementptr inbounds i16, ptr %a, i32 1023 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i16 undef, ptr %a3, align 2 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a4 = getelementptr inbounds i16, ptr %a, i32 1024 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i16 undef, ptr %a4, align 2 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = getelementptr inbounds i16, ptr %a, i32 -1024 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i16 undef, ptr %a5, align 2 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a6 = getelementptr inbounds i16, ptr %a, i32 -1025 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i16 undef, ptr %a6, align 2 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ai = getelementptr inbounds i16, ptr %a, i32 %i +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i16 undef, ptr %ai, align 2 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; %a1 = getelementptr inbounds i16, ptr %a, i32 1 + store volatile i16 undef, ptr %a1 %a2 = getelementptr inbounds i16, ptr %a, i32 -1 + store volatile i16 undef, ptr %a2 %a3 = getelementptr inbounds i16, ptr %a, i32 1023 + store volatile i16 undef, ptr %a3 %a4 = getelementptr inbounds i16, ptr %a, i32 1024 + store volatile i16 undef, ptr %a4 %a5 = getelementptr inbounds i16, ptr %a, i32 -1024 + store volatile i16 undef, ptr %a5 %a6 = getelementptr inbounds i16, ptr %a, i32 -1025 + store volatile i16 undef, ptr %a6 %ai = getelementptr inbounds i16, ptr %a, i32 %i + store volatile i16 undef, ptr %ai ret void } define void @testi32(ptr %a, i32 %i) { ; RVI-LABEL: 'testi32' ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = getelementptr inbounds i32, ptr %a, i32 1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i32 undef, ptr %a1, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = getelementptr inbounds i32, ptr %a, i32 -1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i32 undef, ptr %a2, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = getelementptr inbounds i32, ptr %a, i32 511 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i32 undef, ptr %a3, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a4 = getelementptr inbounds i32, ptr %a, i32 512 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i32 undef, ptr %a4, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = getelementptr inbounds i32, ptr %a, i32 -512 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i32 undef, ptr %a5, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a6 = getelementptr inbounds i32, ptr %a, i32 -513 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i32 undef, ptr %a6, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ai = getelementptr inbounds i32, ptr %a, i32 %i +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile i32 undef, ptr %ai, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; %a1 = getelementptr inbounds i32, ptr %a, i32 1 + store volatile i32 undef, ptr %a1 %a2 = getelementptr inbounds i32, ptr %a, i32 -1 + store volatile i32 undef, ptr %a2 %a3 = getelementptr inbounds i32, ptr %a, i32 511 + store volatile i32 undef, ptr %a3 %a4 = getelementptr inbounds i32, ptr %a, i32 512 + store volatile i32 undef, ptr %a4 %a5 = getelementptr inbounds i32, ptr %a, i32 -512 + store volatile i32 undef, ptr %a5 %a6 = getelementptr inbounds i32, ptr %a, i32 -513 + store volatile i32 undef, ptr %a6 %ai = getelementptr inbounds i32, ptr %a, i32 %i + store volatile i32 undef, ptr %ai ret void } define void @testi64(ptr %a, i32 %i) { -; RVI-LABEL: 'testi64' -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = getelementptr inbounds i64, ptr %a, i32 1 -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = getelementptr inbounds i64, ptr %a, i32 -1 -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = getelementptr inbounds i64, ptr %a, i32 255 -; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a4 = getelementptr inbounds i64, ptr %a, i32 256 -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = getelementptr inbounds i64, ptr %a, i32 -256 -; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a6 = getelementptr inbounds i64, ptr %a, i32 -257 -; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ai = getelementptr inbounds i64, ptr %a, i32 %i -; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void -; %a1 = getelementptr inbounds i64, ptr %a, i32 1 + store volatile i64 undef, ptr %a1 %a2 = getelementptr inbounds i64, ptr %a, i32 -1 + store volatile i64 undef, ptr %a2 %a3 = getelementptr inbounds i64, ptr %a, i32 255 + store volatile i64 undef, ptr %a3 %a4 = getelementptr inbounds i64, ptr %a, i32 256 + store volatile i64 undef, ptr %a4 %a5 = getelementptr inbounds i64, ptr %a, i32 -256 + store volatile i64 undef, ptr %a5 %a6 = getelementptr inbounds i64, ptr %a, i32 -257 + store volatile i64 undef, ptr %a6 %ai = getelementptr inbounds i64, ptr %a, i32 %i + store volatile i64 undef, ptr %ai ret void } define void @testfloat(ptr %a, i32 %i) { ; RVI-LABEL: 'testfloat' ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = getelementptr inbounds float, ptr %a, i32 1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile float undef, ptr %a1, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = getelementptr inbounds float, ptr %a, i32 -1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile float undef, ptr %a2, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = getelementptr inbounds float, ptr %a, i32 511 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile float undef, ptr %a3, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a4 = getelementptr inbounds float, ptr %a, i32 512 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile float undef, ptr %a4, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = getelementptr inbounds float, ptr %a, i32 -512 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile float undef, ptr %a5, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a6 = getelementptr inbounds float, ptr %a, i32 -513 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile float undef, ptr %a6, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ai = getelementptr inbounds float, ptr %a, i32 %i +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile float undef, ptr %ai, align 4 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; %a1 = getelementptr inbounds float, ptr %a, i32 1 + store volatile float undef, ptr %a1 %a2 = getelementptr inbounds float, ptr %a, i32 -1 + store volatile float undef, ptr %a2 %a3 = getelementptr inbounds float, ptr %a, i32 511 + store volatile float undef, ptr %a3 %a4 = getelementptr inbounds float, ptr %a, i32 512 + store volatile float undef, ptr %a4 %a5 = getelementptr inbounds float, ptr %a, i32 -512 + store volatile float undef, ptr %a5 %a6 = getelementptr inbounds float, ptr %a, i32 -513 + store volatile float undef, ptr %a6 %ai = getelementptr inbounds float, ptr %a, i32 %i + store volatile float undef, ptr %ai ret void } define void @testdouble(ptr %a, i32 %i) { ; RVI-LABEL: 'testdouble' ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a1 = getelementptr inbounds double, ptr %a, i32 1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile double undef, ptr %a1, align 8 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a2 = getelementptr inbounds double, ptr %a, i32 -1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile double undef, ptr %a2, align 8 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a3 = getelementptr inbounds double, ptr %a, i32 255 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile double undef, ptr %a3, align 8 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a4 = getelementptr inbounds double, ptr %a, i32 256 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile double undef, ptr %a4, align 8 ; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = getelementptr inbounds double, ptr %a, i32 -256 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile double undef, ptr %a5, align 8 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %a6 = getelementptr inbounds double, ptr %a, i32 -257 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile double undef, ptr %a6, align 8 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ai = getelementptr inbounds double, ptr %a, i32 %i +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile double undef, ptr %ai, align 8 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; %a1 = getelementptr inbounds double, ptr %a, i32 1 + store volatile double undef, ptr %a1 %a2 = getelementptr inbounds double, ptr %a, i32 -1 + store volatile double undef, ptr %a2 %a3 = getelementptr inbounds double, ptr %a, i32 255 + store volatile double undef, ptr %a3 %a4 = getelementptr inbounds double, ptr %a, i32 256 + store volatile double undef, ptr %a4 %a5 = getelementptr inbounds double, ptr %a, i32 -256 + store volatile double undef, ptr %a5 %a6 = getelementptr inbounds double, ptr %a, i32 -257 + store volatile double undef, ptr %a6 %ai = getelementptr inbounds double, ptr %a, i32 %i + store volatile double undef, ptr %ai ret void } define void @testvecs(i32 %i) { ; RVI-LABEL: 'testvecs' -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %b0 = getelementptr inbounds <4 x i8>, ptr undef, i32 1 -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %b1 = getelementptr inbounds <4 x i16>, ptr undef, i32 1 -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %b2 = getelementptr inbounds <4 x i32>, ptr undef, i32 1 -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %b3 = getelementptr inbounds <4 x i64>, ptr undef, i32 1 -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %b4 = getelementptr inbounds <4 x float>, ptr undef, i32 1 -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %b5 = getelementptr inbounds <4 x double>, ptr undef, i32 1 -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %c1 = getelementptr inbounds <4 x i8>, ptr undef, i32 128 -; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %c2 = getelementptr inbounds <4 x i16>, ptr undef, i32 128 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %b0 = getelementptr inbounds <4 x i8>, ptr undef, i32 1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile <4 x i8> undef, ptr %b0, align 4 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %b1 = getelementptr inbounds <4 x i16>, ptr undef, i32 1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile <4 x i16> undef, ptr %b1, align 8 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %b2 = getelementptr inbounds <4 x i32>, ptr undef, i32 1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile <4 x i32> undef, ptr %b2, align 16 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %b3 = getelementptr inbounds <4 x i64>, ptr undef, i32 1 +; RVI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: store volatile <4 x i64> undef, ptr %b3, align 32 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %b4 = getelementptr inbounds <4 x float>, ptr undef, i32 1 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile <4 x float> undef, ptr %b4, align 16 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %b5 = getelementptr inbounds <4 x double>, ptr undef, i32 1 +; RVI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: store volatile <4 x double> undef, ptr %b5, align 32 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %c1 = getelementptr inbounds <4 x i8>, ptr undef, i32 128 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile <4 x i8> undef, ptr %c1, align 4 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %c2 = getelementptr inbounds <4 x i16>, ptr undef, i32 128 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile <4 x i16> undef, ptr %c2, align 8 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %c3 = getelementptr inbounds <4 x i32>, ptr undef, i32 128 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile <4 x i32> undef, ptr %c3, align 16 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %c4 = getelementptr inbounds <4 x i64>, ptr undef, i32 128 +; RVI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: store volatile <4 x i64> undef, ptr %c4, align 32 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %c5 = getelementptr inbounds <4 x float>, ptr undef, i32 128 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile <4 x float> undef, ptr %c5, align 16 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %c6 = getelementptr inbounds <4 x double>, ptr undef, i32 128 +; RVI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: store volatile <4 x double> undef, ptr %c6, align 32 ; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void ; %b0 = getelementptr inbounds <4 x i8>, ptr undef, i32 1 + store volatile <4 x i8> undef, ptr %b0 %b1 = getelementptr inbounds <4 x i16>, ptr undef, i32 1 + store volatile <4 x i16> undef, ptr %b1 %b2 = getelementptr inbounds <4 x i32>, ptr undef, i32 1 + store volatile <4 x i32> undef, ptr %b2 %b3 = getelementptr inbounds <4 x i64>, ptr undef, i32 1 + store volatile <4 x i64> undef, ptr %b3 %b4 = getelementptr inbounds <4 x float>, ptr undef, i32 1 + store volatile <4 x float> undef, ptr %b4 %b5 = getelementptr inbounds <4 x double>, ptr undef, i32 1 + store volatile <4 x double> undef, ptr %b5 %c1 = getelementptr inbounds <4 x i8>, ptr undef, i32 128 + store volatile <4 x i8> undef, ptr %c1 %c2 = getelementptr inbounds <4 x i16>, ptr undef, i32 128 + store volatile <4 x i16> undef, ptr %c2 %c3 = getelementptr inbounds <4 x i32>, ptr undef, i32 128 + store volatile <4 x i32> undef, ptr %c3 %c4 = getelementptr inbounds <4 x i64>, ptr undef, i32 128 + store volatile <4 x i64> undef, ptr %c4 %c5 = getelementptr inbounds <4 x float>, ptr undef, i32 128 + store volatile <4 x float> undef, ptr %c5 %c6 = getelementptr inbounds <4 x double>, ptr undef, i32 128 + store volatile <4 x double> undef, ptr %c6 + + ret void +} + +; Ensure that memory operations of a different type than the pointer source type +; use the correct type to determine if folding is possible. These operations +; are on vector types so there should be a cost for the GEP as the offset cannot +; be folded into the instruction. +define void @non_foldable_vector_uses(ptr %base, <2 x ptr> %base.vec) { +; RVI-LABEL: 'non_foldable_vector_uses' +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %1 = getelementptr i8, ptr %base, i32 42 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %x1 = load volatile <2 x i8>, ptr %1, align 2 +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %2 = getelementptr i8, ptr %base, i32 42 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %x2 = call <2 x i8> @llvm.masked.load.v2i8.p0(ptr %2, i32 1, <2 x i1> undef, <2 x i8> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = getelementptr i8, <2 x ptr> %base.vec, <2 x i32> +; RVI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %x3 = call <2 x i8> @llvm.masked.gather.v2i8.v2p0(<2 x ptr> %3, i32 1, <2 x i1> undef, <2 x i8> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %4 = getelementptr i8, ptr %base, i32 42 +; RVI-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %x4 = call <2 x i8> @llvm.masked.expandload.v2i8(ptr %4, <2 x i1> undef, <2 x i8> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %5 = getelementptr i8, ptr %base, i32 42 +; RVI-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %x5 = call <2 x i8> @llvm.vp.load.v2i8.p0(ptr %5, <2 x i1> undef, i32 undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %6 = getelementptr i8, ptr %base, i32 42 +; RVI-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %x6 = call <2 x i8> @llvm.experimental.vp.strided.load.v2i8.p0.i64(ptr %6, i64 undef, <2 x i1> undef, i32 undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %7 = getelementptr i8, ptr %base, i32 42 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile <2 x i8> undef, ptr %7, align 2 +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %8 = getelementptr i8, ptr %base, i32 42 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: call void @llvm.masked.store.v2i8.p0(<2 x i8> undef, ptr %8, i32 1, <2 x i1> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = getelementptr i8, <2 x ptr> %base.vec, <2 x i32> +; RVI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: call void @llvm.masked.scatter.v2i8.v2p0(<2 x i8> undef, <2 x ptr> %9, i32 1, <2 x i1> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %10 = getelementptr i8, ptr %base, i32 42 +; RVI-NEXT: Cost Model: Found an estimated cost of 12 for instruction: call void @llvm.masked.compressstore.v2i8(<2 x i8> undef, ptr %10, <2 x i1> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %11 = getelementptr i8, ptr %base, i32 42 +; RVI-NEXT: Cost Model: Found an estimated cost of 12 for instruction: call void @llvm.vp.store.v2i8.p0(<2 x i8> undef, ptr %11, <2 x i1> undef, i32 undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %12 = getelementptr i8, ptr %base, i32 42 +; RVI-NEXT: Cost Model: Found an estimated cost of 12 for instruction: call void @llvm.experimental.vp.strided.store.v2i8.p0.i64(<2 x i8> undef, ptr %12, i64 undef, <2 x i1> undef, i32 undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void +; + %1 = getelementptr i8, ptr %base, i32 42 + %x1 = load volatile <2 x i8>, ptr %1 + + %2 = getelementptr i8, ptr %base, i32 42 + %x2 = call <2 x i8> @llvm.masked.load.v2i8.p0(ptr %2, i32 1, <2 x i1> undef, <2 x i8> undef) + + %3 = getelementptr i8, <2 x ptr> %base.vec, <2 x i32> + %x3 = call <2 x i8> @llvm.masked.gather.v2i8.v2p0(<2 x ptr> %3, i32 1, <2 x i1> undef, <2 x i8> undef) + + %4 = getelementptr i8, ptr %base, i32 42 + %x4 = call <2 x i8> @llvm.masked.expandload.v2i8(ptr %4, <2 x i1> undef, <2 x i8> undef) + + %5 = getelementptr i8, ptr %base, i32 42 + %x5 = call <2 x i8> @llvm.vp.load.v2i8.p0(ptr %5, <2 x i1> undef, i32 undef) + + %6 = getelementptr i8, ptr %base, i32 42 + %x6 = call <2 x i8> @llvm.experimental.vp.strided.load.v2i8.i64(ptr %6, i64 undef, <2 x i1> undef, i32 undef) + + %7 = getelementptr i8, ptr %base, i32 42 + store volatile <2 x i8> undef, ptr %7 + + %8 = getelementptr i8, ptr %base, i32 42 + call void @llvm.masked.store.v2i8.p0(<2 x i8> undef, ptr %8, i32 1, <2 x i1> undef) + + %9 = getelementptr i8, <2 x ptr> %base.vec, <2 x i32> + call void @llvm.masked.scatter.v2i8.v2p0(<2 x i8> undef, <2 x ptr> %9, i32 1, <2 x i1> undef) + + %10 = getelementptr i8, ptr %base, i32 42 + call void @llvm.masked.compressstore.v2i8(<2 x i8> undef, ptr %10, <2 x i1> undef) + + %11 = getelementptr i8, ptr %base, i32 42 + call void @llvm.vp.store.v2i8.p0(<2 x i8> undef, ptr %11, <2 x i1> undef, i32 undef) + + %12 = getelementptr i8, ptr %base, i32 42 + call void @llvm.experimental.vp.strided.store.v2i8.i64(<2 x i8> undef, ptr %12, i64 undef, <2 x i1> undef, i32 undef) ret void } + +; Despite the fact that these are vector loads and stores which doesn't allow an +; offset in the addressing mode, because the offsets are zero we don't actually +; need to do any calculation for the GEP and thus it should be free. +define void @foldable_vector_uses(ptr %base, <2 x ptr> %base.vec) { +; RVI-LABEL: 'foldable_vector_uses' +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %1 = getelementptr i8, ptr %base, i32 0 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %x1 = load volatile <2 x i8>, ptr %1, align 2 +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %2 = getelementptr i8, ptr %base, i32 0 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %x2 = call <2 x i8> @llvm.masked.load.v2i8.p0(ptr %2, i32 1, <2 x i1> undef, <2 x i8> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %3 = getelementptr i8, <2 x ptr> %base.vec, <2 x i32> zeroinitializer +; RVI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %x3 = call <2 x i8> @llvm.masked.gather.v2i8.v2p0(<2 x ptr> %3, i32 1, <2 x i1> undef, <2 x i8> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %4 = getelementptr i8, ptr %base, i32 0 +; RVI-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %x4 = call <2 x i8> @llvm.masked.expandload.v2i8(ptr %4, <2 x i1> undef, <2 x i8> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %5 = getelementptr i8, ptr %base, i32 0 +; RVI-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %x5 = call <2 x i8> @llvm.vp.load.v2i8.p0(ptr %5, <2 x i1> undef, i32 undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %6 = getelementptr i8, ptr %base, i32 0 +; RVI-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %x6 = call <2 x i8> @llvm.experimental.vp.strided.load.v2i8.p0.i64(ptr %6, i64 undef, <2 x i1> undef, i32 undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %7 = getelementptr i8, ptr %base, i32 0 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: store volatile <2 x i8> undef, ptr %7, align 2 +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %8 = getelementptr i8, ptr %base, i32 0 +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: call void @llvm.masked.store.v2i8.p0(<2 x i8> undef, ptr %8, i32 1, <2 x i1> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %9 = getelementptr i8, <2 x ptr> %base.vec, <2 x i32> zeroinitializer +; RVI-NEXT: Cost Model: Found an estimated cost of 2 for instruction: call void @llvm.masked.scatter.v2i8.v2p0(<2 x i8> undef, <2 x ptr> %9, i32 1, <2 x i1> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %10 = getelementptr i8, ptr %base, i32 0 +; RVI-NEXT: Cost Model: Found an estimated cost of 12 for instruction: call void @llvm.masked.compressstore.v2i8(<2 x i8> undef, ptr %10, <2 x i1> undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %11 = getelementptr i8, ptr %base, i32 0 +; RVI-NEXT: Cost Model: Found an estimated cost of 12 for instruction: call void @llvm.vp.store.v2i8.p0(<2 x i8> undef, ptr %11, <2 x i1> undef, i32 undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %12 = getelementptr i8, ptr %base, i32 0 +; RVI-NEXT: Cost Model: Found an estimated cost of 12 for instruction: call void @llvm.experimental.vp.strided.store.v2i8.p0.i64(<2 x i8> undef, ptr %12, i64 undef, <2 x i1> undef, i32 undef) +; RVI-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void +; + %1 = getelementptr i8, ptr %base, i32 0 + %x1 = load volatile <2 x i8>, ptr %1 + + %2 = getelementptr i8, ptr %base, i32 0 + %x2 = call <2 x i8> @llvm.masked.load.v2i8.p0(ptr %2, i32 1, <2 x i1> undef, <2 x i8> undef) + + %3 = getelementptr i8, <2 x ptr> %base.vec, <2 x i32> + %x3 = call <2 x i8> @llvm.masked.gather.v2i8.v2p0(<2 x ptr> %3, i32 1, <2 x i1> undef, <2 x i8> undef) + + %4 = getelementptr i8, ptr %base, i32 0 + %x4 = call <2 x i8> @llvm.masked.expandload.v2i8(ptr %4, <2 x i1> undef, <2 x i8> undef) + + %5 = getelementptr i8, ptr %base, i32 0 + %x5 = call <2 x i8> @llvm.vp.load.v2i8.p0(ptr %5, <2 x i1> undef, i32 undef) + + %6 = getelementptr i8, ptr %base, i32 0 + %x6 = call <2 x i8> @llvm.experimental.vp.strided.load.v2i8.i64(ptr %6, i64 undef, <2 x i1> undef, i32 undef) + + %7 = getelementptr i8, ptr %base, i32 0 + store volatile <2 x i8> undef, ptr %7 + + %8 = getelementptr i8, ptr %base, i32 0 + call void @llvm.masked.store.v2i8.p0(<2 x i8> undef, ptr %8, i32 1, <2 x i1> undef) + + %9 = getelementptr i8, <2 x ptr> %base.vec, <2 x i32> + call void @llvm.masked.scatter.v2i8.v2p0(<2 x i8> undef, <2 x ptr> %9, i32 1, <2 x i1> undef) + + %10 = getelementptr i8, ptr %base, i32 0 + call void @llvm.masked.compressstore.v2i8(<2 x i8> undef, ptr %10, <2 x i1> undef) + + %11 = getelementptr i8, ptr %base, i32 0 + call void @llvm.vp.store.v2i8.p0(<2 x i8> undef, ptr %11, <2 x i1> undef, i32 undef) + + %12 = getelementptr i8, ptr %base, i32 0 + call void @llvm.experimental.vp.strided.store.v2i8.i64(<2 x i8> undef, ptr %12, i64 undef, <2 x i1> undef, i32 undef) + + ret void +} + +declare <2 x i8> @llvm.masked.load.v2i8.p0(ptr, i32, <2 x i1>, <2 x i8>) +declare <2 x i8> @llvm.masked.gather.v2i8.v2p0(<2 x ptr>, i32, <2 x i1>, <2 x i8>) +declare <2 x i8> @llvm.masked.expandload.v2i8(ptr, <2 x i1>, <2 x i8>) +declare <2 x i8> @llvm.vp.load.v2i8.p0(ptr, <2 x i1>, i32) +declare <2 x i8> @llvm.experimental.vp.strided.load.v2i8.i64(ptr, i64, <2 x i1>, i32) + +declare void @llvm.masked.store.v2i8.p0(<2 x i8>, ptr, i32, <2 x i1>) +declare void @llvm.masked.scatter.v2i8.v2p0(<2 x i8>, <2 x ptr>, i32, <2 x i1>) +declare void @llvm.masked.compressstore.v2i8(<2 x i8>, ptr, <2 x i1>) +declare void @llvm.vp.store.v2i8.p0(<2 x i8>, ptr, <2 x i1>, i32) +declare void @llvm.experimental.vp.strided.store.v2i8.i64(<2 x i8>, ptr, i64, <2 x i1>, i32) diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/gep.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/gep.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/gep.ll @@ -0,0 +1,82 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=slp-vectorizer -mtriple=riscv64 -mattr=+v \ +; RUN: -riscv-v-slp-max-vf=0 -S | FileCheck %s + +; FIXME: This should not be vectorized, as the cost of computing the +; offsets nullifies the benefits of vectorizing: +; +; copy_with_offset_v2i8: +; addi a0, a0, 8 +; vsetivli zero, 2, e8, mf8, ta, ma +; vle8.v v8, (a0) +; addi a1, a1, 16 +; vse8.v v8, (a1) +; ret +; +; Compared to the scalar version where the offsets can be folded into the +; addressing mode: +; +; copy_with_offset_v2i8: +; lbu a2, 8(a0) +; lbu a0, 9(a0) +; sb a2, 16(a1) +; sb a0, 17(a1) +; ret + +define void @copy_with_offset_v2i8(ptr noalias %p, ptr noalias %q) { +; CHECK-LABEL: @copy_with_offset_v2i8( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 8 +; CHECK-NEXT: [[Q1:%.*]] = getelementptr i8, ptr [[Q:%.*]], i32 16 +; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i8>, ptr [[P1]], align 1 +; CHECK-NEXT: store <2 x i8> [[TMP0]], ptr [[Q1]], align 1 +; CHECK-NEXT: ret void +; +entry: + %p1 = getelementptr i8, ptr %p, i32 8 + %x1 = load i8, ptr %p1 + %q1 = getelementptr i8, ptr %q, i32 16 + store i8 %x1, ptr %q1 + + %p2 = getelementptr i8, ptr %p, i32 9 + %x2 = load i8, ptr %p2 + %q2 = getelementptr i8, ptr %q, i32 17 + store i8 %x2, ptr %q2 + + ret void +} + +; This on the other hand, should be vectorized as the vector savings outweigh +; the GEP costs. +define void @copy_with_offset_v4i8(ptr noalias %p, ptr noalias %q) { +; CHECK-LABEL: @copy_with_offset_v4i8( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 8 +; CHECK-NEXT: [[Q1:%.*]] = getelementptr i8, ptr [[Q:%.*]], i32 16 +; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i8>, ptr [[P1]], align 1 +; CHECK-NEXT: store <4 x i8> [[TMP0]], ptr [[Q1]], align 1 +; CHECK-NEXT: ret void +; +entry: + %p1 = getelementptr i8, ptr %p, i32 8 + %x1 = load i8, ptr %p1 + %q1 = getelementptr i8, ptr %q, i32 16 + store i8 %x1, ptr %q1 + + %p2 = getelementptr i8, ptr %p, i32 9 + %x2 = load i8, ptr %p2 + %q2 = getelementptr i8, ptr %q, i32 17 + store i8 %x2, ptr %q2 + + %p3 = getelementptr i8, ptr %p, i32 10 + %x3 = load i8, ptr %p3 + %q3 = getelementptr i8, ptr %q, i32 18 + store i8 %x3, ptr %q3 + + %p4 = getelementptr i8, ptr %p, i32 11 + %x4 = load i8, ptr %p4 + %q4 = getelementptr i8, ptr %q, i32 19 + store i8 %x4, ptr %q4 + + ret void +}