Skip to content

Commit

Permalink
[SystemZ][z/OS] Fix f32 variadic argument assertion
Browse files Browse the repository at this point in the history
The tablegen lines that specify the XPLINK64 calling convention for promoting an f32 vararg to an f64 are effectively overwritten by the following tablegen line which bitcast an f64 vararg to an i64 (so that it can be used in the GPRs). It becomes a bitcast from f32 to i64.

Since we don't handle a bitcast for f32s this caused an assertion.
  • Loading branch information
mubarizafzal authored and Everybody0523 committed Feb 15, 2022
1 parent faab70b commit ea0676f
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
7 changes: 4 additions & 3 deletions llvm/lib/Target/SystemZ/SystemZCallingConv.td
Expand Up @@ -225,9 +225,10 @@ def CC_SystemZ_XPLINK64 : CallingConv<[
// XPLINK64 ABI compliant code widens integral types smaller than i64
// to i64 before placing the parameters either on the stack or in registers.
CCIfType<[i32], CCIfExtend<CCPromoteToType<i64>>>,
// Promote f32 to f64 and bitcast to i64, if it needs to be passed in GPRS.
CCIfType<[f32], CCIfNotFixed<CCPromoteToType<f64>>>,
CCIfType<[f64], CCIfNotFixed<CCBitConvertToType<i64>>>,
// Promote f32 to f64 and bitcast to i64, if it needs to be passed in GPRs.
// Although we assign the f32 vararg to be bitcast, it will first be promoted
// to an f64 within convertValVTToLocVT().
CCIfType<[f32, f64], CCIfNotFixed<CCBitConvertToType<i64>>>,
// long double, can only be passed in GPR2 and GPR3, if available,
// hence R2Q
CCIfType<[f128], CCIfNotFixed<CCCustom<"CC_XPLINK64_Allocate128BitVararg">>>,
Expand Down
8 changes: 6 additions & 2 deletions llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
Expand Up @@ -1358,8 +1358,12 @@ static SDValue convertValVTToLocVT(SelectionDAG &DAG, const SDLoc &DL,
return DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Value);
case CCValAssign::BCvt: {
assert(VA.getLocVT() == MVT::i64 || VA.getLocVT() == MVT::i128);
assert(VA.getValVT().isVector() || VA.getValVT() == MVT::f64 ||
VA.getValVT() == MVT::f128);
assert(VA.getValVT().isVector() || VA.getValVT() == MVT::f32 ||
VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::f128);
// For an f32 vararg we need to first promote it to an f64 and then
// bitcast it to an i64.
if (VA.getValVT() == MVT::f32 && VA.getLocVT() == MVT::i64)
Value = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f64, Value);
MVT BitCastToType = VA.getValVT().isVector() && VA.getLocVT() == MVT::i64
? MVT::v2i64
: VA.getLocVT();
Expand Down
23 changes: 23 additions & 0 deletions llvm/test/CodeGen/SystemZ/call-zos-vararg.ll
Expand Up @@ -189,7 +189,30 @@ entry:
ret i64 %retval
}

; CHECK-LABEL: call_vararg_float0
; CHECK: lghi 1, 1
; CHECK: llihf 2, 1073692672
define i64 @call_vararg_float0() {
entry:
%retval = call i64 (i64, ...) @pass_vararg2(i64 1, float 1.953125)
ret i64 %retval
}

; CHECK-LABEL: call_vararg_float1
; CHECK: llihf 0, 1073692672
; CHECK-NEXT: stg 0, 2200(4)
; CHECK: larl 1, @CPI21_0
; CHECK-NEXT: le 0, 0(1)
; CHECK: llihh 2, 16384
; CHECK: llihh 3, 16392
define i64 @call_vararg_float1() {
entry:
%retval = call i64 (float, ...) @pass_vararg4(float 1.0, float 2.0, float 3.0, float 1.953125)
ret i64 %retval
}

declare i64 @pass_vararg0(i64 %arg0, i64 %arg1, ...)
declare i64 @pass_vararg1(fp128 %arg0, ...)
declare i64 @pass_vararg2(i64 %arg0, ...)
declare i64 @pass_vararg3(...)
declare i64 @pass_vararg4(float, ...)

0 comments on commit ea0676f

Please sign in to comment.