diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index b48054bf209..1edbc6921f9 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -88,6 +88,8 @@ line upon naming the release. Refer to previous for appropriate section names. [#8526](https://github.com/microsoft/DirectXShaderCompiler/issues/8526). - Fixed incorrect shader results caused by stale overflow and exactness flags after bit-tracking dead code elimination. +- Fixed an optimizer miscompile where selects of bitwise-not values guarded by + signed less-than or unsigned compares were treated as a signed minimum. ### Upcoming Preview Release diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index d7612998ef2..f42bb0677c5 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -3383,7 +3383,10 @@ static SelectPatternFlavor matchSelectPattern(ICmpInst::Predicate Pred, // Y >s C ? ~Y : ~C == ~Y (FalseVal)) { - if (C1->getType() == C2->getType() && ~C1->getValue() == C2->getValue() && + // HLSL Change - Add missing sgt check. Backport of rL264996 (PR27137): + // https://github.com/llvm/llvm-project/commit/56df0ec61033a5bb49b3620e70cc6a61e26b3e7a + if (Pred == ICmpInst::ICMP_SGT && C1->getType() == C2->getType() && + ~C1->getValue() == C2->getValue() && (match(TrueVal, m_Not(m_Specific(CmpLHS))) || match(CmpLHS, m_Not(m_Specific(TrueVal))))) { LHS = TrueVal; diff --git a/tools/clang/test/DXC/Passes/InstructionCombining/instcombine-select-of-not-minmax.ll b/tools/clang/test/DXC/Passes/InstructionCombining/instcombine-select-of-not-minmax.ll new file mode 100644 index 00000000000..48b00781b28 --- /dev/null +++ b/tools/clang/test/DXC/Passes/InstructionCombining/instcombine-select-of-not-minmax.ll @@ -0,0 +1,28 @@ +; RUN: %dxopt %s -instcombine -S | FileCheck %s + +; Regression test for the backport of +; https://github.com/llvm/llvm-project/commit/56df0ec61033a5bb49b3620e70cc6a61e26b3e7a +; (rL264996), copied unchanged. matchSelectPattern matched (X pred C) ? ~X : ~C +; as smin(~X, ~C) regardless of the predicate, but that only holds for sgt. +; Before the fix, InstCombine folded @PR27137 to 'ret i32 -1', which is wrong +; for negative %a. + +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +define i32 @PR27137(i32 %a) { +; CHECK-LABEL: @PR27137( +; CHECK-NEXT: %not_a = xor i32 %a, -1 +; CHECK-NEXT: %c0 = icmp slt i32 %a, 0 +; CHECK-NEXT: %s0 = select i1 %c0, i32 %not_a, i32 -1 +; CHECK-NEXT: %c1 = icmp sgt i32 %s0, -1 +; CHECK-NEXT: %s1 = select i1 %c1, i32 %s0, i32 -1 +; CHECK-NEXT: ret i32 %s1 + + %not_a = xor i32 %a, -1 + %c0 = icmp slt i32 %a, 0 + %s0 = select i1 %c0, i32 %not_a, i32 -1 + %c1 = icmp sgt i32 %s0, -1 + %s1 = select i1 %c1, i32 %s0, i32 -1 + ret i32 %s1 +}