[llvm] [IR] Remove speculatable from {s,u}mul.fix (PR #141748)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 28 05:15:27 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Luke Lau (lukel97)
<details>
<summary>Changes</summary>
I noticed this when looking at the list of functions in isTriviallyVectorizable, and seeing if any of them had UB.
According to the LangRef, smul.fix and umul.fix have UB if the result overflows, but both intrinsics are marked as speculatable.
This removes the attribute which fixes the smul.fix of %x being hoisted out of the select. E.g. if %b = true and %x = 0xffffffff, then we went from no UB to UB.
umul.fix wasn't affected because it wasn't handled yet in InstructionSimplify
---
Full diff: https://github.com/llvm/llvm-project/pull/141748.diff
2 Files Affected:
- (modified) llvm/include/llvm/IR/Intrinsics.td (+2-4)
- (added) llvm/test/Transforms/InstCombine/select-mul-fix.ll (+28)
``````````diff
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index d3899056bc240..8cdf11ffd872b 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -1581,13 +1581,11 @@ def int_ushl_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty],
//
def int_smul_fix : DefaultAttrsIntrinsic<[llvm_anyint_ty],
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty],
- [IntrNoMem, IntrSpeculatable,
- Commutative, ImmArg<ArgIndex<2>>]>;
+ [IntrNoMem, Commutative, ImmArg<ArgIndex<2>>]>;
def int_umul_fix : DefaultAttrsIntrinsic<[llvm_anyint_ty],
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty],
- [IntrNoMem, IntrSpeculatable,
- Commutative, ImmArg<ArgIndex<2>>]>;
+ [IntrNoMem, Commutative, ImmArg<ArgIndex<2>>]>;
def int_sdiv_fix : DefaultAttrsIntrinsic<[llvm_anyint_ty],
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty],
diff --git a/llvm/test/Transforms/InstCombine/select-mul-fix.ll b/llvm/test/Transforms/InstCombine/select-mul-fix.ll
new file mode 100644
index 0000000000000..1545dc6f7d6df
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/select-mul-fix.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -p instcombine -S < %s | FileCheck %s
+
+; Don't fold these intrinsics into the select as they're not speculatable.
+
+define i32 @smul(i1 %b, i32 %x) {
+; CHECK-LABEL: define i32 @smul(
+; CHECK-SAME: i1 [[B:%.*]], i32 [[X:%.*]]) {
+; CHECK-NEXT: [[S:%.*]] = select i1 [[B]], i32 0, i32 [[X]]
+; CHECK-NEXT: [[C:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[S]], i32 42, i32 1)
+; CHECK-NEXT: ret i32 [[C]]
+;
+ %s = select i1 %b, i32 0, i32 %x
+ %c = call i32 @llvm.smul.fix(i32 %s, i32 42, i32 1)
+ ret i32 %c
+}
+
+define i32 @umul(i1 %b, i32 %x) {
+; CHECK-LABEL: define i32 @umul(
+; CHECK-SAME: i1 [[B:%.*]], i32 [[X:%.*]]) {
+; CHECK-NEXT: [[S:%.*]] = select i1 [[B]], i32 0, i32 [[X]]
+; CHECK-NEXT: [[C:%.*]] = call i32 @llvm.umul.fix.i32(i32 [[S]], i32 42, i32 1)
+; CHECK-NEXT: ret i32 [[C]]
+;
+ %s = select i1 %b, i32 0, i32 %x
+ %c = call i32 @llvm.umul.fix(i32 %s, i32 42, i32 1)
+ ret i32 %c
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/141748
More information about the llvm-commits
mailing list