return llvm::any_of(GuardingBranches, AllUsesGuardedByBranch);
}
-static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly) {
- // See whether I has flags that may create poison
- if (const auto *OvOp = dyn_cast<OverflowingBinaryOperator>(Op)) {
- if (OvOp->hasNoSignedWrap() || OvOp->hasNoUnsignedWrap())
- return true;
- }
- if (const auto *ExactOp = dyn_cast<PossiblyExactOperator>(Op))
- if (ExactOp->isExact())
- return true;
- if (const auto *FP = dyn_cast<FPMathOperator>(Op)) {
- auto FMF = FP->getFastMathFlags();
- if (FMF.noNaNs() || FMF.noInfs())
- return true;
+static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
+ bool ConsiderFlags) {
+ if (ConsiderFlags) {
+ // See whether I has flags that may create poison
+ if (const auto *OvOp = dyn_cast<OverflowingBinaryOperator>(Op)) {
+ if (OvOp->hasNoSignedWrap() || OvOp->hasNoUnsignedWrap())
+ return true;
+ }
+ if (const auto *ExactOp = dyn_cast<PossiblyExactOperator>(Op))
+ if (ExactOp->isExact())
+ return true;
+ if (const auto *FP = dyn_cast<FPMathOperator>(Op)) {
+ auto FMF = FP->getFastMathFlags();
+ if (FMF.noNaNs() || FMF.noInfs())
+ return true;
+ }
}
unsigned Opcode = Op->getOpcode();
}
}
-bool llvm::canCreateUndefOrPoison(const Operator *Op) {
- return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/false);
+bool llvm::canCreateUndefOrPoison(const Operator *Op, bool ConsiderFlags) {
+ return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/false, ConsiderFlags);
}
-bool llvm::canCreatePoison(const Operator *Op) {
- return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/true);
+bool llvm::canCreatePoison(const Operator *Op, bool ConsiderFlags) {
+ return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/true, ConsiderFlags);
}
static bool directlyImpliesPoison(const Value *ValAssumedPoison,
define i32 @early_freeze_test3(i32 %v1) {
; CHECK-LABEL: @early_freeze_test3(
-; CHECK-NEXT: [[V2:%.*]] = shl i32 [[V1:%.*]], 1
-; CHECK-NEXT: [[V3:%.*]] = add nuw i32 [[V2]], 2
-; CHECK-NEXT: [[V3_FR:%.*]] = freeze i32 [[V3]]
-; CHECK-NEXT: [[V4:%.*]] = or i32 [[V3_FR]], 1
+; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1:%.*]]
+; CHECK-NEXT: [[V2:%.*]] = shl i32 [[V1_FR]], 1
+; CHECK-NEXT: [[V3:%.*]] = add i32 [[V2]], 2
+; CHECK-NEXT: [[V4:%.*]] = or i32 [[V3]], 1
; CHECK-NEXT: ret i32 [[V4]]
;
%v2 = shl i32 %v1, 1
define i32 @propagate_drop_flags_add(i32 %arg) {
; CHECK-LABEL: @propagate_drop_flags_add(
-; CHECK-NEXT: [[V1:%.*]] = add nuw nsw i32 [[ARG:%.*]], 2
-; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]
-; CHECK-NEXT: ret i32 [[V1_FR]]
+; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
+; CHECK-NEXT: [[V1:%.*]] = add i32 [[ARG_FR]], 2
+; CHECK-NEXT: ret i32 [[V1]]
;
%v1 = add nsw nuw i32 %arg, 2
%v1.fr = freeze i32 %v1
define i32 @propagate_drop_flags_add_foldaway(i32 noundef %arg) {
; CHECK-LABEL: @propagate_drop_flags_add_foldaway(
-; CHECK-NEXT: [[V1:%.*]] = add nuw nsw i32 [[ARG:%.*]], 2
-; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]
-; CHECK-NEXT: ret i32 [[V1_FR]]
+; CHECK-NEXT: [[V1:%.*]] = add i32 [[ARG:%.*]], 2
+; CHECK-NEXT: ret i32 [[V1]]
;
%v1 = add nsw nuw i32 %arg, 2
%v1.fr = freeze i32 %v1
define i32 @propagate_drop_flags_sub(i32 %arg) {
; CHECK-LABEL: @propagate_drop_flags_sub(
-; CHECK-NEXT: [[V1:%.*]] = add nsw i32 [[ARG:%.*]], -2
-; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]
-; CHECK-NEXT: ret i32 [[V1_FR]]
+; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
+; CHECK-NEXT: [[V1:%.*]] = add i32 [[ARG_FR]], -2
+; CHECK-NEXT: ret i32 [[V1]]
;
%v1 = sub nsw nuw i32 %arg, 2
%v1.fr = freeze i32 %v1
define i32 @propagate_drop_flags_mul(i32 %arg) {
; CHECK-LABEL: @propagate_drop_flags_mul(
-; CHECK-NEXT: [[V1:%.*]] = shl nuw nsw i32 [[ARG:%.*]], 1
-; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]
-; CHECK-NEXT: ret i32 [[V1_FR]]
+; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
+; CHECK-NEXT: [[V1:%.*]] = shl i32 [[ARG_FR]], 1
+; CHECK-NEXT: ret i32 [[V1]]
;
%v1 = mul nsw nuw i32 %arg, 2
%v1.fr = freeze i32 %v1
define i32 @propagate_drop_flags_udiv(i32 %arg) {
; CHECK-LABEL: @propagate_drop_flags_udiv(
-; CHECK-NEXT: [[V1:%.*]] = lshr exact i32 [[ARG:%.*]], 1
-; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]
-; CHECK-NEXT: ret i32 [[V1_FR]]
+; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
+; CHECK-NEXT: [[V1:%.*]] = lshr i32 [[ARG_FR]], 1
+; CHECK-NEXT: ret i32 [[V1]]
;
%v1 = udiv exact i32 %arg, 2
%v1.fr = freeze i32 %v1
define i32 @propagate_drop_flags_sdiv(i32 %arg) {
; CHECK-LABEL: @propagate_drop_flags_sdiv(
-; CHECK-NEXT: [[V1:%.*]] = ashr exact i32 [[ARG:%.*]], 1
-; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]
-; CHECK-NEXT: ret i32 [[V1_FR]]
+; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
+; CHECK-NEXT: [[V1:%.*]] = ashr i32 [[ARG_FR]], 1
+; CHECK-NEXT: ret i32 [[V1]]
;
%v1 = sdiv exact i32 %arg, 2
%v1.fr = freeze i32 %v1
define i32 @propagate_drop_shl1(i32 %arg) {
; CHECK-LABEL: @propagate_drop_shl1(
-; CHECK-NEXT: [[V1:%.*]] = shl nuw nsw i32 [[ARG:%.*]], 2
-; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]
-; CHECK-NEXT: ret i32 [[V1_FR]]
+; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
+; CHECK-NEXT: [[V1:%.*]] = shl i32 [[ARG_FR]], 2
+; CHECK-NEXT: ret i32 [[V1]]
;
%v1 = shl nsw nuw i32 %arg, 2
%v1.fr = freeze i32 %v1
define i32 @propagate_drop_ashr1(i32 %arg) {
; CHECK-LABEL: @propagate_drop_ashr1(
-; CHECK-NEXT: [[V1:%.*]] = ashr exact i32 [[ARG:%.*]], 2
-; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]
-; CHECK-NEXT: ret i32 [[V1_FR]]
+; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
+; CHECK-NEXT: [[V1:%.*]] = ashr i32 [[ARG_FR]], 2
+; CHECK-NEXT: ret i32 [[V1]]
;
%v1 = ashr exact i32 %arg, 2
%v1.fr = freeze i32 %v1
define i32 @propagate_drop_lshr1(i32 %arg) {
; CHECK-LABEL: @propagate_drop_lshr1(
-; CHECK-NEXT: [[V1:%.*]] = lshr exact i32 [[ARG:%.*]], 2
-; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]
-; CHECK-NEXT: ret i32 [[V1_FR]]
+; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
+; CHECK-NEXT: [[V1:%.*]] = lshr i32 [[ARG_FR]], 2
+; CHECK-NEXT: ret i32 [[V1]]
;
%v1 = lshr exact i32 %arg, 2
%v1.fr = freeze i32 %v1