mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
b23e310c99
This is a patch that disables the poison-unsafe select -> and/or i1 folding. It has been blocking D72396 and also has been the source of a few miscompilations described in llvm.org/pr49688 . D99674 conditionally blocked this folding and successfully fixed the latter one. The former one was still blocked, and this patch addresses it. Note that a few test functions that has `_logical` suffix are now deoptimized. These are created by @nikic to check the impact of disabling this optimization by copying existing original functions and replacing and/or with select. I can see that most of these are poison-unsafe; they can be revived by introducing freeze instruction. I left comments at fcmp + select optimizations (or-fcmp.ll, and-fcmp.ll) because I think they are good targets for freeze fix. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D101191
92 lines
3.8 KiB
LLVM
92 lines
3.8 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt %s -instcombine -S | FileCheck %s
|
|
|
|
declare { i4, i1 } @llvm.umul.with.overflow.i4(i4, i4) #1
|
|
|
|
define i1 @t0_umul(i4 %size, i4 %nmemb) {
|
|
; CHECK-LABEL: @t0_umul(
|
|
; CHECK-NEXT: [[UMUL:%.*]] = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 [[SIZE:%.*]], i4 [[NMEMB:%.*]])
|
|
; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { i4, i1 } [[UMUL]], 1
|
|
; CHECK-NEXT: ret i1 [[UMUL_OV]]
|
|
;
|
|
%cmp = icmp ne i4 %size, 0
|
|
%umul = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 %size, i4 %nmemb)
|
|
%umul.ov = extractvalue { i4, i1 } %umul, 1
|
|
%and = select i1 %umul.ov, i1 %cmp, i1 false
|
|
ret i1 %and
|
|
}
|
|
|
|
define i1 @t1_commutative(i4 %size, i4 %nmemb) {
|
|
; CHECK-LABEL: @t1_commutative(
|
|
; CHECK-NEXT: [[NMEMB_FR:%.*]] = freeze i4 [[NMEMB:%.*]]
|
|
; CHECK-NEXT: [[UMUL:%.*]] = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 [[SIZE:%.*]], i4 [[NMEMB_FR]])
|
|
; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { i4, i1 } [[UMUL]], 1
|
|
; CHECK-NEXT: ret i1 [[UMUL_OV]]
|
|
;
|
|
%cmp = icmp ne i4 %size, 0
|
|
%umul = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 %size, i4 %nmemb)
|
|
%umul.ov = extractvalue { i4, i1 } %umul, 1
|
|
%and = select i1 %cmp, i1 %umul.ov, i1 false ; swapped
|
|
ret i1 %and
|
|
}
|
|
|
|
define i1 @n2_wrong_size(i4 %size0, i4 %size1, i4 %nmemb) {
|
|
; CHECK-LABEL: @n2_wrong_size(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i4 [[SIZE1:%.*]], 0
|
|
; CHECK-NEXT: [[UMUL:%.*]] = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 [[SIZE0:%.*]], i4 [[NMEMB:%.*]])
|
|
; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { i4, i1 } [[UMUL]], 1
|
|
; CHECK-NEXT: [[AND:%.*]] = select i1 [[UMUL_OV]], i1 [[CMP]], i1 false
|
|
; CHECK-NEXT: ret i1 [[AND]]
|
|
;
|
|
%cmp = icmp ne i4 %size1, 0 ; not %size0
|
|
%umul = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 %size0, i4 %nmemb)
|
|
%umul.ov = extractvalue { i4, i1 } %umul, 1
|
|
%and = select i1 %umul.ov, i1 %cmp, i1 false
|
|
ret i1 %and
|
|
}
|
|
|
|
define i1 @n3_wrong_pred(i4 %size, i4 %nmemb) {
|
|
; CHECK-LABEL: @n3_wrong_pred(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i4 [[SIZE:%.*]], 0
|
|
; CHECK-NEXT: [[UMUL:%.*]] = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 [[SIZE]], i4 [[NMEMB:%.*]])
|
|
; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { i4, i1 } [[UMUL]], 1
|
|
; CHECK-NEXT: [[AND:%.*]] = and i1 [[UMUL_OV]], [[CMP]]
|
|
; CHECK-NEXT: ret i1 [[AND]]
|
|
;
|
|
%cmp = icmp eq i4 %size, 0 ; not 'ne'
|
|
%umul = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 %size, i4 %nmemb)
|
|
%umul.ov = extractvalue { i4, i1 } %umul, 1
|
|
%and = select i1 %umul.ov, i1 %cmp, i1 false
|
|
ret i1 %and
|
|
}
|
|
|
|
define i1 @n4_not_and(i4 %size, i4 %nmemb) {
|
|
; CHECK-LABEL: @n4_not_and(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i4 [[SIZE:%.*]], 0
|
|
; CHECK-NEXT: [[UMUL:%.*]] = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 [[SIZE]], i4 [[NMEMB:%.*]])
|
|
; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { i4, i1 } [[UMUL]], 1
|
|
; CHECK-NEXT: [[AND:%.*]] = or i1 [[UMUL_OV]], [[CMP]]
|
|
; CHECK-NEXT: ret i1 [[AND]]
|
|
;
|
|
%cmp = icmp ne i4 %size, 0
|
|
%umul = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 %size, i4 %nmemb)
|
|
%umul.ov = extractvalue { i4, i1 } %umul, 1
|
|
%and = select i1 %umul.ov, i1 true, i1 %cmp ; not 'and'
|
|
ret i1 %and
|
|
}
|
|
|
|
define i1 @n5_not_zero(i4 %size, i4 %nmemb) {
|
|
; CHECK-LABEL: @n5_not_zero(
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i4 [[SIZE:%.*]], 1
|
|
; CHECK-NEXT: [[UMUL:%.*]] = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 [[SIZE]], i4 [[NMEMB:%.*]])
|
|
; CHECK-NEXT: [[UMUL_OV:%.*]] = extractvalue { i4, i1 } [[UMUL]], 1
|
|
; CHECK-NEXT: [[AND:%.*]] = and i1 [[UMUL_OV]], [[CMP]]
|
|
; CHECK-NEXT: ret i1 [[AND]]
|
|
;
|
|
%cmp = icmp ne i4 %size, 1 ; should be '0'
|
|
%umul = tail call { i4, i1 } @llvm.umul.with.overflow.i4(i4 %size, i4 %nmemb)
|
|
%umul.ov = extractvalue { i4, i1 } %umul, 1
|
|
%and = select i1 %umul.ov, i1 %cmp, i1 false
|
|
ret i1 %and
|
|
}
|