Skip to content

Commit 571fe74

Browse files
paulwalker-armkrishna2803
authored andcommitted
[LLVM][SelectionDAG] Align poison/undef binop folds with IR. (llvm#149334)
The "at construction" binop folds in SelectionDAG::getNode() has different behaviour when compared to the equivalent LLVM IR. This PR makes the behaviour consistent while also extending the coverage to include signed/unsigned max/min operations.
1 parent 798288d commit 571fe74

19 files changed

+1588
-1325
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7843,69 +7843,110 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
78437843
}
78447844
}
78457845

7846-
// Perform trivial constant folding.
7847-
if (SDValue SV = FoldConstantArithmetic(Opcode, DL, VT, {N1, N2}, Flags))
7848-
return SV;
7846+
if (N1.getOpcode() == ISD::POISON || N2.getOpcode() == ISD::POISON) {
7847+
switch (Opcode) {
7848+
case ISD::XOR:
7849+
case ISD::ADD:
7850+
case ISD::PTRADD:
7851+
case ISD::SUB:
7852+
case ISD::SIGN_EXTEND_INREG:
7853+
case ISD::UDIV:
7854+
case ISD::SDIV:
7855+
case ISD::UREM:
7856+
case ISD::SREM:
7857+
case ISD::MUL:
7858+
case ISD::AND:
7859+
case ISD::SSUBSAT:
7860+
case ISD::USUBSAT:
7861+
case ISD::UMIN:
7862+
case ISD::OR:
7863+
case ISD::SADDSAT:
7864+
case ISD::UADDSAT:
7865+
case ISD::UMAX:
7866+
case ISD::SMAX:
7867+
case ISD::SMIN:
7868+
// fold op(arg1, poison) -> poison, fold op(poison, arg2) -> poison.
7869+
return N2.getOpcode() == ISD::POISON ? N2 : N1;
7870+
}
7871+
}
78497872

