[SDAG] freeze operand when expanging urem
authorSanjay Patel <spatel@rotateright.com>
Fri, 13 May 2022 14:30:58 +0000 (10:30 -0400)
committerSanjay Patel <spatel@rotateright.com>
Fri, 13 May 2022 14:55:14 +0000 (10:55 -0400)
This is a potential miscompile as discussed in issue #55291.

The related IR transform was patched with:
d428f09b2c9d49f6a32

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/test/CodeGen/X86/combine-urem.ll

index 5102c1b..f56012d 100644 (file)
@@ -4532,10 +4532,13 @@ SDValue DAGCombiner::visitREM(SDNode *N) {
   if (SDValue C = DAG.FoldConstantArithmetic(Opcode, DL, VT, {N0, N1}))
     return C;
 
-  // fold (urem X, -1) -> select(X == -1, 0, x)
-  if (!isSigned && N1C && N1C->isAllOnes())
-    return DAG.getSelect(DL, VT, DAG.getSetCC(DL, CCVT, N0, N1, ISD::SETEQ),
-                         DAG.getConstant(0, DL, VT), N0);
+  // fold (urem X, -1) -> select(FX == -1, 0, FX)
+  // Freeze the numerator to avoid a miscompile with an undefined value.
+  if (!isSigned && N1C && N1C->isAllOnes()) {
+    SDValue F0 = DAG.getFreeze(N0);
+    SDValue EqualsNeg1 = DAG.getSetCC(DL, CCVT, F0, N1, ISD::SETEQ);
+    return DAG.getSelect(DL, VT, EqualsNeg1, DAG.getConstant(0, DL, VT), F0);
+  }
 
   if (SDValue V = simplifyDivRem(N, DAG))
     return V;
index 5c13315..def64fe 100644 (file)
@@ -63,12 +63,16 @@ define <4 x i32> @combine_vec_urem_by_negone(<4 x i32> %x) {
 define <4 x i32> @combine_vec_urem_undef_by_negone(<4 x i32> %in) {
 ; SSE-LABEL: combine_vec_urem_undef_by_negone:
 ; SSE:       # %bb.0:
-; SSE-NEXT:    xorps %xmm0, %xmm0
+; SSE-NEXT:    pcmpeqd %xmm0, %xmm0
+; SSE-NEXT:    pcmpeqd %xmm0, %xmm0
+; SSE-NEXT:    pandn %xmm0, %xmm0
 ; SSE-NEXT:    retq
 ;
 ; AVX-LABEL: combine_vec_urem_undef_by_negone:
 ; AVX:       # %bb.0:
-; AVX-NEXT:    vxorps %xmm0, %xmm0, %xmm0
+; AVX-NEXT:    vpcmpeqd %xmm0, %xmm0, %xmm0
+; AVX-NEXT:    vpcmpeqd %xmm0, %xmm0, %xmm0
+; AVX-NEXT:    vpandn %xmm0, %xmm0, %xmm0
 ; AVX-NEXT:    retq
   %x = call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> undef, i32 0)
   %y = urem <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>