Skip to content

instcombine can introduce wrapping into a nuw/nsw operation #11821

@zygoloid

Description

@zygoloid
mannequin
Bugzilla Link 11449
Resolution FIXED
Resolved on Apr 30, 2015 16:13
Version trunk
OS Linux
CC @efriedma-quic,@sunfishcode,@MatzeB,@nlewycky

Extended Description

When instcombine sees an add/sub with nsw/nuw, where the sign bit is not demanded, it does not demand the sign bit in the input. The following IR is misoptimized:

; ModuleID = ''
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define i32 @​_Z1fiii(i32 %a, i32 %b, i32 %c) nounwind {
entry:
%or = or i32 %b, 2147483647
%xor = xor i32 %a, %or
%add = add nsw i32 %xor, %c
%and = and i32 %add, 2147483647
ret i32 %and
}

define i32 @​_Z1gi(i32 %c) nounwind {
entry:
%call = call i32 @​_Z1fiii(i32 -1, i32 -1, i32 %c)
ret i32 %call
}

If we run this through opt -inline -instcombine, we get correct IR:

define i32 @​_Z1gi(i32 %c) nounwind {
entry:
%and.i = and i32 %c, 2147483647
ret i32 %and.i
}

If we run this through opt -instcombine -inline, we get incorrect IR:

define i32 @​_Z1gi(i32 %c) nounwind {
entry:
%add.i = add nsw i32 -2147483648, %c
%and.i = and i32 %add.i, 2147483647
ret i32 %and.i
}

This function produces a trap value for negative %c; the original code did not. Perhaps operators with nsw or nuw should implicitly demand the sign bit from their operands, even if the sign bit of the result is not demanded.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzillaIssues migrated from bugzilla

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions