Commit bfa3b627 authored by Gui Andrade's avatar Gui Andrade
Browse files

[InstCombine] Erase attribute lists for simplified libcalls

Currently, a transformation like pow(2.0, x) -> exp2(x) copies the pow
attribute list verbatim and applies it to exp2. This works out fine
when the attribute list is empty, but when it isn't clang may error due
due to the mismatch.

The source function and destination don't necessarily have anything
to do with one another, attribute-wise. So it makes sense to remove
the attribute lists (this is similar to what IPO does in this
situation).

This was discovered after implementing the `noundef` param attribute.

Differential Revision: https://reviews.llvm.org/D82820
parent 3d52b1e8
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -1448,7 +1448,7 @@ static Value *getIntToFPVal(Value *I2F, IRBuilderBase &B) {
/// exp10(x) for pow(10.0, x); exp2(log2(n) * x) for pow(n, x).
Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) {
  Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1);
  AttributeList Attrs = Pow->getCalledFunction()->getAttributes();
  AttributeList Attrs; // Attributes are only meaningful on the original call
  Module *Mod = Pow->getModule();
  Type *Ty = Pow->getType();
  bool Ignored;
@@ -1615,7 +1615,7 @@ static Value *getSqrtCall(Value *V, AttributeList Attrs, bool NoErrno,
/// Use square root in place of pow(x, +/-0.5).
Value *LibCallSimplifier::replacePowWithSqrt(CallInst *Pow, IRBuilderBase &B) {
  Value *Sqrt, *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1);
  AttributeList Attrs = Pow->getCalledFunction()->getAttributes();
  AttributeList Attrs; // Attributes are only meaningful on the original call
  Module *Mod = Pow->getModule();
  Type *Ty = Pow->getType();

@@ -1785,6 +1785,7 @@ Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilderBase &B) {

Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) {
  Function *Callee = CI->getCalledFunction();
  AttributeList Attrs; // Attributes are only meaningful on the original call
  StringRef Name = Callee->getName();
  Value *Ret = nullptr;
  if (UnsafeFPShrink && Name == TLI->getName(LibFunc_exp2) &&
@@ -1801,7 +1802,7 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) {
    if (Value *Exp = getIntToFPVal(Op, B))
      return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), Exp, TLI,
                                   LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl,
                                   B, CI->getCalledFunction()->getAttributes());
                                   B, Attrs);
  }

  return Ret;
@@ -1836,7 +1837,7 @@ Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilderBase &B) {

Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
  Function *LogFn = Log->getCalledFunction();
  AttributeList Attrs = LogFn->getAttributes();
  AttributeList Attrs; // Attributes are only meaningful on the original call
  StringRef LogNm = LogFn->getName();
  Intrinsic::ID LogID = LogFn->getIntrinsicID();
  Module *Mod = Log->getModule();
+3 −3
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ define double @pow_uitofp_double_const_base_fast(i31 %x) {

define double @pow_sitofp_double_const_base_2_fast(i32 %x) {
; CHECK-LABEL: @pow_sitofp_double_const_base_2_fast(
; CHECK-NEXT:    [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) #1
; CHECK-NEXT:    [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[X:%.*]])
; CHECK-NEXT:    [[RES:%.*]] = fpext float [[LDEXPF]] to double
; CHECK-NEXT:    ret double [[RES]]
;
@@ -78,7 +78,7 @@ define double @pow_sitofp_double_const_base_power_of_2_fast(i32 %x) {
define double @pow_uitofp_const_base_2_fast(i31 %x) {
; CHECK-LABEL: @pow_uitofp_const_base_2_fast(
; CHECK-NEXT:    [[TMP1:%.*]] = zext i31 [[X:%.*]] to i32
; CHECK-NEXT:    [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[TMP1]]) #1
; CHECK-NEXT:    [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[TMP1]])
; CHECK-NEXT:    [[RES:%.*]] = fpext float [[LDEXPF]] to double
; CHECK-NEXT:    ret double [[RES]]
;
@@ -343,7 +343,7 @@ define double @pow_uitofp_const_base_no_fast(i32 %x) {

define double @pow_sitofp_const_base_2_no_fast(i32 %x) {
; CHECK-LABEL: @pow_sitofp_const_base_2_no_fast(
; CHECK-NEXT:    [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) #1
; CHECK-NEXT:    [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[X:%.*]])
; CHECK-NEXT:    [[RES:%.*]] = fpext float [[LDEXPF]] to double
; CHECK-NEXT:    ret double [[RES]]
;
+22 −0
Original line number Diff line number Diff line
@@ -175,6 +175,28 @@ define i32 @fake_toascii(i8 %x) {
  ret i32 %y
}

declare double @pow(double, double)
declare double @exp2(double)

; check to make sure only the correct libcall attributes are used
define double @fake_exp2(double %x) {
; CHECK-LABEL: @fake_exp2(
; CHECK-NEXT:    [[Y:%.*]] = call double @exp2(double %x)
; CHECK-NEXT:    ret double [[Y]]

  %y = call inreg double @pow(double inreg 2.0, double inreg %x)
  ret double %y
}
define double @fake_ldexp(i32 %x) {
; CHECK-LABEL: @fake_ldexp(
; CHECK-NEXT:    [[Z:%.*]] = call double @ldexp(double 1.0{{.*}}, i32 %x)
; CHECK-NEXT:    ret double [[Z]]

  %y = sitofp i32 %x to double
  %z = call inreg double @exp2(double %y)
  ret double %z
}


attributes #0 = { nobuiltin }
attributes #1 = { builtin }