8000 [DAGCombiner] Fix a "subtraction if above a constant threshold" misco… · llvm/llvm-project@9e22f96 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9e22f96

Browse files
authored
[DAGCombiner] Fix a "subtraction if above a constant threshold" miscompile (#140042)
This fixes #135194 incorrectly reusing the existing `add nuw/nsw` while the transformed code relies on an unsigned wrap.
1 parent 3fcfce4 commit 9e22f96

File tree

3 files changed

+119
-5
lines changed

3 files changed

+119
-5
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

+15-5
Original file line numberDiff line numberDiff line change
@@ -12156,11 +12156,21 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) {
1215612156
// (select (ult x, C), x, (add x, -C)) -> (umin x, (add x, -C))
1215712157
APInt C;
1215812158
if (sd_match(Cond1, m_ConstInt(C)) && hasUMin(VT)) {
12159-
if ((CC == ISD::SETUGT && Cond0 == N2 &&
12160-
sd_match(N1, m_Add(m_Specific(N2), m_SpecificInt(~C)))) ||
12161-
(CC == ISD::SETULT && Cond0 == N1 &&
12162-
sd_match(N2, m_Add(m_Specific(N1), m_SpecificInt(-C)))))
12163-
return DAG.getNode(ISD::UMIN, DL, VT, N1, N2);
12159+
if (CC == ISD::SETUGT && Cond0 == N2 &&
12160+
sd_match(N1, m_Add(m_Specific(N2), m_SpecificInt(~C)))) {
12161+
// The resulting code relies on an unsigned wrap in ADD.
12162+
// Recreating ADD to drop possible nuw/nsw flags.
12163+
SDValue AddC = DAG.getConstant(~C, DL, VT);
12164+
SDValue Add = DAG.getNode(ISD::ADD, DL, VT, N2, AddC);
12165+
return DAG.getNode(ISD::UMIN, DL, VT, Add, N2);
12166+
}
12167+
if (CC == ISD::SETULT && Cond0 == N1 &&
12168+
sd_match(N2, m_Add(m_Specific(N1), m_SpecificInt(-C)))) {
12169+
// Ditto.
12170+
SDValue AddC = DAG.getConstant(-C, DL, VT);
12171+
SDValue Add = DAG.getNode(ISD::ADD, DL, VT, N1, AddC);
12172+
return DAG.getNode(ISD::UMIN, DL, VT, N1, Add);
12173+
}
1216412174
}
1216512175
}
1216612176

llvm/test/CodeGen/RISCV/rv32zbb.ll

+52
Original file line numberDiff line numberDiff line change
@@ -1917,3 +1917,55 @@ define i32 @sub_if_uge_C_swapped_i32(i32 %x) {
19171917
%cond = select i1 %cmp, i32 %x, i32 %sub
19181918
ret i32 %cond
19191919
}
1920+
1921+
define i7 @sub_if_uge_C_nsw_i7(i7 %a) {
1922+
; RV32I-LABEL: sub_if_uge_C_nsw_i7:
1923+
; RV32I: # %bb.0:
1924+
; RV32I-NEXT: ori a0, a0, 51
1925+
; RV32I-NEXT: andi a1, a0, 127
1926+
; RV32I-NEXT: sltiu a1, a1, 111
1927+
; RV32I-NEXT: addi a1, a1, -1
1928+
; RV32I-NEXT: andi a1, a1, 17
1929+
; RV32I-NEXT: add a0, a0, a1
1930+
; RV32I-NEXT: ret
1931+
;
1932+
; RV32ZBB-LABEL: sub_if_uge_C_nsw_i7:
1933+
; RV32ZBB: # %bb.0:
1934+
; RV32ZBB-NEXT: ori a0, a0, 51
1935+
; RV32ZBB-NEXT: andi a1, a0, 127
1936+
; RV32ZBB-NEXT: addi a0, a0, 17
1937+
; RV32ZBB-NEXT: andi a0, a0, 92
1938+
; RV32ZBB-NEXT: minu a0, a0, a1
1939+
; RV32ZBB-NEXT: ret
1940+
%x = or i7 %a, 51
1941+
%c = icmp ugt i7 %x, -18
1942+
%add = add nsw i7 %x, 17
1943+
%s = select i1 %c, i7 %add, i7 %x
1944+
ret i7 %s
1945+
}
1946+
1947+
define i7 @sub_if_uge_C_swapped_nsw_i7(i7 %a) {
1948+
; RV32I-LABEL: sub_if_uge_C_swapped_nsw_i7:
1949+
; RV32I: # %bb.0:
1950+
; RV32I-NEXT: ori a0, a0, 51
1951+
; RV32I-NEXT: andi a1, a0, 127
1952+
; RV32I-NEXT: sltiu a1, a1, 111
1953+
; RV32I-NEXT: addi a1, a1, -1
1954+
; RV32I-NEXT: andi a1, a1, 17
1955+
; RV32I-NEXT: add a0, a0, a1
1956+
; RV32I-NEXT: ret
1957+
;
1958+
; RV32ZBB-LABEL: sub_if_uge_C_swapped_nsw_i7:
1959+
; RV32ZBB: # %bb.0:
1960+
; RV32ZBB-NEXT: ori a0, a0, 51
1961+
; RV32ZBB-NEXT: andi a1, a0, 127
1962+
; RV32ZBB-NEXT: addi a0, a0, 17
1963+
; RV32ZBB-NEXT: andi a0, a0, 92
1964+
; RV32ZBB-NEXT: minu a0, a1, a0
1965+
; RV32ZBB-NEXT: ret
1966+
%x = or i7 %a, 51
1967+
%c = icmp ult i7 %x, -17
1968+
%add = add nsw i7 %x, 17
1969+
%s = select i1 %c, i7 %x, i7 %add
1970+
ret i7 %s
1971+
}

llvm/test/CodeGen/RISCV/rv64zbb.ll

+52
Original file line numberDiff line numberDiff line change
@@ -2118,3 +2118,55 @@ define i32 @sub_if_uge_C_swapped_i32(i32 signext %x) {
21182118
%cond = select i1 %cmp, i32 %x, i32 %sub
21192119
ret i32 %cond
21202120
}
2121+
2122+
define i7 @sub_if_uge_C_nsw_i7(i7 %a) {
2123+
; RV64I-LABEL: sub_if_uge_C_nsw_i7:
2124+
; RV64I: # %bb.0:
2125+
; RV64I-NEXT: ori a0, a0, 51
2126+
; RV64I-NEXT: andi a1, a0, 127
2127+
; RV64I-NEXT: sltiu a1, a1, 111
2128+
; RV64I-NEXT: addi a1, a1, -1
2129+
; RV64I-NEXT: andi a1, a1, 17
2130+
; RV64I-NEXT: add a0, a0, a1
2131+
; RV64I-NEXT: ret
2132+
;
2133+
; RV64ZBB-LABEL: sub_if_uge_C_nsw_i7:
2134+
; RV64ZBB: # %bb.0:
2135+
; RV64ZBB-NEXT: ori a0, a0, 51
2136+
; RV64ZBB-NEXT: andi a1, a0, 127
2137+
; RV64ZBB-NEXT: addi a0, a0, 17
2138+
; RV64ZBB-NEXT: andi a0, a0, 92
2139+
; RV64ZBB-NEXT: minu a0, a0, a1
2140+
; RV64ZBB-NEXT: ret
2141+
%x = or i7 %a, 51
2142+
%c = icmp ugt i7 %x, -18
2143+
%add = add nsw i7 %x, 17
2144+
%s = select i1 %c, i7 %add, i7 %x
2145+
ret i7 %s
2146+
}
2147+
2148+
define i7 @sub_if_uge_C_swapped_nsw_i7(i7 %a) {
2149+
; RV64I-LABEL: sub_if_uge_C_swapped_nsw_i7:
2150+
; RV64I: # %bb.0:
2151+
; RV64I-NEXT: ori a0, a0, 51
2152+
; RV64I-NEXT: andi a1, a0, 127
2153+
; RV64I-NEXT: sltiu a1, a1, 111
2154+
; RV64I-NEXT: addi a1, a1, -1
2155+
; RV64I-NEXT: andi a1, a1, 17
2156+
; RV64I-NEXT: add a0, a0, a1
2157+
; RV64I-NEXT: ret
2158+
;
2159+
; RV64ZBB-LABEL: sub_if_uge_C_swapped_nsw_i7:
2160+
; RV64ZBB: # %bb.0:
2161+
; RV64ZBB-NEXT: ori a0, a0, 51
2162+
; RV64ZBB-NEXT: andi a1, a0, 127
2163+
; RV64ZBB-NEXT: addi a0, a0, 17
2164+
; RV64ZBB-NEXT: andi a0, a0, 92
2165+
; RV64ZBB-NEXT: minu a0, a1, a0
2166+
; RV64ZBB-NEXT: ret
2167+
%x = or i7 %a, 51
2168+
%c = icmp ult i7 %x, -17
2169+
%add = add nsw i7 %x, 17
2170+
%s = select i1 %c, i7 %x, i7 %add
2171+
ret i7 %s
2172+
}

0 commit comments

Comments
 (0)
0