diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h index 471a7f70dd546..9dea4c1b412db 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -1218,8 +1218,14 @@ class LegalizationArtifactCombiner { } else { LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg()); - if (!ConvertOp && DestTy != MergeSrcTy) - ConvertOp = TargetOpcode::G_BITCAST; + if (!ConvertOp && DestTy != MergeSrcTy) { + if (DestTy.isPointer()) + ConvertOp = TargetOpcode::G_INTTOPTR; + else if (MergeSrcTy.isPointer()) + ConvertOp = TargetOpcode::G_PTRTOINT; + else + ConvertOp = TargetOpcode::G_BITCAST; + } if (ConvertOp) { Builder.setInstr(MI); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-unmerge-values.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-unmerge-values.mir index 5bee62da34634..4f0ca34408012 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-unmerge-values.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-unmerge-values.mir @@ -1,13 +1,21 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -mtriple=aarch64 -O0 -run-pass=legalizer %s -o - | FileCheck %s +# RUN: llc -mtriple=aarch64 -O0 -run-pass=legalizer %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O0 +# RUN: llc -mtriple=aarch64 -run-pass=legalizer %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O2 --- name: test_unmerge_s4_constant body: | bb.0: - ; CHECK-LABEL: name: test_unmerge_s4_constant - ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 - ; CHECK: $x0 = COPY [[C]](s64) + ; CHECK-O0-LABEL: name: test_unmerge_s4_constant + ; CHECK-O0: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK-O0-NEXT: $x0 = COPY [[C]](s64) + ; + ; CHECK-O2-LABEL: name: test_unmerge_s4_constant + ; CHECK-O2: [[C:%[0-9]+]]:_(s8) = G_CONSTANT i8 0 + ; CHECK-O2-NEXT: [[TRUNC:%[0-9]+]]:_(s4) = G_TRUNC [[C]](s8) + ; CHECK-O2-NEXT: [[COPY:%[0-9]+]]:_(s4) = COPY [[TRUNC]](s4) + ; CHECK-O2-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK-O2-NEXT: $x0 = COPY [[C1]](s64) %0:_(s8) = G_CONSTANT i8 0 %1:_(s4), %2:_(s4)= G_UNMERGE_VALUES %0 %3:_(s64) = G_ANYEXT %1 @@ -21,15 +29,17 @@ body: | bb.0: liveins: $w0 ; CHECK-LABEL: name: test_unmerge_s4 - ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 - ; CHECK: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8), [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[COPY]](s32) - ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UV]](s8) - ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4 - ; CHECK: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ZEXT]], [[C]](s64) - ; CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[UV]](s8) - ; CHECK: [[ANYEXT1:%[0-9]+]]:_(s64) = G_ANYEXT [[LSHR]](s32) - ; CHECK: $x0 = COPY [[ANYEXT]](s64) - ; CHECK: $x1 = COPY [[ANYEXT1]](s64) + ; CHECK: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8), [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[COPY]](s32) + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UV]](s8) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ZEXT]], [[C]](s64) + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[UV]](s8) + ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s64) = G_ANYEXT [[LSHR]](s32) + ; CHECK-NEXT: $x0 = COPY [[ANYEXT]](s64) + ; CHECK-NEXT: $x1 = COPY [[ANYEXT1]](s64) %0:_(s32) = COPY $w0 %1:_(s8) = G_TRUNC %0 %2:_(s4), %3:_(s4)= G_UNMERGE_VALUES %1 @@ -39,3 +49,70 @@ body: | $x1 = COPY %5 ... + +--- +name: test_unmerge_unmerge_s64 +body: | + bb.0: + liveins: $x0,$d0,$d1,$d2 + ; CHECK-LABEL: name: test_unmerge_unmerge_s64 + ; CHECK: liveins: $x0, $d0, $d1, $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: $x0 = COPY [[COPY]](s64) + ; CHECK-NEXT: $x1 = COPY [[COPY]](s64) + ; CHECK-NEXT: $x2 = COPY [[COPY]](s64) + %0:_(s64) = COPY $x0 + %1:_(<3 x s64>) = G_BUILD_VECTOR %0:_(s64), %0:_(s64), %0:_(s64) + %2:_(s64), %3:_(s64), %4:_(s64) = G_UNMERGE_VALUES %1:_(<3 x s64>) + $x0 = COPY %2:_(s64) + $x1 = COPY %3:_(s64) + $x2 = COPY %3:_(s64) + +... + +--- +name: test_unmerge_unmerge_to_p0 +body: | + bb.0: + liveins: $x0,$d0,$d1,$d2 + ; CHECK-LABEL: name: test_unmerge_unmerge_to_p0 + ; CHECK: liveins: $x0, $d0, $d1, $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY]](s64) + ; CHECK-NEXT: [[INTTOPTR1:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY]](s64) + ; CHECK-NEXT: $x0 = COPY [[INTTOPTR]](p0) + ; CHECK-NEXT: $x1 = COPY [[INTTOPTR1]](p0) + ; CHECK-NEXT: $x2 = COPY [[INTTOPTR1]](p0) + %0:_(s64) = COPY $x0 + %1:_(<3 x s64>) = G_BUILD_VECTOR %0:_(s64), %0:_(s64), %0:_(s64) + %2:_(p0), %3:_(p0), %4:_(p0) = G_UNMERGE_VALUES %1:_(<3 x s64>) + $x0 = COPY %2:_(p0) + $x1 = COPY %3:_(p0) + $x2 = COPY %3:_(p0) + +... + +--- +name: test_unmerge_unmerge_from_p0 +body: | + bb.0: + liveins: $x0,$d0,$d1,$d2 + ; CHECK-LABEL: name: test_unmerge_unmerge_from_p0 + ; CHECK: liveins: $x0, $d0, $d1, $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 + ; CHECK-NEXT: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[COPY]](p0) + ; CHECK-NEXT: [[PTRTOINT1:%[0-9]+]]:_(s64) = G_PTRTOINT [[COPY]](p0) + ; CHECK-NEXT: $d0 = COPY [[PTRTOINT]](s64) + ; CHECK-NEXT: $d1 = COPY [[PTRTOINT1]](s64) + ; CHECK-NEXT: $d2 = COPY [[PTRTOINT1]](s64) + %0:_(p0) = COPY $x0 + %1:_(<3 x p0>) = G_BUILD_VECTOR %0:_(p0), %0:_(p0), %0:_(p0) + %2:_(s64), %3:_(s64), %4:_(s64) = G_UNMERGE_VALUES %1:_(<3 x p0>) + $d0 = COPY %2:_(s64) + $d1 = COPY %3:_(s64) + $d2 = COPY %3:_(s64) + +... diff --git a/llvm/test/CodeGen/AArch64/ptradd.ll b/llvm/test/CodeGen/AArch64/ptradd.ll index a11e38642a526..427542377bfda 100644 --- a/llvm/test/CodeGen/AArch64/ptradd.ll +++ b/llvm/test/CodeGen/AArch64/ptradd.ll @@ -1,12 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=aarch64 -verify-machineinstrs -global-isel=0 | FileCheck %s --check-prefixes=CHECK,CHECK-SD -; RUN: llc < %s -mtriple=aarch64 -verify-machineinstrs -global-isel=1 -global-isel-abort=2 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI - -; CHECK-GI: warning: Instruction selection used fallback path for vector_gep_v3i32 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for vector_gep_v3i64 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for vector_gep_v3i64_base -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for vector_gep_v3i64_c10 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for vector_gep_v3i64_cm10 +; RUN: llc < %s -mtriple=aarch64 -verify-machineinstrs -global-isel=1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI define ptr @scalar_gep_i32(ptr %b, i32 %off) { ; CHECK-LABEL: scalar_gep_i32: @@ -78,20 +72,38 @@ entry: } define <3 x ptr> @vector_gep_v3i32(<3 x ptr> %b, <3 x i32> %off) { -; CHECK-LABEL: vector_gep_v3i32: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-NEXT: ext v4.16b, v3.16b, v3.16b, #8 -; CHECK-NEXT: // kill: def $d2 killed $d2 def $q2 -; CHECK-NEXT: mov v0.d[1], v1.d[0] -; CHECK-NEXT: saddw v2.2d, v2.2d, v4.2s -; CHECK-NEXT: saddw v0.2d, v0.2d, v3.2s -; CHECK-NEXT: // kill: def $d2 killed $d2 killed $q2 -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 killed $q1 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: vector_gep_v3i32: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-SD-NEXT: ext v4.16b, v3.16b, v3.16b, #8 +; CHECK-SD-NEXT: // kill: def $d2 killed $d2 def $q2 +; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] +; CHECK-SD-NEXT: saddw v2.2d, v2.2d, v4.2s +; CHECK-SD-NEXT: saddw v0.2d, v0.2d, v3.2s +; CHECK-SD-NEXT: // kill: def $d2 killed $d2 killed $q2 +; CHECK-SD-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 killed $q1 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_gep_v3i32: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: smov x9, v3.s[0] +; CHECK-GI-NEXT: fmov x8, d0 +; CHECK-GI-NEXT: mov v0.d[0], x8 +; CHECK-GI-NEXT: smov x8, v3.s[1] +; CHECK-GI-NEXT: mov v4.d[0], x9 +; CHECK-GI-NEXT: fmov x9, d1 +; CHECK-GI-NEXT: mov v0.d[1], x9 +; CHECK-GI-NEXT: fmov x9, d2 +; CHECK-GI-NEXT: mov v4.d[1], x8 +; CHECK-GI-NEXT: mov w8, v3.s[2] +; CHECK-GI-NEXT: add v0.2d, v0.2d, v4.2d +; CHECK-GI-NEXT: add x8, x9, w8, sxtw +; CHECK-GI-NEXT: fmov d2, x8 +; CHECK-GI-NEXT: mov d1, v0.d[1] +; CHECK-GI-NEXT: ret entry: %g = getelementptr i8, <3 x ptr> %b, <3 x i32> %off ret <3 x ptr> %g @@ -143,12 +155,29 @@ entry: } define <3 x ptr> @vector_gep_v3i64(<3 x ptr> %b, <3 x i64> %off) { -; CHECK-LABEL: vector_gep_v3i64: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: add d0, d0, d3 -; CHECK-NEXT: add d1, d1, d4 -; CHECK-NEXT: add d2, d2, d5 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: vector_gep_v3i64: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: add d0, d0, d3 +; CHECK-SD-NEXT: add d1, d1, d4 +; CHECK-SD-NEXT: add d2, d2, d5 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_gep_v3i64: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: fmov x8, d0 +; CHECK-GI-NEXT: // kill: def $d3 killed $d3 def $q3 +; CHECK-GI-NEXT: // kill: def $d4 killed $d4 def $q4 +; CHECK-GI-NEXT: fmov x9, d5 +; CHECK-GI-NEXT: mov v3.d[1], v4.d[0] +; CHECK-GI-NEXT: mov v0.d[0], x8 +; CHECK-GI-NEXT: fmov x8, d1 +; CHECK-GI-NEXT: mov v0.d[1], x8 +; CHECK-GI-NEXT: fmov x8, d2 +; CHECK-GI-NEXT: add x8, x8, x9 +; CHECK-GI-NEXT: add v0.2d, v0.2d, v3.2d +; CHECK-GI-NEXT: fmov d2, x8 +; CHECK-GI-NEXT: mov d1, v0.d[1] +; CHECK-GI-NEXT: ret entry: %g = getelementptr i8, <3 x ptr> %b, <3 x i64> %off ret <3 x ptr> %g @@ -221,19 +250,32 @@ entry: } define <3 x ptr> @vector_gep_v3i64_base(ptr %b, <3 x i64> %off) { -; CHECK-LABEL: vector_gep_v3i64_base: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-NEXT: fmov d3, x0 -; CHECK-NEXT: mov v0.d[1], v1.d[0] -; CHECK-NEXT: dup v1.2d, x0 -; CHECK-NEXT: add d2, d3, d2 -; CHECK-NEXT: add v0.2d, v1.2d, v0.2d -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 killed $q1 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: vector_gep_v3i64_base: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-SD-NEXT: fmov d3, x0 +; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] +; CHECK-SD-NEXT: dup v1.2d, x0 +; CHECK-SD-NEXT: add d2, d3, d2 +; CHECK-SD-NEXT: add v0.2d, v1.2d, v0.2d +; CHECK-SD-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 killed $q1 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_gep_v3i64_base: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: fmov x8, d2 +; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] +; CHECK-GI-NEXT: dup v1.2d, x0 +; CHECK-GI-NEXT: add x8, x0, x8 +; CHECK-GI-NEXT: fmov d2, x8 +; CHECK-GI-NEXT: add v0.2d, v1.2d, v0.2d +; CHECK-GI-NEXT: mov d1, v0.d[1] +; CHECK-GI-NEXT: ret entry: %g = getelementptr i8, ptr %b, <3 x i64> %off ret <3 x ptr> %g @@ -292,18 +334,29 @@ entry: } define <3 x ptr> @vector_gep_v3i64_c10(ptr %b) { -; CHECK-LABEL: vector_gep_v3i64_c10: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #10 // =0xa -; CHECK-NEXT: dup v0.2d, x0 -; CHECK-NEXT: fmov d3, x0 -; CHECK-NEXT: dup v2.2d, x8 -; CHECK-NEXT: add v0.2d, v0.2d, v2.2d -; CHECK-NEXT: add d2, d3, d2 -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 killed $q1 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: vector_gep_v3i64_c10: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: mov w8, #10 // =0xa +; CHECK-SD-NEXT: dup v0.2d, x0 +; CHECK-SD-NEXT: fmov d3, x0 +; CHECK-SD-NEXT: dup v2.2d, x8 +; CHECK-SD-NEXT: add v0.2d, v0.2d, v2.2d +; CHECK-SD-NEXT: add d2, d3, d2 +; CHECK-SD-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 killed $q1 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_gep_v3i64_c10: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: adrp x8, .LCPI19_0 +; CHECK-GI-NEXT: dup v0.2d, x0 +; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI19_0] +; CHECK-GI-NEXT: add x8, x0, #10 +; CHECK-GI-NEXT: fmov d2, x8 +; CHECK-GI-NEXT: add v0.2d, v0.2d, v1.2d +; CHECK-GI-NEXT: mov d1, v0.d[1] +; CHECK-GI-NEXT: ret entry: %g = getelementptr i8, ptr %b, <3 x i64> ret <3 x ptr> %g @@ -373,18 +426,29 @@ entry: } define <3 x ptr> @vector_gep_v3i64_cm10(ptr %b) { -; CHECK-LABEL: vector_gep_v3i64_cm10: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov x8, #-10 // =0xfffffffffffffff6 -; CHECK-NEXT: dup v0.2d, x0 -; CHECK-NEXT: fmov d3, x0 -; CHECK-NEXT: dup v2.2d, x8 -; CHECK-NEXT: add v0.2d, v0.2d, v2.2d -; CHECK-NEXT: add d2, d3, d2 -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 killed $q1 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: vector_gep_v3i64_cm10: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: mov x8, #-10 // =0xfffffffffffffff6 +; CHECK-SD-NEXT: dup v0.2d, x0 +; CHECK-SD-NEXT: fmov d3, x0 +; CHECK-SD-NEXT: dup v2.2d, x8 +; CHECK-SD-NEXT: add v0.2d, v0.2d, v2.2d +; CHECK-SD-NEXT: add d2, d3, d2 +; CHECK-SD-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 killed $q1 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_gep_v3i64_cm10: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: adrp x8, .LCPI23_0 +; CHECK-GI-NEXT: dup v0.2d, x0 +; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI23_0] +; CHECK-GI-NEXT: sub x8, x0, #10 +; CHECK-GI-NEXT: fmov d2, x8 +; CHECK-GI-NEXT: add v0.2d, v0.2d, v1.2d +; CHECK-GI-NEXT: mov d1, v0.d[1] +; CHECK-GI-NEXT: ret entry: %g = getelementptr i8, ptr %b, <3 x i64> ret <3 x ptr> %g