Skip to content

Commit f052064

Browse files
committed
[DAGCombiner] Fix the "subtraction if above a constant threshold" miscompile
This fixes llvm#135194 incorrectly reusing the existing `add nuw/nsw` while the transformed code relies on an unsigned wrap.
1 parent fd9fa66 commit f052064

File tree

3 files changed

+22
-5
lines changed

3 files changed

+22
-5
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12140,11 +12140,16 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) {
1214012140
// (select (ult x, C), x, (add x, -C)) -> (umin x, (add x, -C))
1214112141
APInt C;
1214212142
if (sd_match(Cond1, m_ConstInt(C)) && hasUMin(VT)) {
12143-
if ((CC == ISD::SETUGT && Cond0 == N2 &&
12144-
sd_match(N1, m_Add(m_Specific(N2), m_SpecificInt(~C)))) ||
12145-
(CC == ISD::SETULT && Cond0 == N1 &&
12146-
sd_match(N2, m_Add(m_Specific(N1), m_SpecificInt(-C)))))
12147-
return DAG.getNode(ISD::UMIN, DL, VT, N1, N2);
12143+
if (CC == ISD::SETUGT && Cond0 == N2 &&
12144+
sd_match(N1, m_Add(m_Specific(N2), m_SpecificInt(~C))))
12145+
return DAG.getNode(
12146+
ISD::UMIN, DL, VT,
12147+
DAG.getNode(ISD::ADD, DL, VT, N2, DAG.getConstant(~C, DL, VT)), N2);
12148+
if (CC == ISD::SETULT && Cond0 == N1 &&
12149+
sd_match(N2, m_Add(m_Specific(N1), m_SpecificInt(-C))))
12150+
return DAG.getNode(
12151+
ISD::UMIN, DL, VT, N1,
12152+
DAG.getNode(ISD::ADD, DL, VT, N1, DAG.getConstant(-C, DL, VT)));
1214812153
}
1214912154
}
1215012155

llvm/test/CodeGen/RISCV/rv32zbb.ll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,7 +1932,10 @@ define i7 @sub_if_uge_C_nsw_i7(i7 %a) {
19321932
; RV32ZBB-LABEL: sub_if_uge_C_nsw_i7:
19331933
; RV32ZBB: # %bb.0:
19341934
; RV32ZBB-NEXT: ori a0, a0, 51
1935+
; RV32ZBB-NEXT: andi a1, a0, 127
19351936
; RV32ZBB-NEXT: addi a0, a0, 17
1937+
; RV32ZBB-NEXT: andi a0, a0, 92
1938+
; RV32ZBB-NEXT: minu a0, a0, a1
19361939
; RV32ZBB-NEXT: ret
19371940
%x = or i7 %a, 51
19381941
%c = icmp ugt i7 %x, -18
@@ -1955,7 +1958,10 @@ define i7 @sub_if_uge_C_swapped_nsw_i7(i7 %a) {
19551958
; RV32ZBB-LABEL: sub_if_uge_C_swapped_nsw_i7:
19561959
; RV32ZBB: # %bb.0:
19571960
; RV32ZBB-NEXT: ori a0, a0, 51
1961+
; RV32ZBB-NEXT: andi a1, a0, 127
19581962
; RV32ZBB-NEXT: addi a0, a0, 17
1963+
; RV32ZBB-NEXT: andi a0, a0, 92
1964+
; RV32ZBB-NEXT: minu a0, a1, a0
19591965
; RV32ZBB-NEXT: ret
19601966
%x = or i7 %a, 51
19611967
%c = icmp ult i7 %x, -17

llvm/test/CodeGen/RISCV/rv64zbb.ll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,7 +2087,10 @@ define i7 @sub_if_uge_C_nsw_i7(i7 %a) {
20872087
; RV64ZBB-LABEL: sub_if_uge_C_nsw_i7:
20882088
; RV64ZBB: # %bb.0:
20892089
; RV64ZBB-NEXT: ori a0, a0, 51
2090+
; RV64ZBB-NEXT: andi a1, a0, 127
20902091
; RV64ZBB-NEXT: addi a0, a0, 17
2092+
; RV64ZBB-NEXT: andi a0, a0, 92
2093+
; RV64ZBB-NEXT: minu a0, a0, a1
20912094
; RV64ZBB-NEXT: ret
20922095
%x = or i7 %a, 51
20932096
%c = icmp ugt i7 %x, -18
@@ -2110,7 +2113,10 @@ define i7 @sub_if_uge_C_swapped_nsw_i7(i7 %a) {
21102113
; RV64ZBB-LABEL: sub_if_uge_C_swapped_nsw_i7:
21112114
; RV64ZBB: # %bb.0:
21122115
; RV64ZBB-NEXT: ori a0, a0, 51
2116+
; RV64ZBB-NEXT: andi a1, a0, 127
21132117
; RV64ZBB-NEXT: addi a0, a0, 17
2118+
; RV64ZBB-NEXT: andi a0, a0, 92
2119+
; RV64ZBB-NEXT: minu a0, a1, a0
21142120
; RV64ZBB-NEXT: ret
21152121
%x = or i7 %a, 51
21162122
%c = icmp ult i7 %x, -17

0 commit comments

Comments
 (0)