Don't transform calls unless some aspect is unneeded
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index f8c27ed..45943ca 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -4016,8 +4016,28 @@
--FirstArgIdx;
StringRef FnName = Args[3];
StringRef ImplName = Args[4];
- DenseSet<StringRef> Aspects(llvm::from_range,
- ArrayRef<StringRef>(Args).drop_front(5));
+ ArrayRef<StringRef> AllAspects = ArrayRef<StringRef>(Args).drop_front(5);
+
+ if (AllAspects.empty())
+ return nullptr;
+
+ SmallVector<StringRef> NeededAspects;
+ for (StringRef Aspect : AllAspects) {
+ if (Aspect == "float") {
+ if (llvm::any_of(
+ llvm::make_range(std::next(CI->arg_begin(), FirstArgIdx),
+ CI->arg_end()),
+ [](Value *V) { return V->getType()->isFloatingPointTy(); }))
+ NeededAspects.push_back("float");
+ } else {
+ // Unknown aspects are always considered to be needed.
+ NeededAspects.push_back(Aspect);
+ }
+ }
+
+ if (NeededAspects.size() == AllAspects.size())
+ return nullptr;
+
Module *M = CI->getModule();
Function *Callee = CI->getCalledFunction();
FunctionCallee ModularFn =
@@ -4040,18 +4060,8 @@
B.CreateCall(RelocNoneFn, {Sym});
};
- if (Aspects.contains("float")) {
- Aspects.erase("float");
- if (llvm::any_of(
- llvm::make_range(std::next(CI->arg_begin(), FirstArgIdx),
- CI->arg_end()),
- [](Value *V) { return V->getType()->isFloatingPointTy(); }))
- ReferenceAspect("float");
- }
-
- SmallVector<StringRef> UnknownAspects(Aspects.begin(), Aspects.end());
- llvm::sort(UnknownAspects);
- for (StringRef Request : UnknownAspects)
+ llvm::sort(NeededAspects);
+ for (StringRef Request : NeededAspects)
ReferenceAspect(Request);
return New;
diff --git a/llvm/test/Transforms/InstCombine/modular-format.ll b/llvm/test/Transforms/InstCombine/modular-format.ll
index 9b1e60b..f95b6c5 100644
--- a/llvm/test/Transforms/InstCombine/modular-format.ll
+++ b/llvm/test/Transforms/InstCombine/modular-format.ll
@@ -8,75 +8,58 @@
@.str.int = constant [3 x i8] c"%d\00"
@.str.float = constant [3 x i8] c"%f\00"
@.str.multi = constant [6 x i8] c"%f %d\00"
-@.str.multifp = constant [6 x i8] c"%f %f\00"
@.str.noargs = constant [1 x i8] c"\00"
-; Basic Transformation
+; No aspects are specified, so no transformation occurs.
define void @test_basic(i32 %arg) {
; CHECK-LABEL: @test_basic(
-; CHECK-NEXT: call void (ptr, ...) @basic_mod(ptr nonnull @.str.int, i32 [[ARG:%.*]])
+; CHECK-NEXT: call void (ptr, ...) @basic(ptr nonnull @.str.int, i32 [[ARG:%.*]])
; CHECK-NEXT: ret void
;
call void (ptr, ...) @basic(ptr @.str.int, i32 %arg)
ret void
}
-declare void @basic(ptr, ...) "modular-format"="printf,1,2,basic_mod,basic_impl"
-; "float" Aspect - Present
+declare void @basic(ptr, ...) #0
+
+; The "float" aspect is present and needed, so no transformation occurs.
define void @test_float_present(double %arg) {
; CHECK-LABEL: @test_float_present(
-; CHECK-NEXT: call void (ptr, ...) @float_present_mod(ptr nonnull @.str.float, double [[ARG:%.*]])
-; CHECK-NEXT: call void @llvm.reloc.none(ptr nonnull @basic_impl_float)
+; CHECK-NEXT: call void (ptr, ...) @float_present(ptr nonnull @.str.float, double [[ARG:%.*]])
; CHECK-NEXT: ret void
;
call void (ptr, ...) @float_present(ptr @.str.float, double %arg)
ret void
}
-declare void @float_present(ptr, ...) #0
+declare void @float_present(ptr, ...) #1
-; Unknown Aspects
+; The "float" aspect is present but not needed, so the call is transformed.
+define void @test_float_absent(i32 %arg) {
+; CHECK-LABEL: @test_float_absent(
+; CHECK-NEXT: call void (ptr, ...) @float_present_mod(ptr nonnull @.str.int, i32 [[ARG:%.*]])
+; CHECK-NEXT: ret void
+;
+ call void (ptr, ...) @float_absent(ptr @.str.int, i32 %arg)
+ ret void
+}
+
+declare void @float_absent(ptr, ...) #1
+
+; Unknown aspects are always considered needed, so no transformation occurs.
define void @test_unknown_aspects(i32 %arg) {
; CHECK-LABEL: @test_unknown_aspects(
-; CHECK-NEXT: call void (ptr, ...) @unknown_aspects_mod(ptr nonnull @.str.int, i32 [[ARG:%.*]])
-; CHECK-NEXT: call void @llvm.reloc.none(ptr nonnull @basic_impl_unknown1)
-; CHECK-NEXT: call void @llvm.reloc.none(ptr nonnull @basic_impl_unknown2)
+; CHECK-NEXT: call void (ptr, ...) @unknown_aspects(ptr nonnull @.str.int, i32 [[ARG:%.*]])
; CHECK-NEXT: ret void
;
call void (ptr, ...) @unknown_aspects(ptr @.str.int, i32 %arg)
ret void
}
-declare void @unknown_aspects(ptr, ...) "modular-format"="printf,1,2,unknown_aspects_mod,basic_impl,unknown1,unknown2"
+declare void @unknown_aspects(ptr, ...) #2
-; Multiple Aspects
-define void @test_multiple_aspects(double %arg1, i32 %arg2) {
-; CHECK-LABEL: @test_multiple_aspects(
-; CHECK-NEXT: call void (ptr, ...) @multiple_aspects_mod(ptr nonnull @.str.multi, double [[ARG1:%.*]], i32 [[ARG2:%.*]])
-; CHECK-NEXT: call void @llvm.reloc.none(ptr nonnull @basic_impl_float)
-; CHECK-NEXT: call void @llvm.reloc.none(ptr nonnull @basic_impl_unknown)
-; CHECK-NEXT: ret void
-;
- call void (ptr, ...) @multiple_aspects(ptr @.str.multi, double %arg1, i32 %arg2)
- ret void
-}
-
-declare void @multiple_aspects(ptr, ...) "modular-format"="printf,1,2,multiple_aspects_mod,basic_impl,float,unknown"
-
-; Multiple Floating-Point Arguments
-define void @test_multiple_fp_args(double %arg1, float %arg2) {
-; CHECK-LABEL: @test_multiple_fp_args(
-; CHECK-NEXT: call void (ptr, ...) @float_present_mod(ptr nonnull @.str.multifp, double [[ARG1:%.*]], float [[ARG2:%.*]])
-; CHECK-NEXT: call void @llvm.reloc.none(ptr nonnull @basic_impl_float)
-; CHECK-NEXT: ret void
-;
- call void (ptr, ...) @multiple_fp_args(ptr @.str.multifp, double %arg1, float %arg2)
- ret void
-}
-
-declare void @multiple_fp_args(ptr, ...) #0
-
-; No Arguments to Check
+; The call has no arguments to check, so the "float" aspect is not needed and
+; the call is transformed.
define void @test_no_args_to_check() {
; CHECK-LABEL: @test_no_args_to_check(
; CHECK-NEXT: call void (ptr, ...) @float_present_mod(ptr nonnull @.str.noargs)
@@ -86,19 +69,37 @@
ret void
}
-declare void @no_args_to_check(ptr, ...) #0
+declare void @no_args_to_check(ptr, ...) #1
-; First argument index != 2
+; The first argument index is not 2. The "float" aspect is needed, so no
+; transformation occurs.
define void @test_first_arg_idx(i32 %ignored, double %arg) {
; CHECK-LABEL: @test_first_arg_idx(
-; CHECK-NEXT: call void (i32, ptr, ...) @first_arg_idx_mod(i32 [[IGNORED:%.*]], ptr nonnull @.str.float, double [[ARG:%.*]])
-; CHECK-NEXT: call void @llvm.reloc.none(ptr nonnull @basic_impl_float)
+; CHECK-NEXT: call void (i32, ptr, ...) @first_arg_idx(i32 [[IGNORED:%.*]], ptr nonnull @.str.float, double [[ARG:%.*]])
; CHECK-NEXT: ret void
;
call void (i32, ptr, ...) @first_arg_idx(i32 %ignored, ptr @.str.float, double %arg)
ret void
}
-declare void @first_arg_idx(i32, ptr, ...) "modular-format"="printf,2,3,first_arg_idx_mod,basic_impl,float"
+declare void @first_arg_idx(i32, ptr, ...) #3
-attributes #0 = { "modular-format"="printf,1,2,float_present_mod,basic_impl,float" }
+; One aspect ("unknown") is needed, but one ("float") is not. The call is
+; transformed, and a reference to the needed aspect is emitted.
+define void @test_partial_aspects(i32 %arg) {
+; CHECK-LABEL: @test_partial_aspects(
+; CHECK-NEXT: call void (ptr, ...) @multiple_aspects_mod(ptr nonnull @.str.int, i32 [[ARG:%.*]])
+; CHECK-NEXT: call void @llvm.reloc.none(ptr nonnull @basic_impl_unknown)
+; CHECK-NEXT: ret void
+;
+ call void (ptr, ...) @partial_aspects(ptr @.str.int, i32 %arg)
+ ret void
+}
+
+declare void @partial_aspects(ptr, ...) #4
+
+attributes #0 = { "modular-format"="printf,1,2,basic_mod,basic_impl" }
+attributes #1 = { "modular-format"="printf,1,2,float_present_mod,basic_impl,float" }
+attributes #2 = { "modular-format"="printf,1,2,unknown_aspects_mod,basic_impl,unknown1,unknown2" }
+attributes #3 = { "modular-format"="printf,2,3,first_arg_idx_mod,basic_impl,float" }
+attributes #4 = { "modular-format"="printf,1,2,multiple_aspects_mod,basic_impl,float,unknown" }