| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -passes=instcombine -S | FileCheck %s |
| |
| ; It is a miscompile in most of these tests if we |
| ; execute div/rem without freezing the potentially |
| ; poison condition value. |
| |
| define i5 @sdiv_common_divisor(i1 %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @sdiv_common_divisor( |
| ; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = sdiv i5 [[SEL_V]], [[X:%.*]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = sdiv i5 %y, %x |
| %r2 = sdiv i5 %z, %x |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @srem_common_divisor(i1 %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @srem_common_divisor( |
| ; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = srem i5 [[SEL_V]], [[X:%.*]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = srem i5 %y, %x |
| %r2 = srem i5 %z, %x |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| ; This is ok without freeze because UB can only happen with x==0, |
| ; and that occurs in the original code. |
| |
| define i5 @udiv_common_divisor(i1 %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @udiv_common_divisor( |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = udiv i5 [[SEL_V]], [[X:%.*]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = udiv i5 %y, %x |
| %r2 = udiv i5 %z, %x |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| ; This is ok without freeze because UB can only happen with x==0, |
| ; and that occurs in the original code. |
| |
| define i5 @urem_common_divisor(i1 %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @urem_common_divisor( |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = urem i5 [[SEL_V]], [[X:%.*]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = urem i5 %y, %x |
| %r2 = urem i5 %z, %x |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @sdiv_common_dividend(i1 %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @sdiv_common_dividend( |
| ; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = sdiv i5 [[X:%.*]], [[SEL_V]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = sdiv i5 %x, %y |
| %r2 = sdiv i5 %x, %z |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @srem_common_dividend(i1 %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @srem_common_dividend( |
| ; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = srem i5 [[X:%.*]], [[SEL_V]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = srem i5 %x, %y |
| %r2 = srem i5 %x, %z |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @udiv_common_dividend(i1 %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @udiv_common_dividend( |
| ; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = udiv i5 [[X:%.*]], [[SEL_V]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = udiv i5 %x, %y |
| %r2 = udiv i5 %x, %z |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @urem_common_dividend(i1 %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @urem_common_dividend( |
| ; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]] |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[TMP1]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = urem i5 [[X:%.*]], [[SEL_V]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = urem i5 %x, %y |
| %r2 = urem i5 %x, %z |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| ; Repeat the above tests, but guarantee that the select |
| ; condition is not poison via argument attribute. That |
| ; makes it safe to execute the select before div/rem |
| ; without needing to freeze the condition. |
| |
| define i5 @sdiv_common_divisor_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @sdiv_common_divisor_defined_cond( |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = sdiv i5 [[SEL_V]], [[X:%.*]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = sdiv i5 %y, %x |
| %r2 = sdiv i5 %z, %x |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @srem_common_divisor_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @srem_common_divisor_defined_cond( |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = srem i5 [[SEL_V]], [[X:%.*]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = srem i5 %y, %x |
| %r2 = srem i5 %z, %x |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @udiv_common_divisor_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @udiv_common_divisor_defined_cond( |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = udiv i5 [[SEL_V]], [[X:%.*]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = udiv i5 %y, %x |
| %r2 = udiv i5 %z, %x |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @urem_common_divisor_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @urem_common_divisor_defined_cond( |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = urem i5 [[SEL_V]], [[X:%.*]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = urem i5 %y, %x |
| %r2 = urem i5 %z, %x |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @sdiv_common_dividend_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @sdiv_common_dividend_defined_cond( |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = sdiv i5 [[X:%.*]], [[SEL_V]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = sdiv i5 %x, %y |
| %r2 = sdiv i5 %x, %z |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @srem_common_dividend_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @srem_common_dividend_defined_cond( |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = srem i5 [[X:%.*]], [[SEL_V]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = srem i5 %x, %y |
| %r2 = srem i5 %x, %z |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @udiv_common_dividend_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @udiv_common_dividend_defined_cond( |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = udiv i5 [[X:%.*]], [[SEL_V]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = udiv i5 %x, %y |
| %r2 = udiv i5 %x, %z |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |
| |
| define i5 @urem_common_dividend_defined_cond(i1 noundef %b, i5 %x, i5 %y, i5 %z) { |
| ; CHECK-LABEL: @urem_common_dividend_defined_cond( |
| ; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[B:%.*]], i5 [[Z:%.*]], i5 [[Y:%.*]] |
| ; CHECK-NEXT: [[SEL:%.*]] = urem i5 [[X:%.*]], [[SEL_V]] |
| ; CHECK-NEXT: ret i5 [[SEL]] |
| ; |
| %r1 = urem i5 %x, %y |
| %r2 = urem i5 %x, %z |
| %sel = select i1 %b, i5 %r2, i5 %r1 |
| ret i5 %sel |
| } |