[llvm] [msan] handle llvm.masked.{udiv, sdiv, urem, srem} intrinsics (PR #225363)
Emilio Cota via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 01:21:18 PDT 2026
https://github.com/cota updated https://github.com/llvm/llvm-project/pull/225363
>From 4bffab46b183d01a60c1a0cf0cc7f890c9ce7033 Mon Sep 17 00:00:00 2001
From: Emilio Cota <ecg at google.com>
Date: Tue, 22 Sep 2026 10:30:08 +0000
Subject: [PATCH] [msan] handle llvm.masked.{udiv,sdiv,urem,srem} intrinsics
Check the divisor and propagate the dividend's shadow on active lanes,
poisoning disabled result lanes. This poisoning is consistent with
the definition of these intrinsics; see #189705 (9ba774566).
This gets rid of false positives from inactive input lanes since
visitInstruction() was checking every operand across all lanes,
active or not.
Depends on: #227462
---
.../Instrumentation/MemorySanitizer.cpp | 37 ++++
.../MemorySanitizer/masked-divrem.ll | 174 +++++++++---------
2 files changed, 121 insertions(+), 90 deletions(-)
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 214262a95e41a8..96a84e75a854cb 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -4630,6 +4630,37 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
setOrigin(&I, Origin);
}
+ // e.g., <4 x i32> @llvm.masked.udiv.v4i32(<4 x i32> %dividend,
+ // <4 x i32> %divisor,
+ // <4 x i1> %mask)
+ //
+ // As handleIntegerDiv(), but per-lane: strict on the divisor and propagating
+ // the dividend, both only on the enabled lanes. Disabled lanes cannot cause
+ // undefined behaviour, and their result is poison.
+ void handleMaskedIntegerDivRem(IntrinsicInst &I) {
+ assert(I.arg_size() == 3);
+ IRBuilder<> IRB(&I);
+ Value *Dividend = I.getArgOperand(0);
+ Value *Divisor = I.getArgOperand(1);
+ Value *Mask = I.getArgOperand(2);
+
+ insertCheckShadowOf(Mask, &I);
+
+ Value *MaskedDivisorShadow = IRB.CreateSelect(
+ Mask, getShadow(Divisor), getCleanShadow(Divisor), "_msmaskeddivisor");
+ insertCheckShadow(MaskedDivisorShadow, getOrigin(Divisor), &I);
+
+ if (!PropagateShadow) {
+ setShadow(&I, getCleanShadow(&I));
+ setOrigin(&I, getCleanOrigin());
+ return;
+ }
+
+ setShadow(&I, IRB.CreateSelect(Mask, getShadow(Dividend),
+ getPoisonedShadow(&I), "_msmaskeddiv"));
+ setOrigin(&I, getOrigin(Dividend));
+ }
+
// e.g., void @llvm.x86.avx.maskstore.ps.256(ptr, <8 x i32>, <8 x float>)
// dst mask src
//
@@ -5936,6 +5967,12 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
case Intrinsic::masked_load:
handleMaskedLoad(I);
break;
+ case Intrinsic::masked_udiv:
+ case Intrinsic::masked_sdiv:
+ case Intrinsic::masked_urem:
+ case Intrinsic::masked_srem:
+ handleMaskedIntegerDivRem(I);
+ break;
case Intrinsic::vector_reduce_and:
handleVectorReduceAndIntrinsic(I);
break;
diff --git a/llvm/test/Instrumentation/MemorySanitizer/masked-divrem.ll b/llvm/test/Instrumentation/MemorySanitizer/masked-divrem.ll
index 32773dd3808e67..5fac18ab75a180 100644
--- a/llvm/test/Instrumentation/MemorySanitizer/masked-divrem.ll
+++ b/llvm/test/Instrumentation/MemorySanitizer/masked-divrem.ll
@@ -7,25 +7,24 @@ target triple = "x86_64-unknown-linux-gnu"
define <4 x i32> @masked_udiv(<4 x i32> %x, <4 x i32> %y, <4 x i1> %m) sanitize_memory {
; CHECK-LABEL: @masked_udiv(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
+; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i1>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 32), align 8
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 16), align 8
-; CHECK-NEXT: [[TMP3:%.*]] = load <4 x i1>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 32), align 8
+; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP2]] to i128
+; CHECK-NEXT: [[_MSMASKEDDIVISOR:%.*]] = select <4 x i1> [[M:%.*]], <4 x i32> [[TMP1]], <4 x i32> zeroinitializer
+; CHECK-NEXT: [[_MSMASKEDDIV:%.*]] = select <4 x i1> [[M]], <4 x i32> [[TMP2]], <4 x i32> splat (i32 -1)
+; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i1> [[TMP0]] to i4
+; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i4 [[TMP3]], 0
+; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[_MSMASKEDDIVISOR]] to i128
; CHECK-NEXT: [[_MSCMP1:%.*]] = icmp ne i128 [[TMP4]], 0
-; CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP1]] to i128
-; CHECK-NEXT: [[_MSCMP3:%.*]] = icmp ne i128 [[TMP8]], 0
-; CHECK-NEXT: [[_MSOR:%.*]] = or i1 [[_MSCMP1]], [[_MSCMP3]]
-; CHECK-NEXT: [[TMP5:%.*]] = bitcast <4 x i1> [[TMP3]] to i4
-; CHECK-NEXT: [[_MSCMP2:%.*]] = icmp ne i4 [[TMP5]], 0
-; CHECK-NEXT: [[_MSOR3:%.*]] = or i1 [[_MSOR]], [[_MSCMP2]]
-; CHECK-NEXT: br i1 [[_MSOR3]], label [[TMP6:%.*]], label [[TMP7:%.*]], !prof [[PROF1:![0-9]+]]
-; CHECK: 6:
+; CHECK-NEXT: [[_MSOR:%.*]] = or i1 [[_MSCMP]], [[_MSCMP1]]
+; CHECK-NEXT: br i1 [[_MSOR]], label [[TMP5:%.*]], label [[TMP6:%.*]], !prof [[PROF1:![0-9]+]]
+; CHECK: 5:
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5:[0-9]+]]
; CHECK-NEXT: unreachable
-; CHECK: 7:
-; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.udiv.v4i32(<4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i1> [[M:%.*]])
-; CHECK-NEXT: store <4 x i32> zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK: 6:
+; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.udiv.v4i32(<4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i1> [[M]])
+; CHECK-NEXT: store <4 x i32> [[_MSMASKEDDIV]], ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <4 x i32> [[RES]]
;
entry:
@@ -36,25 +35,24 @@ entry:
define <4 x i32> @masked_sdiv(<4 x i32> %x, <4 x i32> %y, <4 x i1> %m) sanitize_memory {
; CHECK-LABEL: @masked_sdiv(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
+; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i1>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 32), align 8
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 16), align 8
-; CHECK-NEXT: [[TMP3:%.*]] = load <4 x i1>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 32), align 8
+; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP2]] to i128
+; CHECK-NEXT: [[_MSMASKEDDIVISOR:%.*]] = select <4 x i1> [[M:%.*]], <4 x i32> [[TMP1]], <4 x i32> zeroinitializer
+; CHECK-NEXT: [[_MSMASKEDDIV:%.*]] = select <4 x i1> [[M]], <4 x i32> [[TMP2]], <4 x i32> splat (i32 -1)
+; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i1> [[TMP0]] to i4
+; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i4 [[TMP3]], 0
+; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[_MSMASKEDDIVISOR]] to i128
; CHECK-NEXT: [[_MSCMP1:%.*]] = icmp ne i128 [[TMP4]], 0
-; CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP1]] to i128
-; CHECK-NEXT: [[_MSCMP3:%.*]] = icmp ne i128 [[TMP8]], 0
-; CHECK-NEXT: [[_MSOR:%.*]] = or i1 [[_MSCMP1]], [[_MSCMP3]]
-; CHECK-NEXT: [[TMP5:%.*]] = bitcast <4 x i1> [[TMP3]] to i4
-; CHECK-NEXT: [[_MSCMP2:%.*]] = icmp ne i4 [[TMP5]], 0
-; CHECK-NEXT: [[_MSOR3:%.*]] = or i1 [[_MSOR]], [[_MSCMP2]]
-; CHECK-NEXT: br i1 [[_MSOR3]], label [[TMP6:%.*]], label [[TMP7:%.*]], !prof [[PROF1]]
-; CHECK: 6:
+; CHECK-NEXT: [[_MSOR:%.*]] = or i1 [[_MSCMP]], [[_MSCMP1]]
+; CHECK-NEXT: br i1 [[_MSOR]], label [[TMP5:%.*]], label [[TMP6:%.*]], !prof [[PROF1]]
+; CHECK: 5:
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
; CHECK-NEXT: unreachable
-; CHECK: 7:
-; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.sdiv.v4i32(<4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i1> [[M:%.*]])
-; CHECK-NEXT: store <4 x i32> zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK: 6:
+; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.sdiv.v4i32(<4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i1> [[M]])
+; CHECK-NEXT: store <4 x i32> [[_MSMASKEDDIV]], ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <4 x i32> [[RES]]
;
entry:
@@ -65,25 +63,24 @@ entry:
define <4 x i32> @masked_urem(<4 x i32> %x, <4 x i32> %y, <4 x i1> %m) sanitize_memory {
; CHECK-LABEL: @masked_urem(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
+; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i1>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 32), align 8
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 16), align 8
-; CHECK-NEXT: [[TMP3:%.*]] = load <4 x i1>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 32), align 8
+; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP2]] to i128
+; CHECK-NEXT: [[_MSMASKEDDIVISOR:%.*]] = select <4 x i1> [[M:%.*]], <4 x i32> [[TMP1]], <4 x i32> zeroinitializer
+; CHECK-NEXT: [[_MSMASKEDDIV:%.*]] = select <4 x i1> [[M]], <4 x i32> [[TMP2]], <4 x i32> splat (i32 -1)
+; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i1> [[TMP0]] to i4
+; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i4 [[TMP3]], 0
+; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[_MSMASKEDDIVISOR]] to i128
; CHECK-NEXT: [[_MSCMP1:%.*]] = icmp ne i128 [[TMP4]], 0
-; CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP1]] to i128
-; CHECK-NEXT: [[_MSCMP3:%.*]] = icmp ne i128 [[TMP8]], 0
-; CHECK-NEXT: [[_MSOR:%.*]] = or i1 [[_MSCMP1]], [[_MSCMP3]]
-; CHECK-NEXT: [[TMP5:%.*]] = bitcast <4 x i1> [[TMP3]] to i4
-; CHECK-NEXT: [[_MSCMP2:%.*]] = icmp ne i4 [[TMP5]], 0
-; CHECK-NEXT: [[_MSOR3:%.*]] = or i1 [[_MSOR]], [[_MSCMP2]]
-; CHECK-NEXT: br i1 [[_MSOR3]], label [[TMP6:%.*]], label [[TMP7:%.*]], !prof [[PROF1]]
-; CHECK: 6:
+; CHECK-NEXT: [[_MSOR:%.*]] = or i1 [[_MSCMP]], [[_MSCMP1]]
+; CHECK-NEXT: br i1 [[_MSOR]], label [[TMP5:%.*]], label [[TMP6:%.*]], !prof [[PROF1]]
+; CHECK: 5:
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
; CHECK-NEXT: unreachable
-; CHECK: 7:
-; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.urem.v4i32(<4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i1> [[M:%.*]])
-; CHECK-NEXT: store <4 x i32> zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK: 6:
+; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.urem.v4i32(<4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i1> [[M]])
+; CHECK-NEXT: store <4 x i32> [[_MSMASKEDDIV]], ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <4 x i32> [[RES]]
;
entry:
@@ -94,25 +91,24 @@ entry:
define <4 x i32> @masked_srem(<4 x i32> %x, <4 x i32> %y, <4 x i1> %m) sanitize_memory {
; CHECK-LABEL: @masked_srem(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
+; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i1>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 32), align 8
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 16), align 8
-; CHECK-NEXT: [[TMP3:%.*]] = load <4 x i1>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 32), align 8
+; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[TMP2]] to i128
+; CHECK-NEXT: [[_MSMASKEDDIVISOR:%.*]] = select <4 x i1> [[M:%.*]], <4 x i32> [[TMP1]], <4 x i32> zeroinitializer
+; CHECK-NEXT: [[_MSMASKEDDIV:%.*]] = select <4 x i1> [[M]], <4 x i32> [[TMP2]], <4 x i32> splat (i32 -1)
+; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i1> [[TMP0]] to i4
+; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i4 [[TMP3]], 0
+; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[_MSMASKEDDIVISOR]] to i128
; CHECK-NEXT: [[_MSCMP1:%.*]] = icmp ne i128 [[TMP4]], 0
-; CHECK-NEXT: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP1]] to i128
-; CHECK-NEXT: [[_MSCMP3:%.*]] = icmp ne i128 [[TMP8]], 0
-; CHECK-NEXT: [[_MSOR:%.*]] = or i1 [[_MSCMP1]], [[_MSCMP3]]
-; CHECK-NEXT: [[TMP5:%.*]] = bitcast <4 x i1> [[TMP3]] to i4
-; CHECK-NEXT: [[_MSCMP2:%.*]] = icmp ne i4 [[TMP5]], 0
-; CHECK-NEXT: [[_MSOR3:%.*]] = or i1 [[_MSOR]], [[_MSCMP2]]
-; CHECK-NEXT: br i1 [[_MSOR3]], label [[TMP6:%.*]], label [[TMP7:%.*]], !prof [[PROF1]]
-; CHECK: 6:
+; CHECK-NEXT: [[_MSOR:%.*]] = or i1 [[_MSCMP]], [[_MSCMP1]]
+; CHECK-NEXT: br i1 [[_MSOR]], label [[TMP5:%.*]], label [[TMP6:%.*]], !prof [[PROF1]]
+; CHECK: 5:
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
; CHECK-NEXT: unreachable
-; CHECK: 7:
-; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.srem.v4i32(<4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i1> [[M:%.*]])
-; CHECK-NEXT: store <4 x i32> zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK: 6:
+; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.srem.v4i32(<4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i1> [[M]])
+; CHECK-NEXT: store <4 x i32> [[_MSMASKEDDIV]], ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <4 x i32> [[RES]]
;
entry:
@@ -150,18 +146,17 @@ define <4 x i32> @urem_masked_loads(ptr %pa, ptr %pb) sanitize_memory {
; CHECK-NEXT: unreachable
; CHECK: 11:
; CHECK-NEXT: [[B:%.*]] = call <4 x i32> @llvm.masked.load.v4i32.p0(ptr [[PB]], <4 x i1> <i1 true, i1 true, i1 true, i1 false>, <4 x i32> poison)
-; CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x i32> [[_MSMASKEDLD]] to i128
+; CHECK-NEXT: [[_MSMASKEDDIVISOR:%.*]] = select <4 x i1> <i1 true, i1 true, i1 true, i1 false>, <4 x i32> [[_MSMASKEDLD1]], <4 x i32> zeroinitializer
+; CHECK-NEXT: [[_MSMASKEDDIV:%.*]] = select <4 x i1> <i1 true, i1 true, i1 true, i1 false>, <4 x i32> [[_MSMASKEDLD]], <4 x i32> splat (i32 -1)
+; CHECK-NEXT: [[TMP6:%.*]] = bitcast <4 x i32> [[_MSMASKEDDIVISOR]] to i128
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP6]], 0
-; CHECK-NEXT: [[TMP13:%.*]] = bitcast <4 x i32> [[_MSMASKEDLD1]] to i128
-; CHECK-NEXT: [[_MSCMP4:%.*]] = icmp ne i128 [[TMP13]], 0
-; CHECK-NEXT: [[_MSOR:%.*]] = or i1 [[_MSCMP]], [[_MSCMP4]]
-; CHECK-NEXT: br i1 [[_MSOR]], label [[TMP14:%.*]], label [[TMP15:%.*]], !prof [[PROF1]]
-; CHECK: 14:
+; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP13:%.*]], label [[TMP14:%.*]], !prof [[PROF1]]
+; CHECK: 13:
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
; CHECK-NEXT: unreachable
-; CHECK: 15:
+; CHECK: 14:
; CHECK-NEXT: [[R:%.*]] = call <4 x i32> @llvm.masked.urem.v4i32(<4 x i32> [[A]], <4 x i32> [[B]], <4 x i1> <i1 true, i1 true, i1 true, i1 false>)
-; CHECK-NEXT: store <4 x i32> zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK-NEXT: store <4 x i32> [[_MSMASKEDDIV]], ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <4 x i32> [[R]]
;
entry:
@@ -178,7 +173,8 @@ define i1 @udiv_clean_dividend_poisons_disabled_lanes(<4 x i32> %b) sanitize_mem
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[TMP0]] to i128
+; CHECK-NEXT: [[_MSMASKEDDIVISOR:%.*]] = select <4 x i1> <i1 true, i1 true, i1 true, i1 false>, <4 x i32> [[TMP0]], <4 x i32> zeroinitializer
+; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[_MSMASKEDDIVISOR]] to i128
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP1]], 0
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP2:%.*]], label [[TMP3:%.*]], !prof [[PROF1]]
; CHECK: 2:
@@ -188,9 +184,9 @@ define i1 @udiv_clean_dividend_poisons_disabled_lanes(<4 x i32> %b) sanitize_mem
; CHECK-NEXT: [[R:%.*]] = call <4 x i32> @llvm.masked.udiv.v4i32(<4 x i32> splat (i32 100), <4 x i32> [[B:%.*]], <4 x i1> <i1 true, i1 true, i1 true, i1 false>)
; CHECK-NEXT: [[LANE3:%.*]] = extractelement <4 x i32> [[R]], i32 3
; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[LANE3]], 0
-; CHECK-NEXT: [[TMP5:%.*]] = and i32 -1, [[TMP4]]
+; CHECK-NEXT: [[TMP5:%.*]] = and i32 0, [[TMP4]]
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
-; CHECK-NEXT: [[_MSPROP_ICMP:%.*]] = and i1 false, [[TMP6]]
+; CHECK-NEXT: [[_MSPROP_ICMP:%.*]] = and i1 true, [[TMP6]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[LANE3]], 0
; CHECK-NEXT: br i1 [[_MSPROP_ICMP]], label [[TMP7:%.*]], label [[TMP8:%.*]], !prof [[PROF1]]
; CHECK: 7:
@@ -221,21 +217,20 @@ f:
define <4 x i32> @udiv_all_lanes_enabled(<4 x i32> %x, <4 x i32> %y) sanitize_memory {
; CHECK-LABEL: @udiv_all_lanes_enabled(
; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 16), align 8
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
-; CHECK-NEXT: [[TMP6:%.*]] = load <4 x i32>, ptr getelementptr (i8, ptr @__msan_param_tls, i64 16), align 8
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i32> [[TMP1]] to i128
+; CHECK-NEXT: [[_MSMASKEDDIVISOR:%.*]] = select <4 x i1> splat (i1 true), <4 x i32> [[TMP0]], <4 x i32> zeroinitializer
+; CHECK-NEXT: [[_MSMASKEDDIV:%.*]] = select <4 x i1> splat (i1 true), <4 x i32> [[TMP1]], <4 x i32> splat (i32 -1)
+; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i32> [[_MSMASKEDDIVISOR]] to i128
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
-; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i32> [[TMP6]] to i128
-; CHECK-NEXT: [[_MSCMP1:%.*]] = icmp ne i128 [[TMP3]], 0
-; CHECK-NEXT: [[_MSOR:%.*]] = or i1 [[_MSCMP]], [[_MSCMP1]]
-; CHECK-NEXT: br i1 [[_MSOR]], label [[TMP4:%.*]], label [[TMP5:%.*]], !prof [[PROF1]]
-; CHECK: 4:
+; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
+; CHECK: 3:
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
; CHECK-NEXT: unreachable
-; CHECK: 5:
+; CHECK: 4:
; CHECK-NEXT: [[R:%.*]] = call <4 x i32> @llvm.masked.udiv.v4i32(<4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i1> splat (i1 true))
-; CHECK-NEXT: store <4 x i32> zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK-NEXT: store <4 x i32> [[_MSMASKEDDIV]], ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <4 x i32> [[R]]
;
entry:
@@ -253,7 +248,7 @@ define void @masked_udiv_scalable(ptr %pa, ptr %pb, ptr %pr, <vscale x 4 x i1> %
; CHECK-NEXT: [[TMP13:%.*]] = load i64, ptr getelementptr (i8, ptr @__msan_param_tls, i64 16), align 8
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: [[_MSCMP1:%.*]] = icmp ne i64 [[TMP7]], 0
-; CHECK-NEXT: br i1 [[_MSCMP1]], label [[TMP19:%.*]], label [[TMP20:%.*]], !prof [[PROF1]]
+; CHECK-NEXT: br i1 [[_MSCMP1]], label [[TMP18:%.*]], label [[TMP19:%.*]], !prof [[PROF1]]
; CHECK: 3:
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
; CHECK-NEXT: unreachable
@@ -264,7 +259,7 @@ define void @masked_udiv_scalable(ptr %pa, ptr %pb, ptr %pr, <vscale x 4 x i1> %
; CHECK-NEXT: [[TMP2:%.*]] = inttoptr i64 [[TMP1]] to ptr
; CHECK-NEXT: [[_MSLD:%.*]] = load <vscale x 4 x i32>, ptr [[TMP2]], align 16
; CHECK-NEXT: [[_MSCMP2:%.*]] = icmp ne i64 [[TMP12]], 0
-; CHECK-NEXT: br i1 [[_MSCMP2]], label [[TMP8:%.*]], label [[TMP21:%.*]], !prof [[PROF1]]
+; CHECK-NEXT: br i1 [[_MSCMP2]], label [[TMP8:%.*]], label [[TMP20:%.*]], !prof [[PROF1]]
; CHECK: 8:
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
; CHECK-NEXT: unreachable
@@ -274,27 +269,26 @@ define void @masked_udiv_scalable(ptr %pa, ptr %pb, ptr %pr, <vscale x 4 x i1> %
; CHECK-NEXT: [[TMP4:%.*]] = xor i64 [[TMP3]], 87960930222080
; CHECK-NEXT: [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
; CHECK-NEXT: [[_MSLD1:%.*]] = load <vscale x 4 x i32>, ptr [[TMP5]], align 16
-; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.nxv4i32(<vscale x 4 x i32> [[_MSLD]])
+; CHECK-NEXT: [[_MSMASKEDDIVISOR:%.*]] = select <vscale x 4 x i1> [[M:%.*]], <vscale x 4 x i32> [[_MSLD1]], <vscale x 4 x i32> zeroinitializer
+; CHECK-NEXT: [[_MSMASKEDDIV:%.*]] = select <vscale x 4 x i1> [[M]], <vscale x 4 x i32> [[_MSLD]], <vscale x 4 x i32> splat (i32 -1)
+; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.nxv4i32(<vscale x 4 x i32> [[_MSMASKEDDIVISOR]])
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i32 [[TMP6]], 0
-; CHECK-NEXT: [[TMP14:%.*]] = call i32 @llvm.vector.reduce.or.nxv4i32(<vscale x 4 x i32> [[_MSLD1]])
-; CHECK-NEXT: [[_MSCMP5:%.*]] = icmp ne i32 [[TMP14]], 0
-; CHECK-NEXT: [[_MSOR:%.*]] = or i1 [[_MSCMP]], [[_MSCMP5]]
-; CHECK-NEXT: br i1 [[_MSOR]], label [[TMP15:%.*]], label [[TMP16:%.*]], !prof [[PROF1]]
-; CHECK: 15:
+; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP14:%.*]], label [[TMP15:%.*]], !prof [[PROF1]]
+; CHECK: 14:
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
; CHECK-NEXT: unreachable
-; CHECK: 16:
-; CHECK-NEXT: [[R:%.*]] = call <vscale x 4 x i32> @llvm.masked.udiv.nxv4i32(<vscale x 4 x i32> [[A]], <vscale x 4 x i32> [[B]], <vscale x 4 x i1> [[M:%.*]])
+; CHECK: 15:
+; CHECK-NEXT: [[R:%.*]] = call <vscale x 4 x i32> @llvm.masked.udiv.nxv4i32(<vscale x 4 x i32> [[A]], <vscale x 4 x i32> [[B]], <vscale x 4 x i1> [[M]])
; CHECK-NEXT: [[_MSCMP4:%.*]] = icmp ne i64 [[TMP13]], 0
-; CHECK-NEXT: br i1 [[_MSCMP4]], label [[TMP17:%.*]], label [[TMP18:%.*]], !prof [[PROF1]]
-; CHECK: 17:
+; CHECK-NEXT: br i1 [[_MSCMP4]], label [[TMP16:%.*]], label [[TMP17:%.*]], !prof [[PROF1]]
+; CHECK: 16:
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
; CHECK-NEXT: unreachable
-; CHECK: 18:
+; CHECK: 17:
; CHECK-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[PR:%.*]] to i64
; CHECK-NEXT: [[TMP10:%.*]] = xor i64 [[TMP9]], 87960930222080
; CHECK-NEXT: [[TMP11:%.*]] = inttoptr i64 [[TMP10]] to ptr
-; CHECK-NEXT: store <vscale x 4 x i32> zeroinitializer, ptr [[TMP11]], align 16
+; CHECK-NEXT: store <vscale x 4 x i32> [[_MSMASKEDDIV]], ptr [[TMP11]], align 16
; CHECK-NEXT: store <vscale x 4 x i32> [[R]], ptr [[PR]], align 16
; CHECK-NEXT: ret void
;
More information about the llvm-commits
mailing list