[LegalizeTypes] Avoid promotion of exponent in FPOWI

The FPOWI DAG node is normally lowered to a libcall to one of the
RTLIB::POWI* runtime functions and the exponent should normally
have a type matching sizeof(int) when making the call. Thus,
type promotion of the exponent could lead to an FPOWI with a type
for the second operand that would be incorrect when doing the
libcall (a situation which would be hard to detect post-legalization
if we allow such FPOWI nodes).

This patch is changing DAGTypeLegalizer::PromoteIntOp_FPOWI to
do the rewrite into a libcall directly instead of promoting the
operand. This way we can check that the exponent is smaller than
sizeof(int) and we can let TargetLowering handle promotion as
part of making the libcall. It could be noticed here that makeLibCall
has some knowledge about targets such as 64-bit RISCV, for which the
libcall argument should be extended to a type larger than sizeof(int).

Differential Revision: https://reviews.llvm.org/D102950
This commit is contained in:
Bjorn Pettersson 2021-05-22 00:24:25 +02:00
parent 9c54ee4378
commit d1273d39d3
1 changed files with 39 additions and 2 deletions

View File

@ -18,6 +18,7 @@
//===----------------------------------------------------------------------===//
#include "LegalizeTypes.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
@ -1986,8 +1987,44 @@ SDValue DAGTypeLegalizer::PromoteIntOp_PREFETCH(SDNode *N, unsigned OpNo) {
}
SDValue DAGTypeLegalizer::PromoteIntOp_FPOWI(SDNode *N) {
SDValue Op = SExtPromotedInteger(N->getOperand(1));
return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), Op), 0);
// FIXME: Support for promotion of STRICT_FPOWI is not implemented yet.
assert(N->getOpcode() == ISD::FPOWI && "No STRICT_FPOWI support here yet.");
// The integer operand is the last operand in FPOWI (so the result and
// floating point operand is already type legalized).
// We can't just promote the exponent type in FPOWI, since we want to lower
// the node to a libcall and we if we promote to a type larger than
// sizeof(int) the libcall might not be according to the targets ABI. Instead
// we rewrite to a libcall here directly, letting makeLibCall handle promotion
// if the target accepts it according to shouldSignExtendTypeInLibCall.
RTLIB::Libcall LC;
switch (N->getSimpleValueType(0).SimpleTy) {
default: llvm_unreachable("Unexpected request for libcall!");
case MVT::f32: LC = RTLIB::POWI_F32; break;
case MVT::f64: LC = RTLIB::POWI_F64; break;
case MVT::f80: LC = RTLIB::POWI_F80; break;
case MVT::f128: LC = RTLIB::POWI_F128; break;
case MVT::ppcf128: LC = RTLIB::POWI_PPCF128; break;
}
if (!TLI.getLibcallName(LC)) {
// Some targets don't have a powi libcall; use pow instead.
// FIXME: Implement this if some target needs it.
DAG.getContext()->emitError("Don't know how to promote fpowi to fpow");
return DAG.getUNDEF(N->getValueType(0));
}
// The exponent should fit in a sizeof(int) type for the libcall to be valid.
assert(DAG.getLibInfo().getIntSize() ==
N->getOperand(1).getValueType().getSizeInBits() &&
"POWI exponent should match with sizeof(int) when doing the libcall.");
TargetLowering::MakeLibCallOptions CallOptions;
CallOptions.setSExt(true);
SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) };
std::pair<SDValue, SDValue> Tmp =
TLI.makeLibCall(DAG, LC, N->getValueType(0), Ops,
CallOptions, SDLoc(N), SDValue());
ReplaceValueWith(SDValue(N, 0), Tmp.first);
return SDValue();
}
SDValue DAGTypeLegalizer::PromoteIntOp_VECREDUCE(SDNode *N) {