diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1105,19 +1105,18 @@ case 'd': // Data register (equivalent to 'r') case 'h': // High-part register case 'r': // General-purpose register - if (CallOperandVal->getType()->isIntegerTy()) - weight = CW_Register; + weight = CallOperandVal->getType()->isIntegerTy() ? CW_Register : CW_Default; break; case 'f': // Floating-point register - if (type->isFloatingPointTy()) - weight = CW_Register; + if (!useSoftFloat()) + weight = type->isFloatingPointTy() ? CW_Register : CW_Default; break; case 'v': // Vector register - if ((type->isVectorTy() || type->isFloatingPointTy()) && - Subtarget.hasVector()) - weight = CW_Register; + if (Subtarget.hasVector()) + weight = (type->isVectorTy() || type->isFloatingPointTy()) ? CW_Register + : CW_Default; break; case 'I': // Unsigned 8-bit constant @@ -1179,9 +1178,9 @@ default: break; case 'd': // Data register (equivalent to 'r') case 'r': // General-purpose register - if (VT == MVT::i64) + if (VT.getSizeInBits() == 64) return std::make_pair(0U, &SystemZ::GR64BitRegClass); - else if (VT == MVT::i128) + else if (VT.getSizeInBits() == 128) return std::make_pair(0U, &SystemZ::GR128BitRegClass); return std::make_pair(0U, &SystemZ::GR32BitRegClass); @@ -1197,18 +1196,19 @@ case 'f': // Floating-point register if (!useSoftFloat()) { - if (VT == MVT::f64) + if (VT.getSizeInBits() == 64) return std::make_pair(0U, &SystemZ::FP64BitRegClass); - else if (VT == MVT::f128) + else if (VT.getSizeInBits() == 128) return std::make_pair(0U, &SystemZ::FP128BitRegClass); return std::make_pair(0U, &SystemZ::FP32BitRegClass); } break; + case 'v': // Vector register if (Subtarget.hasVector()) { - if (VT == MVT::f32) + if (VT.getSizeInBits() == 32) return std::make_pair(0U, &SystemZ::VR32BitRegClass); - if (VT == MVT::f64) + if (VT.getSizeInBits() == 64) return std::make_pair(0U, &SystemZ::VR64BitRegClass); return std::make_pair(0U, &SystemZ::VR128BitRegClass); } @@ -1216,15 +1216,22 @@ } } if (Constraint.size() > 0 && Constraint[0] == '{') { + + // A clobber constraint (e.g. ~{f0}) will have MVT::Other which is illegal + // to check the size on. + auto getVTSizeInBits = [&VT]() { + return VT == MVT::Other ? 0 : VT.getSizeInBits(); + }; + // We need to override the default register parsing for GPRs and FPRs // because the interpretation depends on VT. The internal names of // the registers are also different from the external names // (F0D and F0S instead of F0, etc.). if (Constraint[1] == 'r') { - if (VT == MVT::i32) + if (getVTSizeInBits() == 32) return parseRegisterNumber(Constraint, &SystemZ::GR32BitRegClass, SystemZMC::GR32Regs, 16); - if (VT == MVT::i128) + if (getVTSizeInBits() == 128) return parseRegisterNumber(Constraint, &SystemZ::GR128BitRegClass, SystemZMC::GR128Regs, 16); return parseRegisterNumber(Constraint, &SystemZ::GR64BitRegClass, @@ -1234,10 +1241,10 @@ if (useSoftFloat()) return std::make_pair( 0u, static_cast(nullptr)); - if (VT == MVT::f32) + if (getVTSizeInBits() == 32) return parseRegisterNumber(Constraint, &SystemZ::FP32BitRegClass, SystemZMC::FP32Regs, 16); - if (VT == MVT::f128) + if (getVTSizeInBits() == 128) return parseRegisterNumber(Constraint, &SystemZ::FP128BitRegClass, SystemZMC::FP128Regs, 16); return parseRegisterNumber(Constraint, &SystemZ::FP64BitRegClass, @@ -1247,10 +1254,10 @@ if (!Subtarget.hasVector()) return std::make_pair( 0u, static_cast(nullptr)); - if (VT == MVT::f32) + if (getVTSizeInBits() == 32) return parseRegisterNumber(Constraint, &SystemZ::VR32BitRegClass, SystemZMC::VR32Regs, 32); - if (VT == MVT::f64) + if (getVTSizeInBits() == 64) return parseRegisterNumber(Constraint, &SystemZ::VR64BitRegClass, SystemZMC::VR64Regs, 32); return parseRegisterNumber(Constraint, &SystemZ::VR128BitRegClass, @@ -1453,28 +1460,24 @@ SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, std::optional CC) const { EVT ValueVT = Val.getValueType(); - assert((ValueVT != MVT::i128 || - ((NumParts == 1 && PartVT == MVT::Untyped) || - (NumParts == 2 && PartVT == MVT::i64))) && - "Unknown handling of i128 value."); - if (ValueVT == MVT::i128 && NumParts == 1) { + if (ValueVT.getSizeInBits() == 128 && NumParts == 1 && PartVT == MVT::Untyped) { // Inline assembly operand. - Parts[0] = lowerI128ToGR128(DAG, Val); + Parts[0] = lowerI128ToGR128(DAG, DAG.getBitcast(MVT::i128, Val)); return true; } + return false; } SDValue SystemZTargetLowering::joinRegisterPartsIntoValue( SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts, MVT PartVT, EVT ValueVT, std::optional CC) const { - assert((ValueVT != MVT::i128 || - ((NumParts == 1 && PartVT == MVT::Untyped) || - (NumParts == 2 && PartVT == MVT::i64))) && - "Unknown handling of i128 value."); - if (ValueVT == MVT::i128 && NumParts == 1) + if (ValueVT.getSizeInBits() == 128 && NumParts == 1 && PartVT == MVT::Untyped) { // Inline assembly operand. - return lowerGR128ToI128(DAG, Parts[0]); + SDValue Res = lowerGR128ToI128(DAG, Parts[0]); + return DAG.getBitcast(ValueVT, Res); + } + return SDValue(); } diff --git a/llvm/test/CodeGen/SystemZ/inline-asm-f-constraint-softfloat.ll b/llvm/test/CodeGen/SystemZ/inline-asm-f-constraint-softfloat.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/inline-asm-f-constraint-softfloat.ll @@ -0,0 +1,9 @@ +; RUN: not llc -mtriple=s390x-linux-gnu -mcpu=z15 -mattr=soft-float < %s 2>&1 | FileCheck %s + +; CHECK: error: couldn't allocate output register for constraint 'f' + +define signext i32 @int_and_f(i32 signext %cc_dep1) { +entry: + %0 = tail call i32 asm sideeffect "", "=f,0"(i32 %cc_dep1) + ret i32 %0 +} diff --git a/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting-explicit-regs-zEC12.ll b/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting-explicit-regs-zEC12.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting-explicit-regs-zEC12.ll @@ -0,0 +1,206 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mtriple=s390x-linux-gnu -mcpu=zEC12 < %s | FileCheck %s +; +; Test inline assembly where the operand is bitcasted. + +define signext i32 @int_and_f(i32 signext %cc_dep1) { +; CHECK-LABEL: int_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: risbhg %r0, %r2, 0, 159, 32 +; CHECK-NEXT: ldgr %f1, %r0 +; CHECK-NEXT: # kill: def $f1s killed $f1s killed $f1d +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: # kill: def $f1s killed $f1s def $f1d +; CHECK-NEXT: lgdr %r0, %f1 +; CHECK-NEXT: risblg %r0, %r0, 0, 159, 32 +; CHECK-NEXT: lgfr %r2, %r0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i32 asm sideeffect "", "={f1},0"(i32 %cc_dep1) + ret i32 %0 +} + +define i64 @long_and_f(i64 %cc_dep1) { +; CHECK-LABEL: long_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ldgr %f2, %r2 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r2, %f2 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i64 asm sideeffect "", "={f2},0"(i64 %cc_dep1) + ret i64 %0 +} + +define void @__int128_and_f(ptr noalias nocapture writeonly sret(i128) align 8 %agg.result, ptr %0) { +; CHECK-LABEL: __int128_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ld %f1, 0(%r3) +; CHECK-NEXT: ld %f3, 8(%r3) +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: std %f1, 0(%r2) +; CHECK-NEXT: std %f3, 8(%r2) +; CHECK-NEXT: br %r14 +entry: + %cc_dep1 = load i128, ptr %0, align 8 + %1 = tail call i128 asm sideeffect "", "={f1},0"(i128 %cc_dep1) + store i128 %1, ptr %agg.result, align 8 + ret void +} + +define float @float_and_r(float %cc_dep1) { +; CHECK-LABEL: float_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: # kill: def $f0s killed $f0s def $f0d +; CHECK-NEXT: lgdr %r0, %f0 +; CHECK-NEXT: risblg %r2, %r0, 0, 159, 32 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: risbhg %r0, %r2, 0, 159, 32 +; CHECK-NEXT: ldgr %f0, %r0 +; CHECK-NEXT: # kill: def $f0s killed $f0s killed $f0d +; CHECK-NEXT: br %r14 +entry: + %0 = tail call float asm sideeffect "", "={r2},0"(float %cc_dep1) + ret float %0 +} + +define double @double_and_r(double %cc_dep1) { +; CHECK-LABEL: double_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lgdr %r3, %f0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: ldgr %f0, %r3 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call double asm sideeffect "", "={r3},0"(double %cc_dep1) + ret double %0 +} + +define void @longdouble_and_r(ptr noalias nocapture writeonly sret(fp128) align 8 %agg.result, ptr %0) { +; CHECK-LABEL: longdouble_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lg %r5, 8(%r3) +; CHECK-NEXT: lg %r4, 0(%r3) +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: stg %r5, 8(%r2) +; CHECK-NEXT: stg %r4, 0(%r2) +; CHECK-NEXT: br %r14 +entry: + %cc_dep1 = load fp128, ptr %0, align 8 + %1 = tail call fp128 asm sideeffect "", "={r4},0"(fp128 %cc_dep1) + store fp128 %1, ptr %agg.result, align 8 + ret void +} + +define <2 x i16> @vec32_and_r(<2 x i16> %cc_dep1) { +; CHECK-LABEL: vec32_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: # kill: def $r3l killed $r3l def $r3d +; CHECK-NEXT: # kill: def $r2l killed $r2l def $r2d +; CHECK-NEXT: risbgn %r3, %r2, 32, 47, 16 +; CHECK-NEXT: # kill: def $r3l killed $r3l killed $r3d +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: srlk %r2, %r3, 16 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i16> asm sideeffect "", "={r3},0"(<2 x i16> %cc_dep1) + ret <2 x i16> %0 +} + +define <2 x i32> @vec64_and_r(<2 x i32> %cc_dep1) { +; CHECK-LABEL: vec64_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: # kill: def $r2l killed $r2l def $r2d +; CHECK-NEXT: sllg %r5, %r2, 32 +; CHECK-NEXT: lr %r5, %r3 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgr %r3, %r5 +; CHECK-NEXT: srlg %r2, %r5, 32 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: # kill: def $r3l killed $r3l killed $r3d +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i32> asm sideeffect "", "={r5},0"(<2 x i32> %cc_dep1) + ret <2 x i32> %0 +} + +define <2 x i16> @vec32_and_f(<2 x i16> %cc_dep1) { +; CHECK-LABEL: vec32_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: # kill: def $r3l killed $r3l def $r3d +; CHECK-NEXT: # kill: def $r2l killed $r2l def $r2d +; CHECK-NEXT: risbgn %r3, %r2, 32, 47, 16 +; CHECK-NEXT: risbhg %r0, %r3, 0, 159, 32 +; CHECK-NEXT: ldgr %f3, %r0 +; CHECK-NEXT: # kill: def $f3s killed $f3s killed $f3d +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: # kill: def $f3s killed $f3s def $f3d +; CHECK-NEXT: lgdr %r0, %f3 +; CHECK-NEXT: risblg %r3, %r0, 0, 159, 32 +; CHECK-NEXT: srlk %r2, %r3, 16 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i16> asm sideeffect "", "={f3},0"(<2 x i16> %cc_dep1) + ret <2 x i16> %0 +} + +define <2 x i32> @vec64_and_f(<2 x i32> %cc_dep1) { +; CHECK-LABEL: vec64_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: # kill: def $r2l killed $r2l def $r2d +; CHECK-NEXT: sllg %r0, %r2, 32 +; CHECK-NEXT: lr %r0, %r3 +; CHECK-NEXT: ldgr %f4, %r0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r3, %f4 +; CHECK-NEXT: srlg %r2, %r3, 32 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: # kill: def $r3l killed $r3l killed $r3d +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i32> asm sideeffect "", "={f4},0"(<2 x i32> %cc_dep1) + ret <2 x i32> %0 +} + +define <4 x i32> @vec128_and_f(<4 x i32> %cc_dep1) { +; CHECK-LABEL: vec128_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: aghi %r15, -176 +; CHECK-NEXT: .cfi_def_cfa_offset 336 +; CHECK-NEXT: # kill: def $r4l killed $r4l def $r4d +; CHECK-NEXT: sllg %r0, %r4, 32 +; CHECK-NEXT: lr %r0, %r5 +; CHECK-NEXT: # kill: def $r2l killed $r2l def $r2d +; CHECK-NEXT: stg %r0, 168(%r15) +; CHECK-NEXT: sllg %r0, %r2, 32 +; CHECK-NEXT: lr %r0, %r3 +; CHECK-NEXT: stg %r0, 160(%r15) +; CHECK-NEXT: ld %f0, 160(%r15) +; CHECK-NEXT: ld %f2, 168(%r15) +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r3, %f0 +; CHECK-NEXT: lgdr %r5, %f2 +; CHECK-NEXT: srlg %r2, %r3, 32 +; CHECK-NEXT: srlg %r4, %r5, 32 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: # kill: def $r3l killed $r3l killed $r3d +; CHECK-NEXT: # kill: def $r4l killed $r4l killed $r4d +; CHECK-NEXT: # kill: def $r5l killed $r5l killed $r5d +; CHECK-NEXT: aghi %r15, 176 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <4 x i32> asm sideeffect "", "={f0},0"(<4 x i32> %cc_dep1) + ret <4 x i32> %0 +} + diff --git a/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting-explicit-regs.ll b/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting-explicit-regs.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting-explicit-regs.ll @@ -0,0 +1,273 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mtriple=s390x-linux-gnu -mcpu=z15 < %s | FileCheck %s --check-prefixes=CHECK,Z15 +; RUN: llc -mtriple=s390x-linux-gnu -mcpu=z13 < %s | FileCheck %s --check-prefixes=CHECK,Z13 +; +; Test inline assembly where the operand is bitcasted. + +define signext i32 @int_and_f(i32 signext %cc_dep1) { +; CHECK-LABEL: int_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlvgf %v0, %r2, 0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlgvf %r0, %v0, 0 +; CHECK-NEXT: lgfr %r2, %r0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i32 asm sideeffect "", "={f0},0"(i32 %cc_dep1) + ret i32 %0 +} + +define i64 @long_and_f(i64 %cc_dep1) { +; CHECK-LABEL: long_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ldgr %f1, %r2 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r2, %f1 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i64 asm sideeffect "", "={f1},0"(i64 %cc_dep1) + ret i64 %0 +} + +define void @__int128_and_f(ptr noalias nocapture writeonly sret(i128) align 8 %agg.result, ptr %0) { +; Z15-LABEL: __int128_and_f: +; Z15: # %bb.0: # %entry +; Z15-NEXT: vl %v0, 0(%r3), 3 +; Z15-NEXT: vrepg %v6, %v0, 1 +; Z15-NEXT: vlr %v4, %v0 +; Z15-NEXT: #APP +; Z15-NEXT: #NO_APP +; Z15-NEXT: vmrhg %v0, %v4, %v6 +; Z15-NEXT: vst %v0, 0(%r2), 3 +; Z15-NEXT: br %r14 +; +; Z13-LABEL: __int128_and_f: +; Z13: # %bb.0: # %entry +; Z13-NEXT: ld %f4, 0(%r3) +; Z13-NEXT: ld %f6, 8(%r3) +; Z13-NEXT: #APP +; Z13-NEXT: #NO_APP +; Z13-NEXT: std %f4, 0(%r2) +; Z13-NEXT: std %f6, 8(%r2) +; Z13-NEXT: br %r14 +entry: + %cc_dep1 = load i128, ptr %0, align 8 + %1 = tail call i128 asm sideeffect "", "={f4},0"(i128 %cc_dep1) + store i128 %1, ptr %agg.result, align 8 + ret void +} + +define signext i32 @int_and_v(i32 signext %cc_dep1) { +; CHECK-LABEL: int_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlvgf %v0, %r2, 0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlgvf %r0, %v0, 0 +; CHECK-NEXT: lgfr %r2, %r0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i32 asm sideeffect "", "={v0},0"(i32 %cc_dep1) + ret i32 %0 +} + +define i64 @long_and_v(i64 %cc_dep1) { +; CHECK-LABEL: long_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ldgr %f1, %r2 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r2, %f1 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i64 asm sideeffect "", "={v1},0"(i64 %cc_dep1) + ret i64 %0 +} + +define void @__int128_and_v(ptr noalias nocapture writeonly sret(i128) align 8 %agg.result, ptr %0) { +; CHECK-LABEL: __int128_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vl %v2, 0(%r3), 3 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vst %v2, 0(%r2), 3 +; CHECK-NEXT: br %r14 +entry: + %cc_dep1 = load i128, ptr %0, align 8 + %1 = tail call i128 asm sideeffect "", "={v2},0"(i128 %cc_dep1) + store i128 %1, ptr %agg.result, align 8 + ret void +} + +define float @float_and_r(float %cc_dep1) { +; CHECK-LABEL: float_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlgvf %r0, %v0, 0 +; CHECK-NEXT: # kill: def $r0l killed $r0l killed $r0d +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlvgf %v0, %r0, 0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call float asm sideeffect "", "={r0},0"(float %cc_dep1) + ret float %0 +} + +define double @double_and_r(double %cc_dep1) { +; CHECK-LABEL: double_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lgdr %r1, %f0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: ldgr %f0, %r1 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call double asm sideeffect "", "={r1},0"(double %cc_dep1) + ret double %0 +} + +define void @longdouble_and_r(ptr noalias nocapture writeonly sret(fp128) align 8 %agg.result, ptr %0) { +; CHECK-LABEL: longdouble_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lg %r5, 8(%r3) +; CHECK-NEXT: lg %r4, 0(%r3) +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: stg %r5, 8(%r2) +; CHECK-NEXT: stg %r4, 0(%r2) +; CHECK-NEXT: br %r14 +entry: + %cc_dep1 = load fp128, ptr %0, align 8 + %1 = tail call fp128 asm sideeffect "", "={r4},0"(fp128 %cc_dep1) + store fp128 %1, ptr %agg.result, align 8 + ret void +} + +define float @float_and_v(float %cc_dep1) { +; CHECK-LABEL: float_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ldr %f3, %f0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: ldr %f0, %f3 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call float asm sideeffect "", "={v3},0"(float %cc_dep1) + ret float %0 +} + +define double @double_and_v(double %cc_dep1) { +; CHECK-LABEL: double_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ldr %f4, %f0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: ldr %f0, %f4 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call double asm sideeffect "", "={v4},0"(double %cc_dep1) + ret double %0 +} + +define void @longdouble_and_v(ptr noalias nocapture writeonly sret(fp128) align 8 %agg.result, ptr %0) { +; CHECK-LABEL: longdouble_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vl %v5, 0(%r3), 3 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vst %v5, 0(%r2), 3 +; CHECK-NEXT: br %r14 +entry: + %cc_dep1 = load fp128, ptr %0, align 8 + %1 = tail call fp128 asm sideeffect "", "={v5},0"(fp128 %cc_dep1) + store fp128 %1, ptr %agg.result, align 8 + ret void +} + +define <2 x i16> @vec32_and_r(<2 x i16> %cc_dep1) { +; CHECK-LABEL: vec32_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlgvf %r5, %v24, 0 +; CHECK-NEXT: # kill: def $r5l killed $r5l killed $r5d +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlvgf %v24, %r5, 0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i16> asm sideeffect "", "={r5},0"(<2 x i16> %cc_dep1) + ret <2 x i16> %0 +} + +define <2 x i32> @vec64_and_r(<2 x i32> %cc_dep1) { +; CHECK-LABEL: vec64_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlgvg %r4, %v24, 0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlvgg %v24, %r4, 0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i32> asm sideeffect "", "={r4},0"(<2 x i32> %cc_dep1) + ret <2 x i32> %0 +} + +define <4 x i32> @vec128_and_r(<4 x i32> %cc_dep1) { +; CHECK-LABEL: vec128_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlgvg %r3, %v24, 1 +; CHECK-NEXT: vlgvg %r2, %v24, 0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlvgp %v24, %r2, %r3 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <4 x i32> asm sideeffect "", "={r2},0"(<4 x i32> %cc_dep1) + ret <4 x i32> %0 +} + +define <2 x i16> @vec32_and_f(<2 x i16> %cc_dep1) { +; CHECK-LABEL: vec32_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlr %v4, %v24 +; CHECK-NEXT: # kill: def $f4s killed $f4s killed $v4 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: # kill: def $f4s killed $f4s def $v4 +; CHECK-NEXT: vlr %v24, %v4 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i16> asm sideeffect "", "={f4},0"(<2 x i16> %cc_dep1) + ret <2 x i16> %0 +} + +define <2 x i32> @vec64_and_f(<2 x i32> %cc_dep1) { +; CHECK-LABEL: vec64_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlr %v5, %v24 +; CHECK-NEXT: # kill: def $f5d killed $f5d killed $v5 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: # kill: def $f5d killed $f5d def $v5 +; CHECK-NEXT: vlr %v24, %v5 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i32> asm sideeffect "", "={f5},0"(<2 x i32> %cc_dep1) + ret <2 x i32> %0 +} + +define <4 x i32> @vec128_and_f(<4 x i32> %cc_dep1) { +; CHECK-LABEL: vec128_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vrepg %v3, %v24, 1 +; CHECK-NEXT: vlr %v1, %v24 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vmrhg %v24, %v1, %v3 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <4 x i32> asm sideeffect "", "={f1},0"(<4 x i32> %cc_dep1) + ret <4 x i32> %0 +} + diff --git a/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting-zEC12.ll b/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting-zEC12.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting-zEC12.ll @@ -0,0 +1,201 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mtriple=s390x-linux-gnu -mcpu=zEC12 < %s | FileCheck %s +; +; Test inline assembly where the operand is bitcasted. + +define signext i32 @int_and_f(i32 signext %cc_dep1) { +; CHECK-LABEL: int_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: risbhg %r0, %r2, 0, 159, 32 +; CHECK-NEXT: ldgr %f0, %r0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r0, %f0 +; CHECK-NEXT: risblg %r0, %r0, 0, 159, 32 +; CHECK-NEXT: lgfr %r2, %r0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i32 asm sideeffect "", "=f,0"(i32 %cc_dep1) + ret i32 %0 +} + +define i64 @long_and_f(i64 %cc_dep1) { +; CHECK-LABEL: long_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ldgr %f0, %r2 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r2, %f0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i64 asm sideeffect "", "=f,0"(i64 %cc_dep1) + ret i64 %0 +} + +define void @__int128_and_f(ptr noalias nocapture writeonly sret(i128) align 8 %agg.result, ptr %0) { +; CHECK-LABEL: __int128_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ld %f0, 0(%r3) +; CHECK-NEXT: ld %f2, 8(%r3) +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: std %f0, 0(%r2) +; CHECK-NEXT: std %f2, 8(%r2) +; CHECK-NEXT: br %r14 +entry: + %cc_dep1 = load i128, ptr %0, align 8 + %1 = tail call i128 asm sideeffect "", "=f,0"(i128 %cc_dep1) + store i128 %1, ptr %agg.result, align 8 + ret void +} + +define float @float_and_r(float %cc_dep1) { +; CHECK-LABEL: float_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: # kill: def $f0s killed $f0s def $f0d +; CHECK-NEXT: lgdr %r0, %f0 +; CHECK-NEXT: risblg %r0, %r0, 0, 159, 32 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: risbhg %r0, %r0, 0, 159, 32 +; CHECK-NEXT: ldgr %f0, %r0 +; CHECK-NEXT: # kill: def $f0s killed $f0s killed $f0d +; CHECK-NEXT: br %r14 +entry: + %0 = tail call float asm sideeffect "", "=r,0"(float %cc_dep1) + ret float %0 +} + +define double @double_and_r(double %cc_dep1) { +; CHECK-LABEL: double_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lgdr %r0, %f0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: ldgr %f0, %r0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call double asm sideeffect "", "=r,0"(double %cc_dep1) + ret double %0 +} + +define void @longdouble_and_r(ptr noalias nocapture writeonly sret(fp128) align 8 %agg.result, ptr %0) { +; CHECK-LABEL: longdouble_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lg %r1, 8(%r3) +; CHECK-NEXT: lg %r0, 0(%r3) +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: stg %r1, 8(%r2) +; CHECK-NEXT: stg %r0, 0(%r2) +; CHECK-NEXT: br %r14 +entry: + %cc_dep1 = load fp128, ptr %0, align 8 + %1 = tail call fp128 asm sideeffect "", "=r,0"(fp128 %cc_dep1) + store fp128 %1, ptr %agg.result, align 8 + ret void +} + +define <2 x i16> @vec32_and_r(<2 x i16> %cc_dep1) { +; CHECK-LABEL: vec32_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: # kill: def $r3l killed $r3l def $r3d +; CHECK-NEXT: # kill: def $r2l killed $r2l def $r2d +; CHECK-NEXT: risbgn %r3, %r2, 32, 47, 16 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: srlk %r2, %r3, 16 +; CHECK-NEXT: # kill: def $r3l killed $r3l killed $r3d +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i16> asm sideeffect "", "=r,0"(<2 x i16> %cc_dep1) + ret <2 x i16> %0 +} + +define <2 x i32> @vec64_and_r(<2 x i32> %cc_dep1) { +; CHECK-LABEL: vec64_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: # kill: def $r2l killed $r2l def $r2d +; CHECK-NEXT: sllg %r0, %r2, 32 +; CHECK-NEXT: lr %r0, %r3 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lr %r3, %r0 +; CHECK-NEXT: srlg %r2, %r0, 32 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i32> asm sideeffect "", "=r,0"(<2 x i32> %cc_dep1) + ret <2 x i32> %0 +} + +define <2 x i16> @vec32_and_f(<2 x i16> %cc_dep1) { +; CHECK-LABEL: vec32_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: # kill: def $r3l killed $r3l def $r3d +; CHECK-NEXT: # kill: def $r2l killed $r2l def $r2d +; CHECK-NEXT: risbgn %r3, %r2, 32, 47, 16 +; CHECK-NEXT: risbhg %r0, %r3, 0, 159, 32 +; CHECK-NEXT: ldgr %f0, %r0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r0, %f0 +; CHECK-NEXT: risblg %r3, %r0, 0, 159, 32 +; CHECK-NEXT: srlk %r2, %r3, 16 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i16> asm sideeffect "", "=f,0"(<2 x i16> %cc_dep1) + ret <2 x i16> %0 +} + +define <2 x i32> @vec64_and_f(<2 x i32> %cc_dep1) { +; CHECK-LABEL: vec64_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: # kill: def $r2l killed $r2l def $r2d +; CHECK-NEXT: sllg %r0, %r2, 32 +; CHECK-NEXT: lr %r0, %r3 +; CHECK-NEXT: ldgr %f0, %r0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r3, %f0 +; CHECK-NEXT: srlg %r2, %r3, 32 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: # kill: def $r3l killed $r3l killed $r3d +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i32> asm sideeffect "", "=f,0"(<2 x i32> %cc_dep1) + ret <2 x i32> %0 +} + +define <4 x i32> @vec128_and_f(<4 x i32> %cc_dep1) { +; CHECK-LABEL: vec128_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: aghi %r15, -176 +; CHECK-NEXT: .cfi_def_cfa_offset 336 +; CHECK-NEXT: # kill: def $r4l killed $r4l def $r4d +; CHECK-NEXT: sllg %r0, %r4, 32 +; CHECK-NEXT: lr %r0, %r5 +; CHECK-NEXT: # kill: def $r2l killed $r2l def $r2d +; CHECK-NEXT: stg %r0, 168(%r15) +; CHECK-NEXT: sllg %r0, %r2, 32 +; CHECK-NEXT: lr %r0, %r3 +; CHECK-NEXT: stg %r0, 160(%r15) +; CHECK-NEXT: ld %f0, 160(%r15) +; CHECK-NEXT: ld %f2, 168(%r15) +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r3, %f0 +; CHECK-NEXT: lgdr %r5, %f2 +; CHECK-NEXT: srlg %r2, %r3, 32 +; CHECK-NEXT: srlg %r4, %r5, 32 +; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d +; CHECK-NEXT: # kill: def $r3l killed $r3l killed $r3d +; CHECK-NEXT: # kill: def $r4l killed $r4l killed $r4d +; CHECK-NEXT: # kill: def $r5l killed $r5l killed $r5d +; CHECK-NEXT: aghi %r15, 176 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <4 x i32> asm sideeffect "", "=f,0"(<4 x i32> %cc_dep1) + ret <4 x i32> %0 +} + diff --git a/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting.ll b/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/inline-asm-fp-int-casting.ll @@ -0,0 +1,262 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mtriple=s390x-linux-gnu -mcpu=z15 < %s | FileCheck %s --check-prefixes=CHECK,Z15 +; RUN: llc -mtriple=s390x-linux-gnu -mcpu=z13 < %s | FileCheck %s --check-prefixes=CHECK,Z13 +; +; Test inline assembly where the operand is bitcasted. + +define signext i32 @int_and_f(i32 signext %cc_dep1) { +; CHECK-LABEL: int_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlvgf %v0, %r2, 0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlgvf %r0, %v0, 0 +; CHECK-NEXT: lgfr %r2, %r0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i32 asm sideeffect "", "=f,0"(i32 %cc_dep1) + ret i32 %0 +} + +define i64 @long_and_f(i64 %cc_dep1) { +; CHECK-LABEL: long_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ldgr %f0, %r2 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r2, %f0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i64 asm sideeffect "", "=f,0"(i64 %cc_dep1) + ret i64 %0 +} + +define void @__int128_and_f(ptr noalias nocapture writeonly sret(i128) align 8 %agg.result, ptr %0) { +; Z15-LABEL: __int128_and_f: +; Z15: # %bb.0: # %entry +; Z15-NEXT: vl %v0, 0(%r3), 3 +; Z15-NEXT: vrepg %v2, %v0, 1 +; Z15-NEXT: #APP +; Z15-NEXT: #NO_APP +; Z15-NEXT: vmrhg %v0, %v0, %v2 +; Z15-NEXT: vst %v0, 0(%r2), 3 +; Z15-NEXT: br %r14 +; +; Z13-LABEL: __int128_and_f: +; Z13: # %bb.0: # %entry +; Z13-NEXT: ld %f0, 0(%r3) +; Z13-NEXT: ld %f2, 8(%r3) +; Z13-NEXT: #APP +; Z13-NEXT: #NO_APP +; Z13-NEXT: std %f0, 0(%r2) +; Z13-NEXT: std %f2, 8(%r2) +; Z13-NEXT: br %r14 +entry: + %cc_dep1 = load i128, ptr %0, align 8 + %1 = tail call i128 asm sideeffect "", "=f,0"(i128 %cc_dep1) + store i128 %1, ptr %agg.result, align 8 + ret void +} + +define signext i32 @int_and_v(i32 signext %cc_dep1) { +; CHECK-LABEL: int_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlvgf %v0, %r2, 0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlgvf %r0, %v0, 0 +; CHECK-NEXT: lgfr %r2, %r0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i32 asm sideeffect "", "=v,0"(i32 %cc_dep1) + ret i32 %0 +} + +define i64 @long_and_v(i64 %cc_dep1) { +; CHECK-LABEL: long_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ldgr %f0, %r2 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: lgdr %r2, %f0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call i64 asm sideeffect "", "=v,0"(i64 %cc_dep1) + ret i64 %0 +} + +define void @__int128_and_v(ptr noalias nocapture writeonly sret(i128) align 8 %agg.result, ptr %0) { +; CHECK-LABEL: __int128_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vl %v0, 0(%r3), 3 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vst %v0, 0(%r2), 3 +; CHECK-NEXT: br %r14 +entry: + %cc_dep1 = load i128, ptr %0, align 8 + %1 = tail call i128 asm sideeffect "", "=v,0"(i128 %cc_dep1) + store i128 %1, ptr %agg.result, align 8 + ret void +} + +define float @float_and_r(float %cc_dep1) { +; CHECK-LABEL: float_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlgvf %r0, %v0, 0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlvgf %v0, %r0, 0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call float asm sideeffect "", "=r,0"(float %cc_dep1) + ret float %0 +} + +define double @double_and_r(double %cc_dep1) { +; CHECK-LABEL: double_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lgdr %r0, %f0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: ldgr %f0, %r0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call double asm sideeffect "", "=r,0"(double %cc_dep1) + ret double %0 +} + +define void @longdouble_and_r(ptr noalias nocapture writeonly sret(fp128) align 8 %agg.result, ptr %0) { +; CHECK-LABEL: longdouble_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lg %r1, 8(%r3) +; CHECK-NEXT: lg %r0, 0(%r3) +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: stg %r1, 8(%r2) +; CHECK-NEXT: stg %r0, 0(%r2) +; CHECK-NEXT: br %r14 +entry: + %cc_dep1 = load fp128, ptr %0, align 8 + %1 = tail call fp128 asm sideeffect "", "=r,0"(fp128 %cc_dep1) + store fp128 %1, ptr %agg.result, align 8 + ret void +} + +define float @float_and_v(float %cc_dep1) { +; CHECK-LABEL: float_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: br %r14 +entry: + %0 = tail call float asm sideeffect "", "=v,0"(float %cc_dep1) + ret float %0 +} + +define double @double_and_v(double %cc_dep1) { +; CHECK-LABEL: double_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: br %r14 +entry: + %0 = tail call double asm sideeffect "", "=v,0"(double %cc_dep1) + ret double %0 +} + +define void @longdouble_and_v(ptr noalias nocapture writeonly sret(fp128) align 8 %agg.result, ptr %0) { +; CHECK-LABEL: longdouble_and_v: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vl %v0, 0(%r3), 3 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vst %v0, 0(%r2), 3 +; CHECK-NEXT: br %r14 +entry: + %cc_dep1 = load fp128, ptr %0, align 8 + %1 = tail call fp128 asm sideeffect "", "=v,0"(fp128 %cc_dep1) + store fp128 %1, ptr %agg.result, align 8 + ret void +} + +define <2 x i16> @vec32_and_r(<2 x i16> %cc_dep1) { +; CHECK-LABEL: vec32_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlgvf %r0, %v24, 0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlvgf %v24, %r0, 0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i16> asm sideeffect "", "=r,0"(<2 x i16> %cc_dep1) + ret <2 x i16> %0 +} + +define <2 x i32> @vec64_and_r(<2 x i32> %cc_dep1) { +; CHECK-LABEL: vec64_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlgvg %r0, %v24, 0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlvgg %v24, %r0, 0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i32> asm sideeffect "", "=r,0"(<2 x i32> %cc_dep1) + ret <2 x i32> %0 +} + +define <4 x i32> @vec128_and_r(<4 x i32> %cc_dep1) { +; CHECK-LABEL: vec128_and_r: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlgvg %r1, %v24, 1 +; CHECK-NEXT: vlgvg %r0, %v24, 0 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlvgp %v24, %r0, %r1 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <4 x i32> asm sideeffect "", "=r,0"(<4 x i32> %cc_dep1) + ret <4 x i32> %0 +} + +define <2 x i16> @vec32_and_f(<2 x i16> %cc_dep1) { +; CHECK-LABEL: vec32_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlr %v0, %v24 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlr %v24, %v0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i16> asm sideeffect "", "=f,0"(<2 x i16> %cc_dep1) + ret <2 x i16> %0 +} + +define <2 x i32> @vec64_and_f(<2 x i32> %cc_dep1) { +; CHECK-LABEL: vec64_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vlr %v0, %v24 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vlr %v24, %v0 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <2 x i32> asm sideeffect "", "=f,0"(<2 x i32> %cc_dep1) + ret <2 x i32> %0 +} + +define <4 x i32> @vec128_and_f(<4 x i32> %cc_dep1) { +; CHECK-LABEL: vec128_and_f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vrepg %v2, %v24, 1 +; CHECK-NEXT: vlr %v0, %v24 +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vmrhg %v24, %v0, %v2 +; CHECK-NEXT: br %r14 +entry: + %0 = tail call <4 x i32> asm sideeffect "", "=f,0"(<4 x i32> %cc_dep1) + ret <4 x i32> %0 +} + diff --git a/llvm/test/CodeGen/SystemZ/inline-asm-v-constraint-novecfacility.ll b/llvm/test/CodeGen/SystemZ/inline-asm-v-constraint-novecfacility.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/inline-asm-v-constraint-novecfacility.ll @@ -0,0 +1,9 @@ +; RUN: not llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 2>&1 | FileCheck %s + +; CHECK: error: couldn't allocate output register for constraint 'v' + +define signext i32 @int_and_v(i32 signext %cc_dep1) { +entry: + %0 = tail call i32 asm sideeffect "", "=v,0"(i32 %cc_dep1) + ret i32 %0 +}