78507873
// Canonicalize an UNDEF to the RHS, even over a constant.
7851-
if (N1.isUndef()) {
7874+
if (N1.getOpcode() == ISD::UNDEF && N2.getOpcode() != ISD::UNDEF) {
78527875
if (TLI->isCommutativeBinOp(Opcode)) {
78537876
std::swap(N1, N2);
78547877
} else {
78557878
switch (Opcode) {
78567879
case ISD::PTRADD:
78577880
case ISD::SUB:
7858-
// fold op(undef, arg2) -> undef, fold op(poison, arg2) ->poison.
7859-
return N1.getOpcode() == ISD::POISON ? getPOISON(VT) : getUNDEF(VT);
7881+
// fold op(undef, non_undef_arg2) -> undef.
7882+
return N1;
78607883
case ISD::SIGN_EXTEND_INREG:
78617884
case ISD::UDIV:
78627885
case ISD::SDIV:
78637886
case ISD::UREM:
78647887
case ISD::SREM:
78657888
case ISD::SSUBSAT:
78667889
case ISD::USUBSAT:
7867-
// fold op(undef, arg2) -> 0, fold op(poison, arg2) -> poison.
7868-
return N1.getOpcode() == ISD::POISON ? getPOISON(VT)
7869-
: getConstant(0, DL, VT);
7890+
// fold op(undef, non_undef_arg2) -> 0.
7891+
return getConstant(0, DL, VT);
78707892
}
78717893
}
78727894
}
78737895

78747896
// Fold a bunch of operators when the RHS is undef.
7875-
if (N2.isUndef()) {
7897+
if (N2.getOpcode() == ISD::UNDEF) {
78767898
switch (Opcode) {
78777899
case ISD::XOR:
7878-
if (N1.isUndef())
7900+
if (N1.getOpcode() == ISD::UNDEF)
78797901
// Handle undef ^ undef -> 0 special case. This is a common
78807902
// idiom (misuse).
78817903
return getConstant(0, DL, VT);
78827904
[[fallthrough]];
78837905
case ISD::ADD:
78847906
case ISD::PTRADD:
78857907
case ISD::SUB:
7908+
// fold op(arg1, undef) -> undef.
7909+
return N2;
78867910
case ISD::UDIV:
78877911
case ISD::SDIV:
78887912
case ISD::UREM:
78897913
case ISD::SREM:
7890-
// fold op(arg1, undef) -> undef, fold op(arg1, poison) -> poison.
7891-
return N2.getOpcode() == ISD::POISON ? getPOISON(VT) : getUNDEF(VT);
7914+
// fold op(arg1, undef) -> poison.
7915+
return getPOISON(VT);
78927916
case ISD::MUL:
78937917
case ISD::AND:
78947918
case ISD::SSUBSAT:
78957919
case ISD::USUBSAT:
7896-
// fold op(arg1, undef) -> 0, fold op(arg1, poison) -> poison.
7897-
return N2.getOpcode() == ISD::POISON ? getPOISON(VT)
7898-
: getConstant(0, DL, VT);
7920+
case ISD::UMIN:
7921+
// fold op(undef, undef) -> undef, fold op(arg1, undef) -> 0.
7922+
return N1.getOpcode() == ISD::UNDEF ? N2 : getConstant(0, DL, VT);
78997923
case ISD::OR:
79007924
case ISD::SADDSAT:
79017925
case ISD::UADDSAT:
7902-
// fold op(arg1, undef) -> an all-ones constant, fold op(arg1, poison) ->
7903-
// poison.
7904-
return N2.getOpcode() == ISD::POISON ? getPOISON(VT)
7905-
: getAllOnesConstant(DL, VT);
7926+
case ISD::UMAX:
7927+
// fold op(undef, undef) -> undef, fold op(arg1, undef) -> -1.
7928+
return N1.getOpcode() == ISD::UNDEF ? N2 : getAllOnesConstant(DL, VT);
7929+
case ISD::SMAX:
7930+
// fold op(undef, undef) -> undef, fold op(arg1, undef) -> MAX_INT.
7931+
return N1.getOpcode() == ISD::UNDEF
7932+
? N2
7933+
: getConstant(
7934+
APInt::getSignedMaxValue(VT.getScalarSizeInBits()), DL,
7935+
VT);
7936+
case ISD::SMIN:
7937+
// fold op(undef, undef) -> undef, fold op(arg1, undef) -> MIN_INT.
7938+
return N1.getOpcode() == ISD::UNDEF
7939+
? N2
7940+
: getConstant(
7941+
APInt::getSignedMinValue(VT.getScalarSizeInBits()), DL,
7942+
VT);
79067943
}
79077944
}
79087945

7946+
// Perform trivial constant folding.
7947+
if (SDValue SV = FoldConstantArithmetic(Opcode, DL, VT, {N1, N2}, Flags))
7948+
return SV;
7949+
79097950
// Memoize this node if possible.
79107951
SDNode *N;
79117952
SDVTList VTs = getVTList(VT);

llvm/test/CodeGen/AArch64/combine-and-like.ll

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
define i32 @f(i32 %a0) {
55
; CHECK-LABEL: f:
66
; CHECK: // %bb.0:
7-
; CHECK-NEXT: mov w0, wzr
87
; CHECK-NEXT: ret
98
%1 = lshr i32 %a0, 2147483647
109
%2 = add i32 %1, 2147483647

llvm/test/CodeGen/AMDGPU/saddsat.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ define <3 x i16> @v_saddsat_v3i16(<3 x i16> %lhs, <3 x i16> %rhs) {
235235
; GFX6-NEXT: v_and_b32_e32 v0, 0xffff, v0
236236
; GFX6-NEXT: v_med3_i32 v3, v2, s4, v4
237237
; GFX6-NEXT: v_or_b32_e32 v0, v0, v1
238-
; GFX6-NEXT: v_or_b32_e32 v2, 0xffff0000, v3
238+
; GFX6-NEXT: v_and_b32_e32 v2, 0xffff, v3
239239
; GFX6-NEXT: v_alignbit_b32 v1, v3, v1, 16
240240
; GFX6-NEXT: s_setpc_b64 s[30:31]
241241
;

llvm/test/CodeGen/AMDGPU/uaddsat.ll

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,9 @@ define <3 x i16> @v_uaddsat_v3i16(<3 x i16> %lhs, <3 x i16> %rhs) {
202202
; GFX6-NEXT: v_add_i32_e32 v2, vcc, v2, v5
203203
; GFX6-NEXT: v_min_u32_e32 v0, 0xffff, v0
204204
; GFX6-NEXT: v_lshlrev_b32_e32 v1, 16, v1
205-
; GFX6-NEXT: v_min_u32_e32 v3, 0xffff, v2
205+
; GFX6-NEXT: v_min_u32_e32 v2, 0xffff, v2
206206
; GFX6-NEXT: v_or_b32_e32 v0, v0, v1
207-
; GFX6-NEXT: v_or_b32_e32 v2, 0xffff0000, v3
208-
; GFX6-NEXT: v_alignbit_b32 v1, v3, v1, 16
207+
; GFX6-NEXT: v_alignbit_b32 v1, v2, v1, 16
209208
; GFX6-NEXT: s_setpc_b64 s[30:31]
210209
;
211210
; GFX8-LABEL: v_uaddsat_v3i16:

0 commit comments

Comments
 (0)