[llvm] [IR] Remove speculatable from {s,u}mul.fix (PR #141748)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Wed May 28 05:14:57 PDT 2025
https://github.com/lukel97 created https://github.com/llvm/llvm-project/pull/141748
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
>From 3e7635db1e3ec15b97fa66c6b5d80d8dd43aa95a Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 28 May 2025 13:01:07 +0100
Subject: [PATCH 1/2] Precommit tests
---
.../Transforms/InstCombine/select-mul-fix.ll | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100644 llvm/test/Transforms/InstCombine/select-mul-fix.ll
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..db4532cd6aa32
--- /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: [[TMP1:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[X]], i32 42, i32 1)
+; CHECK-NEXT: [[C:%.*]] = select i1 [[B]], i32 0, i32 [[TMP1]]
+; 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
+}
>From be7586516022fbb963bdde8d4213aaced90ec852 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 28 May 2025 13:07:33 +0100
Subject: [PATCH 2/2] [IR] Remove speculatable from {s,u}mul.fix
I noticed this when looking at the list of functions in isTriviallyVectorizable, and 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
---
llvm/include/llvm/IR/Intrinsics.td | 6 ++----
llvm/test/Transforms/InstCombine/select-mul-fix.ll | 4 ++--
2 files changed, 4 insertions(+), 6 deletions(-)
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
index db4532cd6aa32..1545dc6f7d6df 100644
--- a/llvm/test/Transforms/InstCombine/select-mul-fix.ll
+++ b/llvm/test/Transforms/InstCombine/select-mul-fix.ll
@@ -6,8 +6,8 @@
define i32 @smul(i1 %b, i32 %x) {
; CHECK-LABEL: define i32 @smul(
; CHECK-SAME: i1 [[B:%.*]], i32 [[X:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[X]], i32 42, i32 1)
-; CHECK-NEXT: [[C:%.*]] = select i1 [[B]], i32 0, i32 [[TMP1]]
+; 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
More information about the llvm-commits
mailing list